Search code examples
xslt-1.0xslt-grouping

Want to sum the key quantities of each line recursively in XSLT


I have done few calculations using key-match for each line and i am expecting to sum the total of these values at the last row. Below is the calculation.

LINE#1

4 (DispatchQuantity = 2; occurrence = 2 -> 2 x 2 = 4)      MID-LAYER          12   (UnitNetWeight = 3KG x 12)
4 (DispatchQuantity = 2; occurrence = 2 -> 2 x 2 = 4)      PALLET-LAYER       12   (UnitNetWeight = 3KG x 12)

LINE#2

8 (DispatchQuantity = 4; occurrence = 2 -> 4 x 2 = 8)      MID-LAYER          24   (UnitNetWeight = 3KG x 8)

I need to add the numbers of each line to produce one last block which should contains 16 (4+4+8) and 48(12+12+24)

current o/p:
4 MID-LAYER 12
4 PALLET-LAYER 12
8 MID-LAYER 24

XML:

<?xml version="1.0" encoding="UTF-8"?>
<cXML payloadID="16314uu19eii6-765h52u1pp0.162.97.178" timestamp="2021-10-06T02:54:24-07:00" version="1.2.051" xml:lang="en-PL">
      <Header>
            <Line>
                <Items>
                    <Item>
                        <Dimension type="unitNetWeight" quantity="3.0"/>
                        <Code>One</Code>
                        <CodeIdentifier>MID-LAYER</CodeIdentifier>
                        <DispatchQuantity quantity="2.0"/>
                    </Item>
                    <Item>
                        <Dimension type="unitNetWeight" quantity="3.0"/>
                        <Code>auxiliary</Code>
                        <CodeIdentifier>MID-LAYER</CodeIdentifier>
                        <DispatchQuantity quantity="2.0"/>
                    </Item>
                    <Item>
                        <Dimension type="unitNetWeight" quantity="3.0"/>
                        <Code>auxiliary</Code>
                        <CodeIdentifier>MID-LAYER</CodeIdentifier>
                        <DispatchQuantity quantity="2.0"/>
                    </Item>
                    <Item>
                        <Dimension type="unitNetWeight" quantity="3.0"/>
                        <Code>auxiliary</Code>
                        <CodeIdentifier>PALLET-LAYER</CodeIdentifier>
                        <DispatchQuantity quantity="2.0"/>
                    </Item>
                    <Item>
                        <Dimension type="unitNetWeight" quantity="3.0"/>
                        <Code>auxiliary</Code>
                        <CodeIdentifier>PALLET-LAYER</CodeIdentifier>
                        <DispatchQuantity quantity="2.0"/>
                    </Item>
            </Items>
            <Items>
                    
                    <Item>
                        <Dimension type="unitNetWeight" quantity="3.0"/>
                        <Code>auxiliary</Code>
                        <CodeIdentifier>MID-LAYER</CodeIdentifier>
                        <DispatchQuantity quantity="4.0"/>
                    </Item>
                    <Item>
                        <Dimension type="unitNetWeight" quantity="3.0"/>
                        <Code>auxiliary</Code>
                        <CodeIdentifier>MID-LAYER</CodeIdentifier>
                        <DispatchQuantity quantity="4.0"/>
                    </Item>
                    
          </Items>
      </Line>
   </Header>
   </cXML>

