Search code examples
xsltcountgrouping

Count the number of elements after grouping in XSLT


We have XML:

<?xml version="1.0" encoding="utf-8"?>
<items>
    <element name="Name1" value="Text1"/>   
    <element name="Name1" value="Text3"/>
    <element name="Name1" value="Text4"/>   
    <element name="Name3" value="Text5"/>   
    <element name="Name3" value="Text8"/>   
</items>

We need to group elements by name and count their number. Output XML:

<?xml version="1.0"?>
<goods>
    <group name="Name1" sum="3">
        <item>Text1</item>
        <item>Text3</item>
        <item>Text4</item>
    </group>
    
    </group>
    <group name="Name3" sum="2">
        <item>Text5</item>
        <item>Text8</item>
    </group>
</goods>

I use for it the Munch grouping.

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:key name="PC" match="element" use="@name"/>    
    <xsl:template match="items">
        <goods>
            <xsl:apply-templates select="element[generate-id(.) = generate-id(key('PC',@name))]"/>          
        </goods>
    </xsl:template>
    
    <xsl:template match="element">
        <group name="{@name}">
            <xsl:for-each select="key('PC',@name)">
                <item>
                    <xsl:value-of select="@value"/>
                </item>
            </xsl:for-each>         
        </group>
    </xsl:template>     
</xsl:stylesheet>

But don't know how to count the number of elements after grouping.


Solution

  • Just use count() on the key().

    Example...

    <xsl:template match="element">
        <group name="{@name}" sum="{count(key('PC',@name))}">
            <xsl:for-each select="key('PC',@name)">
                <item>
                    <xsl:value-of select="@value"/>
                </item>
            </xsl:for-each>         
        </group>
    </xsl:template>