How to number a sorted list in XSLT
I used 开发者_JAVA技巧xsl:sort in apply-templates to sort the elements and I would like to have them also numbered, but if I try to use xsl:number, then it just gives the original position, not the one after sorting. I guess variables can't be used either because they cannot be changed? So how can I correctly number my list?
You can use <xsl:value-of select="position()" />
to get the current position in the loop.
From the xpath spec: The position function returns a number equal to the context position from the expression evaluation context.
XML:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<library>
<book><name>abc</name></book>
<book><name>def</name></book>
<book><name>aaa</name></book>
</library>
XSLT (test.xsl):
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:for-each select="/library/book">
<xsl:sort select="name" data-type="text" />
<xsl:value-of select="position()" />: <xsl:value-of select="name" />,
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
From a comment of the OP:
Oh, that worked! Thank you! I was not using the for-each loop, had
<xsl:apply-templates select="book">
instead. But with for-each it works
Here are two examples, both using <xsl:apply-templates>
-- not <xsl:for-each>
:
<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="/*">
<xsl:apply-templates>
<xsl:sort select=". mod 3"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="num">
<xsl:text>
</xsl:text>
<xsl:value-of select="position()"/>: <xsl:text/>
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the following XML document:
<nums>
<num>01</num>
<num>02</num>
<num>03</num>
<num>04</num>
<num>05</num>
<num>06</num>
<num>07</num>
<num>08</num>
<num>09</num>
<num>10</num>
</nums>
It produces a numbered list of elements, sorted by their remainder when divided by 3:
1: <num>03</num>
2: <num>06</num>
3: <num>09</num>
4: <num>01</num>
5: <num>04</num>
6: <num>07</num>
7: <num>10</num>
8: <num>02</num>
9: <num>05</num>
10: <num>08</num>
The second example is a programming idiom used extensively in XSLT 1.0:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<numsMax>
<xsl:apply-templates>
<xsl:sort data-type="number" order="descending"/>
</xsl:apply-templates>
</numsMax>
</xsl:template>
<xsl:template match="num">
<xsl:if test="position()=1">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the following XML document:
<nums>
<num>07</num>
<num>10</num>
<num>05</num>
<num>02</num>
<num>03</num>
<num>08</num>
<num>04</num>
<num>01</num>
<num>06</num>
<num>09</num>
</nums>
It produces the maximum of all the numbers, using position()=1
on the sorted node-list:
<numsMax>
<num>10</num>
</numsMax>
精彩评论