Code:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" 
    xmlns:fo="http://www.w3.org/1999/XSL/Format"
    xmlns:date="http://exslt.org/dates-and-times"
    extension-element-prefixes="date"
    >
    
    <!--unique key-->
    <xsl:key name="aux" match="Item[Code='auxiliary']" use="concat(CodeIdentifier, '|', generate-id(..))"/>
    
    <xsl:decimal-format name="generalFormat" grouping-separator="," decimal-separator="." /> 
    <xsl:output method="xml" indent="yes" />
    
    <xsl:template match="/" name="Barcode">
        
        <fo:root>
            <fo:layout-master-set>
                <fo:simple-page-master master-name="ManufacturLabelSize-first" page-height="297mm" page-width="210mm"  margin-top="25.4mm" margin-right="25.4mm" margin-left="25.4mm" margin-bottom="25.4mm">
                    <fo:region-body margin-top="15mm" />
                    <fo:region-before />
                    <fo:region-after />
                </fo:simple-page-master>
            </fo:layout-master-set>
            
            <fo:page-sequence master-reference="ManufacturLabelSize-first" id="pSeqID">
                
                <fo:flow flow-name="xsl-region-body">
                    
                    <fo:table>
                        
                        <fo:table-body border="solid" border-width="0.5pt">
                            <xsl:for-each select="cXML/Header/Line">
                                <xsl:for-each select="Items">
                                <fo:table-row>
                                    <fo:table-cell>
                                        <!--DispatchQuantity*occurence-->
                                        <fo:block>
                                            <xsl:for-each select="Item[Code='auxiliary'][count(. | key('aux', concat(CodeIdentifier, '|', generate-id(..)))[1]) = 1]">
                                                <fo:block >
                                                    <xsl:value-of select="(DispatchQuantity/@quantity) * count(key('aux', concat(CodeIdentifier, '|', generate-id(..))))"/>
                                                </fo:block>
                                            </xsl:for-each>
                                        </fo:block>
                                    </fo:table-cell>
                                    
                                    <fo:table-cell>
                                        <!--unique code-->
                                        <fo:block>
                                            <xsl:for-each select="Item[Code='auxiliary'][count(. | key('aux', concat(CodeIdentifier, '|', generate-id(..)))[1]) = 1]"> 
                                                <fo:block >
                                                    <xsl:value-of select="CodeIdentifier"/>
                                                </fo:block>
                                            </xsl:for-each>
                                        </fo:block>
                                    </fo:table-cell>
                                    
                                    <fo:table-cell>
                                        <!--(DispatchQuantity*occurence)*UnitNetWeight-->
                                        <fo:block>
                                            <xsl:for-each select="Item[Code='auxiliary'][count(. | key('aux', concat(CodeIdentifier, '|', generate-id(..)))[1]) = 1]">
                                                 <fo:block font-size="8" font-family="Calibri" padding-before="2mm" start-indent="0.75mm">
                                                    <xsl:value-of select="(DispatchQuantity/@quantity) * count(key('aux', concat(CodeIdentifier, '|', generate-id(..)))) * Dimension[@type='unitNetWeight']/@quantity"/>
                                                </fo:block>
                                                
                                            </xsl:for-each>
                                        </fo:block>
                                    </fo:table-cell>
                                </fo:table-row>
                            </xsl:for-each>
                            </xsl:for-each>
                            
                        </fo:table-body>          
                    </fo:table> 
                </fo:flow>
            </fo:page-sequence>
        </fo:root>
        
    </xsl:template>
    
    
    
</xsl:stylesheet>

Your kind help is much valued!


Solution

  • Consider this simplified example:

    XSLT 1.0 (+EXSLT node-set() function)

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:exsl="http://exslt.org/common"
    extension-element-prefixes="exsl">
    <xsl:output method="text" encoding="UTF-8"/>
    
    <xsl:key name="aux" match="Item[Code='auxiliary']" use="concat(CodeIdentifier, '|', generate-id(..))"/>
    
    <xsl:template match="cXML">
    
        <xsl:variable name="groups-RTF">
            <xsl:for-each select="//Item[Code='auxiliary'][count(. | key('aux', concat(CodeIdentifier, '|', generate-id(..)))[1]) = 1]"> 
                <group code="{CodeIdentifier}">
                    <xsl:variable name="group-size" select="count(key('aux', concat(CodeIdentifier, '|', generate-id(..))))"/>
                    <xsl:variable name="quantity" select="DispatchQuantity/@quantity * $group-size"/>
                    <quantity>
                        <xsl:value-of select="$quantity"/>
                    </quantity>
                    <weight>
                        <xsl:value-of select="Dimension[@type='unitNetWeight']/@quantity * $quantity"/>
                    </weight>
                </group>
            </xsl:for-each>
        </xsl:variable>
        
        <xsl:variable name="groups" select="exsl:node-set($groups-RTF)/group" />    
    
        <!-- output -->
        <xsl:text>code, quantity, weight&#10;</xsl:text>
        <xsl:for-each select="$groups">
            <xsl:value-of select="@code"/>
            <xsl:text>, </xsl:text>
            <xsl:value-of select="quantity"/>
            <xsl:text>, </xsl:text>
            <xsl:value-of select="weight"/>
            <xsl:text>&#10;</xsl:text>
        </xsl:for-each>
        <xsl:text>TOTAL, </xsl:text>
        <xsl:value-of select="sum($groups/quantity)"/>
        <xsl:text>, </xsl:text>
        <xsl:value-of select="sum($groups/weight)"/>
    </xsl:template>
    
    </xsl:stylesheet>
    

    Result

    code, quantity, weight
    MID-LAYER, 4, 12
    PALLET-LAYER, 4, 12
    MID-LAYER, 8, 24
    TOTAL, 16, 48