Search code examples
xmlxsltxpath-2.0

How I can count distinct-values with xslt and XPath 2.0


I want to get a list of distinct values and count the sum of amounts.

my xml is:

<root>
    <orders>
        <fileid>123456789</fileid>
        <order>
            <name>Max Mustermann</name>
            <street>Musterstr. 5</street>
            <zip>12345</zip>
            <city>Munster</city>
            <articles>
                <article>
                    <name>Vase</name>
                    <articlenumber>1234-001</articlenumber>
                    <amount>2</amount>
                </article>
            </articles>
        </order>
        <order>
            <name>Karin Müller</name>
            <street>Hofstr. 25</street>
            <zip>54321</zip>
            <city>Hamburg</city>
            <articles>
                <article>
                    <name>Blumen</name>
                    <articlenumber>4321-003</articlenumber>
                    <amount>10</amount>
                </article>
            </articles>
        </order>
        <order>
            <name>Jenni Schulz</name>
            <street>Achenerstr. 7</street>
            <zip>34567</zip>
            <city>Achen</city>
            <articles>
                <article>
                    <name>Tischdecke</name>
                    <articlenumber>4711-001</articlenumber>
                    <amount>1</amount>
                </article>
                <article>
                    <name>Vase</name>
                    <articlenumber>1234-001</articlenumber>
                    <amount>4</amount>
                </article>
            </articles>
        </order>
    </orders>
</root>

And I want this list:

<articles>
    <article>
        <name>Vase</name>
        <articlenumber>1234-001</articlenumber>
        <amount>6</amount>
    </article>
    <article>
        <name>Blumen</name>
        <articlenumber>4321-003</articlenumber>
        <amount>10</amount>
    </article>
    <article>
        <name>Tischdecke</name>
        <articlenumber>4711-001</articlenumber>
        <amount>1</amount>
    </article>
</articles>

From 3 Orders with 4 articles I want to translate with xslt a list, only with the articles with the sum of all amount in all orders. In this list the articles should distinct. You can see this with the Article "Vase". This is in 2 orders with an amount from 2 and 4. In my target list the Article "Vase" is only one time and with an amount from 6. The sum of all orders.

I read a lot, and could get a distinct list of articlenames or articlenumbers, but everytime I couldn't combine all needed values. Did you have an Idea and could help me? Thank you


Solution

  • With XSLT 2.0 it is a grouping problem to be solved with for-each-group:

    <xsl:template match="/">
      <articles>
        <xsl:for-each-group select="//articles/article" group-by="articlenumber">
          <xsl:copy>
            <xsl:copy-of select="* except amount"/>
            <amount><xsl:value-of select="sum(current-group()/amount)"/></amount>
          </xsl:copy>
       </xsl:for-each-group>
     </articles>
    </xsl:template>
    

    See http://xsltransform.net/3NzcBt8 for a complete sample.