Reputation: 929
Input XML:
<doc>
<section>
<para>Paragraph 1</para>
<para>Paragraph 2</para>
<para>Paragraph 3</para>
</section>
<para>Paragraph 4</para>
<para>Paragraph 5</para>
<para>Paragraph 6</para>
</doc>
Required output:
<book>
<section>
<p class="para" id="0001">Paragraph 1</p>
<p class="para" id="0002">Paragraph 2</p>
<p class="para" id="0003">Paragraph 3</p>
</section>
<p class="para" id="0004">Paragraph 4</p>
<p class="para" id="0005">Paragraph 5</p>
<p class="para" id="0006">Paragraph 6</p>
</book>
I tried with following XSL but I am not getting desired output. Anyone could help me in this?
<xsl:template match="para">
<xsl:variable name="count" select="position()"/>
<p class="para" id="{$count}">
<xsl:apply-templates/>
</p>
</xsl:template>
The result I am getting is:
<p class="para" id="2">Paragraph 1</p>
<p class="para" id="4">Paragraph 2</p>
<p class="para" id="6">Paragraph 3</p>
<p class="para" id="4">Paragraph 4</p>
<p class="para" id="6">Paragraph 5</p>
<p class="para" id="8">Paragraph 6</p>
Upvotes: 8
Views: 16837
Reputation: 52858
Here's an option that isn't using xsl:for-each
or any xsl:variable
's...
XML Input
<doc>
<section>
<para>Paragraph 1</para>
<para>Paragraph 2</para>
<para>Paragraph 3</para>
</section>
<para>Paragraph 4</para>
<para>Paragraph 5</para>
<para>Paragraph 6</para>
</doc>
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="doc">
<book>
<xsl:apply-templates select="@*|node()"/>
</book>
</xsl:template>
<xsl:template match="para">
<p class="para" id="{format-number(count(preceding::para)+1,'0000')}">
<xsl:apply-templates select="@*|node()"/>
</p>
</xsl:template>
</xsl:stylesheet>
XML Output
<book>
<section>
<p class="para" id="0001">Paragraph 1</p>
<p class="para" id="0002">Paragraph 2</p>
<p class="para" id="0003">Paragraph 3</p>
</section>
<p class="para" id="0004">Paragraph 4</p>
<p class="para" id="0005">Paragraph 5</p>
<p class="para" id="0006">Paragraph 6</p>
</book>
A second option is instead of counting preceding::para
you could use xsl:number
...
<xsl:template match="para">
<p class="para">
<xsl:attribute name="id">
<xsl:number format="0000" level="any"/>
</xsl:attribute>
<xsl:apply-templates select="@*|node()"/>
</p>
</xsl:template>
Upvotes: 16
Reputation: 11298
Here is your required xsl
<xsl:template match="doc">
<book>
<section>
<xsl:for-each select="section/para">
<xsl:variable name="count" select="position()"/>
<xsl:variable name ="seq">
<xsl:value-of select="format-number($count,'0000')"/>
</xsl:variable>
<p class="para" id="{$seq}">
<xsl:value-of select="."/>
</p>
</xsl:for-each>
</section>
<xsl:variable name="secCount" select="count(section/para)"/>
<xsl:for-each select="para">
<xsl:variable name="count" select="position()"/>
<xsl:variable name ="seq">
<xsl:value-of select="format-number( number($count) + number($secCount),'0000')"/>
</xsl:variable>
<p class="para" id="{$seq}">
<xsl:value-of select="."/>
</p>
</xsl:for-each>
</book>
</xsl:template>
Upvotes: 2