K Soze
K Soze

Reputation: 163

How to transform this xml with xslt?

I have the following XML:

<dev>
    <niv1>
        <int>blablabla</int>
        <auteur>blablabla</auteur>
        <exer>
            <p align="justif">blablabla</p>
        </exer>
    </niv1>
    <sign>M. A.</sign>
    <p align="justif">
        <pc>blablabla</pc>: blablabla2
    </p>

    <niv1>
        <int>blablabla</int>
        <auteur>blablabla</auteur>
        <exer>
            <p align="justif">blablabla</p>
        </exer>
    </niv1>
    <sign>M. A.</sign>
    <p align="justif">
        <pc>blablabla</pc>: blablabla2
    </p>
    <!--Same pattern over and over again-->
</dev>

I would like to have something like

<article>
  <content>
    <div>
       <some tags>xxxx</some tags>
    </div>
    <span class="sign">xxx</span>
     <p class="ref">
        <p class="mini-caps">xxxx</p>: 
     </p>
   </content>
</article>

The xml output I have for now looks like this:

<article>
  <content>
    <div>
       <some tags>xxxx</some tags>
    </div>
   </content>
</article>
<span class="sign">xxx</span>
<p class="ref">
      <p class="mini-caps">xxxx</p>: 
</p>

I can't manage to put the last span and p elements in content tag.

My XSLT is something like (not the all file here):

<xsl:template match="niv1">
    <article>
        <content>
            <div>
                <xsl:apply-templates mode="content"/>
            </div>
            <xsl:apply-templates select="sign"/>
        </content>
    </article>
</xsl:template>

<xsl:template match="sign">
    <span class="sign">
        <xsl:apply-templates/>
    </span>
</xsl:template>

<xsl:template match="p">
    <p class="ref">
        <xsl:apply-templates/>
    </p>
</xsl:template>

<xsl:template match="pc">
    <p class="mini-caps">
        <xsl:apply-templates/>
    </p>
</xsl:template>

I don't know if it is possible to achieve what I want since when I match <niv1>, <sign> and <p> are not child nodes of niv1. I don't use XSLT often and I am pretty a beginner.

Upvotes: 0

Views: 31

Answers (1)

Aniket V
Aniket V

Reputation: 3247

There are couple of changes that you would need to do in order to move the siblings sign and p as children of niv1.

Modify the template matching niv1 as below. In this template the 1st occurrence of siblings sign and p following niv1 have been made its children using a mode so that the siblings can be removed later.

<xsl:template match="niv1">
    <article>
        <content>
            <div>
                <xsl:apply-templates mode="content"/>
            </div>
            <xsl:apply-templates select="following-sibling::sign[1]" mode="alter-sign" />
            <xsl:apply-templates select="following-sibling::p[1]" mode="alter-p" />
        </content>
    </article>
</xsl:template>

A mode is applied to the below templates

<xsl:template match="sign" mode="alter-sign">
    <span class="sign">
        <xsl:apply-templates />
    </span>
</xsl:template>

<xsl:template match="p" mode="alter-p">
    <p class="ref">
        <xsl:apply-templates />
    </p>
</xsl:template>

Any other occurrence of sign and p are removed.

<xsl:template match="sign | p" />

These changes provide the following output (since there are 2 occurrences of niv1 in shared input, the output shows 2 article nodes).

<article>
    <content>
        <div>blablablablablablablablabla</div>
        <span class="sign">M. A.</span>
        <p class="ref">
            <p class="mini-caps">blablabla</p>  : blablabla2
        </p>
    </content>
</article>
<article>
    <content>
        <div>blablablablablablablablabla</div>
        <span class="sign">M. A.</span>
        <p class="ref">
            <p class="mini-caps">blablabla</p>  : blablabla2
        </p>
    </content>
</article>

Upvotes: 1

Related Questions