Variable increment in XSLT
i've an xml file like
<node>
<elm val="data1"/>
<elm val="data2"/>
<elm val="data3"/>
<elm val="d开发者_如何学Cata4"/>
<elm val="data5"/>
<elm val="data6"/>
<elm val="data7"/>
</node>
i need to write an xslt for this xml file to display in a table fomat like
1 dat1
2 dat2
3 dat3
4 dat4
5 dat5
6 dat6
7 dat7
please help me to do this
<xsl:tempate match="node">
<table>
<xsl:call-template select="elm"/>
</table>
</xsl:template>
<xsl:template match="elm">
<tr>
<td>
<xsl:value-of select="count(preceding-sibling::elm) + 1"/>
</td>
<td>
<xsl:value-of select="@val"/>
</td>
</tr>
</xsl:template>
Alternatively if the exact ouput is required use the following template for elm
.
<xsl:template match="elm">
<xsl:param name="pos" select="count(preceding-sibling::elm) + 1"/>
<tr>
<td>
<xsl:value-of select="$pos"/>
</td>
<td>
<xsl:text>dat</xsl:text>
<xsl:value-of select="$pos"/>
</td>
</tr>
</xsl:template>
Or in case of text output:
<xsl:tempate match="node">
<xsl:foreach select="elm">
<xsl:value-of select="count(preceding-sibling::elm) + 1"/>
<xsl:text> dat</xsl:text>
<xsl:value-of select="count(preceding-sibling::elm) + 1"/>
<xsl:text disable-output-escaping="yes">&#xA;</xsl:text>
</xsl:foreach>
</xsl:template>
This is wrong:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="elm">
<xsl:value-of select="concat(position(), ' ', @val)"/>
</xsl:template>
</xsl:stylesheet>
When run with many XSLT processors this will produce the following (unwanted) output:
2 data1
4 data2
6 data3
8 data4
10 data5
12 data6
14 data7
The reason is that when templates are applied to the children of the top element, this includes the children that are white-space-only text nodes -- between every two consecutive elm
elements.
So, Oded's solution is wrong.
Here is one correct solution (and one of the shortest possible):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="elm">
<xsl:value-of select="concat(position(), ' ', @val, '
')"/>
</xsl:template>
</xsl:stylesheet>
This transformation produces the correct result:
1 data1
2 data2
3 data3
4 data4
5 data5
6 data6
7 data7
Do note:
The use of the
<xsl:strip-space elements="*"/>
to direct the XSLT processor to discard any white-space-only text nodes.The use of the XPath
concat()
function to glue together the position, the data and the NL character.
You can use the position()
function
<xsl:template match="elm">
<xsl:value-of select="concat(position(), ' ', @val)" />
</xsl:template>
Note: The table format in your example does not match the value of the val
attribute, but I have assumed that you want both to be the same (output of first line should be 1 data1
instead of 1 dat1
.
As @Dimitre Novatchev noted in his answer, this assumes that your original document has no white-space-only nodes. In his answer he deals with this by removing all white-space-only nodes from the input document (using the <xsl:strip-space elements="*"/>
directive) and appending a new line character (

) at the end of the concatenation.
<xsl:template match="node">
<table>
<xsl:apply-templates select="elm"/>
</table>
</xsl:template>
<xsl:template match="elm">
<tr>
<td><xsl:value-of select="position()"/></td>
<td>dat<xsl:value-of select="position()"/></td>
</tr>
</xsl:template>
XSLT "variables" are unvarying variables. Once you set them, you can't arbitrarily change them.
The only hacks around it is to use the position() function and other "+1" functions, but you don't get the flexibility of a true variable.
There are many articles about the unvariability of XSLT "variables".
Quoting article on "http://www.xml.com/pub/a/2001/02/07/trxml9.html"
XSLT variables actually have a lot more in common with constants in many programming languages and are used for a similar purpose.
Counters in XSLT are not possible because XSLT is not a procedural language, it's declarative. To the downvoter: please provide reason. If this is wrong, then please prove otherwise.
精彩评论