Arnab Halder
Arnab Halder

Reputation: 21

Group by at multiple node at once in xslt

Below is the input xml structure-

<root>
    <Entry>
        <id>id1</id>
        <Line>
            <tax>tax1</tax>
            <amount>13.00</amount>
        </Line>
        <Line>
            <tax>tax2</tax>
            <amount>4.00</amount>
        </Line>
        <Line>
            <tax>tax2</tax>
            <amount>2.00</amount>
        </Line>
        <Line>
            <tax>tax4</tax>
            <amount>8.00</amount>
        </Line>
    </Entry>
    <Entry>
        <id>id1</id>
        <Line>
            <tax>tax2</tax>
            <amount>15.00</amount>
        </Line>
        <Line>
            <tax>tax3</tax>
            <amount>35.00</amount>
        </Line>
    </Entry>
    <Entry>
        <id>id2</id>
        <Line>
            <tax>tax2</tax>
            <amount>12.00</amount>
        </Line>
            <Line>
            <tax>tax2</tax>
            <amount>22.00</amount>
        </Line>
        <Line>
            <tax>tax1</tax>
            <amount>5.00</amount>
        </Line>
    </Entry>        
</root>

I want to get the output as below structure-

id1, tax1,  13.00
id1, tax2,  21.00
id1, tax3,  35.00
id1, tax4,  8.00
id2, tax1,  5.00
id2, tax2,  34.00

I tried to implement the below logic. but it didn't work. forEach Entry groupBy id forEach distinct(id) groupBy tax

Can someone please help me with the xslt transformation?

Upvotes: 0

Views: 101

Answers (1)

Mads Hansen
Mads Hansen

Reputation: 66781

The following XSLT 2.0 stylesheet uses xsl:for-each-group to group the amount by a composite key of their id and tax values concatenated, calculates the sum() of the grouped amount and uses format-number() to ensure two decimal places.

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" />
    
    <xsl:template match="/">
        <xsl:for-each-group select="/root/Entry/Line/amount" group-by="string-join((../../id, ../tax), '-')">
            <xsl:sort select="current-grouping-key()"/>
            <xsl:value-of select="../../id, ../tax, format-number(sum(current-group()), '#.00')" separator=", " />
            <xsl:text>&#10;</xsl:text>
        </xsl:for-each-group>
    </xsl:template>
    
</xsl:stylesheet>

Upvotes: 2

Related Questions