Reputation: 13
I would like to reduce a list to distinct elements but count the number of each occurence of that element:
<list>
<entry>A</entry>
<entry>B</entry>
<entry>A</entry>
<entry>A</entry>
<entry>B</entry>
</list>
aimed result:
A - 3 [occurences]
B - 2 [occurences]
I have tried to use
<xsl:value-of select="count()" />
but it either counts all occurences of the "entry" element (5) or the number different "entry" elements (2, being A and B).
My latest try was to combine two for-each loops (never done before), but that doesn't work either:
<xsl:variable name="occurences">
<xsl:for-each select="//entry[not(.=preceding::entry)]">
<xsl:value-of select="count()" />
</xsl:for-each>
</xsl:variable>
<xsl:template match="/">
<xsl:for-each select="//entry">
<p>
<xsl:value-of select="." /> - <xsl:value-of select="$occurences" />
</p>
</xsl:for-each>
</xsl:template>
[An XPath function was called with the wrong number of arguments.]
I'd be grateful for any hint...
Thank you! John
Upvotes: 1
Views: 1433
Reputation: 70648
If you can indeed use XSLT 2.0, you can use the xsl:for-each-group
here, but you need to select entry
elements, not the single list
element, as it is entry elements you wish to group.
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="list">
<table>
<xsl:for-each-group select="entry" group-by=".">
<tr>
<td><xsl:value-of select="."/></td>
<td><xsl:value-of select="count(current-group())"/></td>
</tr>
</xsl:for-each-group>
</table>
</xsl:template>
</xsl:stylesheet>
Alternatively, here is how you would do it with distinct-values
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:key name="entry" match="entry" use="." />
<xsl:variable name="root" select="/" />
<xsl:template match="list">
<table>
<xsl:for-each select="distinct-values(entry)">
<tr>
<td><xsl:value-of select="."/></td>
<td><xsl:value-of select="count(key('entry', ., $root))"/></td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
Note the use of the third parameter in the key
function, as within the loop you are no longer in the context of the main document.
Upvotes: 1