Search code examples
xslt-groupingxslt-3.0

sum of count in xslt-3


Given the following example,

https://xsltfiddle.liberty-development.net/3NzcBsV

each description must occur only once. How one could add in the first row of the output report the number of description elements that have occurred more than once in the xml file under question?

Desired output:

3 (because "Light Belgian waffles covered with an assortment of fresh berries and whipped cream" was found 2 times, and "Two of our famous Belgian Waffles with plenty of real maple [syrup]" was found 3 times, thus 1+2=3 )
02  Light Belgian waffles covered with an assortment of fresh berries and whipped cream 900
04  Light Belgian waffles covered with an assortment of fresh berries and whipped cream 100
01  Two of our famous Belgian Waffles with plenty of real maple [syrup] 650
01  Two of our famous Belgian Waffles with plenty of real maple [syrup] 350
05  Two of our famous Belgian Waffles with plenty of real maple [syrup] 250

Solution

  • Store the grouped elements into a container element and count the items of the different groups (or substract one from that count as you seem to want):

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="3.0">
    
      <xsl:output method="text" />
    
      <xsl:template match="breakfast_menu">
          <xsl:variable name="groups">
              <xsl:for-each-group select="food" group-by="description">
                  <xsl:sort select="current-grouping-key()"/>
                  <xsl:if test="current-group()[2]">
                      <group key="{current-grouping-key()}">
                          <xsl:copy-of select="current-group()"/>
                      </group>
                  </xsl:if>
              </xsl:for-each-group>          
          </xsl:variable>
          <xsl:value-of select="sum($groups/group!(count(food) - 1))"/>
          <xsl:text>&#10;</xsl:text>
          <xsl:apply-templates select="$groups/group/food"/>
      </xsl:template>
    
      <xsl:template match="food">
          <xsl:value-of select="name, description, string(calories)" separator="&#9;"/>
          <xsl:text>&#10;</xsl:text>
      </xsl:template>
    
    </xsl:stylesheet>
    

    https://xsltfiddle.liberty-development.net/3NzcBsV/4