Search code examples
xsltxslt-2.0xslt-grouping

XSLT 2.0 for-each-group, sum based on parent value


I have tried to get for-each-group to work without success in my xml, I want to group the areas in my refdes-tags ond calculate the sum of the prices per area.

If I have several refdes with the same area under an item it does only count the first one in the sum but I want all to be counted.

Input:

<part>
    <bom>
        <item partnumber="1">
            <refdes area="area1">010</refdes>
            <price>0.5</price>
        </item>
        <item partnumber="2">
            <refdes area="area2">020</refdes>
            <price>1.0</price>
        </item>
        <item partnumber="3">
            <refdes area="area1">030</refdes>
            <refdes area="area1">060</refdes>
            <refdes area="area2">070</refdes>
            <price>0.3</price>
        </item>
    </bom>
</part>

xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" /> 
    <xsl:template match="/">
        <table class="sortable" id="odd">
            <tr>
                <th>Area</th>
                <th>Price</th>
            </tr>
            <xsl:for-each-group select="part/bom/item/refdes" group-by="@area">
                <xsl:sort select="@area" data-type="text" order="ascending"/>
                <xsl:element name="tr">
                    <td>
                        <xsl:value-of select="current-grouping-key()" />
                    </td>
                    <td>
                        <xsl:value-of select="sum(current-group()/../price)" />
                    </td>
                </xsl:element>
            </xsl:for-each-group>
        </table>
    </xsl:template>
</xsl:stylesheet>

Output:

<?xml version="1.0" encoding="UTF-8"?>
<table class="sortable" id="odd">
   <tr>
      <th>Area</th>
      <th>Price</th>
   </tr>
   <tr>
      <td>area1</td>
      <td>0.8</td>
   </tr>
   <tr>
      <td>area2</td>
      <td>1.3</td>
   </tr>
</table>

Wanted output:

<?xml version="1.0" encoding="UTF-8"?>
<table class="sortable" id="odd">
   <tr>
      <th>Area</th>
      <th>Price</th>
   </tr>
   <tr>
      <td>area1</td>
      <td>1.1</td>
   </tr>
   <tr>
      <td>area2</td>
      <td>1.3</td>
   </tr>
</table>

Solution

  • The problem is that for the case where the area attribute is "area1", there are only two price nodes involved. The sum function will not sum the same node more than once. (Change sum to count and you will see it return 2).

    Try changing the statement to this instead

    <xsl:value-of select="sum(for $ref in current-group() return $ref/../price)" />