would like to know how to go about creating multiple groupings in XSLT. The following XML should be grouped by memberID, deposit date, and deposit type. The total amount for each member should be summed by date and deposit type.
<?xml version="1.0" encoding="UTF-8"?>
<Report>
<Deposit_Data>
<MemberID>12345</MemberID>
<MemberFirstName>Mickey</MemberFirstName>
<MemberLastName>Mouse</MemberLastName>
<DepositDate>2023-11-22</DepositDate>
<DepositInfo>
<DepositType>CHK</DepositType>
<Amount>50.00</Amount>
</DepositInfo>
<DepositInfo>
<DepositType>SAV</DepositType>
<Amount>30.00</Amount>
</DepositInfo>
</Deposit_Data>
<Deposit_Data>
<MemberID>12345</MemberID>
<MemberFirstName>Mickey</MemberFirstName>
<MemberLastName>Mouse</MemberLastName>
<DepositDate>2023-11-22</DepositDate>
<DepositInfo>
<DepositType>CHK</DepositType>
<Amount>10.00</Amount>
</DepositInfo>
<DepositInfo>
<DepositType>SAV</DepositType>
<Amount>5.00</Amount>
</DepositInfo>
</Deposit_Data>
<Deposit_Data>
<MemberID>12345</MemberID>
<MemberFirstName>Mickey</MemberFirstName>
<MemberLastName>Mouse</MemberLastName>
<DepositDate>2023-12-05</DepositDate>
<DepositInfo>
<DepositType>CHK</DepositType>
<Amount>25.00</Amount>
</DepositInfo>
<DepositInfo>
<DepositType>SAV</DepositType>
<Amount>10.00</Amount>
</DepositInfo>
</Deposit_Data>
<Deposit_Data>
<MemberID>78910</MemberID>
<MemberFirstName>Donald</MemberFirstName>
<MemberLastName>Duck</MemberLastName>
<DepositDate>2023-11-22</DepositDate>
<DepositInfo>
<DepositType>CHK</DepositType>
<Amount>10.00</Amount>
</DepositInfo>
<DepositInfo>
<DepositType>SAV</DepositType>
<Amount>30.00</Amount>
</DepositInfo>
</Deposit_Data>
<Deposit_Data>
<MemberID>78910</MemberID>
<MemberFirstName>Donald</MemberFirstName>
<MemberLastName>Duck</MemberLastName>
<DepositDate>2023-12-05</DepositDate>
<DepositInfo>
<DepositType>CHK</DepositType>
<Amount>20.00</Amount>
</DepositInfo>
<DepositInfo>
<DepositType>SAV</DepositType>
<Amount>10.00</Amount>
</DepositInfo>
</Deposit_Data>
<Deposit_Data>
<MemberID>78910</MemberID>
<MemberFirstName>Donald</MemberFirstName>
<MemberLastName>Duck</MemberLastName>
<DepositDate>2023-12-05</DepositDate>
<DepositInfo>
<DepositType>CHK</DepositType>
<Amount>5.00</Amount>
</DepositInfo>
<DepositInfo>
<DepositType>SAV</DepositType>
<Amount>10.00</Amount>
</DepositInfo>
</Deposit_Data>
The end result should be:
MemberID|DepositDate|DepositType|Amount
12345|2023-11-22|CHK|60
12345|2023-11-22|SAV|35
12345|2023-12-05|CHK|25
12345|2023-12-05|SAV|10
78910|2023-11-22|CHK|10
78910|2023-11-22|SAV|30
78910|2023-12-05|CHK|25
78910|2023-12-05|SAV|20
I tried running with a for-each-group based on the date and deposit type which didn't work. Please see below for the XSLT.
<xsl:template match="Deposit_Data">
<xsl:choose>
<xsl:when test="exists(DepositInfo)">
<xsl:for-each-group select="." group-by="DepositDate">
<xsl:variable name="DepositDateOfCurrentGroup" select="current-grouping-key()"/>
<!-- MemberID --><xsl:value-of select="MemberID"/>
<xsl:value-of select="$vPipeDelimiter"/>
<!-- DepositDate --><xsl:value-of select="format-date($DepositDateOfCurrentGroup,'[Y0001][M01][D01]')"/>
<xsl:value-of select="$vPipeDelimiter"/>
<!-- DepositType -->
<xsl:choose>
<xsl:when test="DepositInfo/DepositType = 'CHK'">
<!-- Amount --><xsl:text>ACCT1</xsl:text>
</xsl:when>
<xsl:when test="DepositInfo/DepositType = 'SAV'">
<!-- Amount --><xsl:text>ACCT2</xsl:text>
</xsl:when>
<xsl:when test="DepositInfo/DepositType = 'CD'">
<!-- Amount --><xsl:text>ACCT3</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text/>
</xsl:otherwise>
</xsl:choose>
<xsl:value-of select="$vPipeDelimiter"/>
<xsl:choose>
<xsl:when test="exists(DepositDate = $DepositDateOfCurrentGroup and DepositInfo/DepositType = 'CHK')">
<xsl:value-of select="format-number(sum(DepositDate[DepositDate = $DepositDateOfCurrentGroup]/Amount),'#######0.00')"/>
</xsl:when>
<xsl:when test="exists([DepositDate = $DepositDateOfCurrentGroup and DepositInfo/DepositType = 'SAV'])">
<xsl:value-of select="format-number(sum(DepositDate[DepositDate = $DepositDateOfCurrentGroup]/Amount),'#######0.00')"/>
</xsl:when>
<xsl:when test="exists(DepositDate = $DepositDateOfCurrentGroup and DepositInfo/DepositType = 'CD')">
<xsl:value-of select="format-number(sum(DepositDate[DepositDate = $DepositDateOfCurrentGroup]/Amount),'#######0.00')"/>
</xsl:when>
<xsl:otherwise>
<xsl:text>0.00</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:value-of select="$vLineFeed"/>
</xsl:for-each-group>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
The end result has no grouping:
MemberID|DepositDate|DepositType|Amount|
12345|20231122|CHK|0.00
12345|20231122|CHK|0.00
12345|20231205|CHK|0.00
78910|20231122|CHK|0.00
78910|20231205|CHK|0.00
78910|20231205|CHK|0.00
Revised XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all">
<xsl:output method="text" />
<xsl:variable name="vPipeDelimiter" select="'|'" />
<xsl:variable name="vLineFeed" select="' '" />
<xsl:variable name="FirstDepositDate">
<xsl:choose>
<xsl:when test="Report/Deposit_Data[DepositDate != ''][1]/DepositDate != ''">
<xsl:value-of select="Report/Deposit_Data[DepositDate != '']/DepositDate"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="format-date(current-date(),'[Y0001]-[M01]-[D01]')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:template match="/">
<xsl:call-template name="header"/>
<xsl:call-template name="Deposit_Data" />
</xsl:template>
<!--Header Template-->
<xsl:template name="header">
<!-- MemberID --><xsl:text>MemberID</xsl:text>
<xsl:value-of select="$vPipeDelimiter"/>
<!-- DepositDate--><xsl:text>DepositDate</xsl:text>
<xsl:value-of select="$vPipeDelimiter"/>
<!-- DepositType --><xsl:text>DepositType</xsl:text>
<xsl:value-of select="$vPipeDelimiter"/>
<!-- Amount --><xsl:text>Amount</xsl:text>
<xsl:value-of select="$vPipeDelimiter"/>
<xsl:value-of select="$vLineFeed"/>
</xsl:template>
<xsl:template name="Deposit_Data">
<xsl:for-each-group select="Report/Deposit_Data" composite="yes" group-by="MemberID, DepositDate">
<xsl:variable name="key" select="current-grouping-key()"/>
<xsl:for-each-group select="current-group()/DepositInfo" group-by="DepositType">
<!-- MemberID --><xsl:value-of select="../MemberID"/>
<xsl:value-of select="$vPipeDelimiter"/>
<!-- MemberID --><xsl:value-of select="../DepositDate"/>
<xsl:value-of select="$vPipeDelimiter"/>
<xsl:choose>
<xsl:when test="DepositType = 'CHK'">
<xsl:value-of select="'ACCT1', sum(current-group()/Amount)" separator="|"/>
</xsl:when>
<xsl:when test="DepositType = 'SAV'">
<xsl:value-of select="'ACCT2', sum(current-group()/Amount)" separator="|"/>
</xsl:when>
<xsl:when test="DepositInfo/DepositType = 'CD'">
<xsl:value-of select="'ACCT3', sum(current-group()/Amount)" separator="|"/>
</xsl:when>
<xsl:otherwise>
<xsl:text/>
</xsl:otherwise>
</xsl:choose>
<xsl:text> </xsl:text>
</xsl:for-each-group>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
Using XSLT 3, you could use
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:for-each-group select="Report/Deposit_Data" composite="yes" group-by="MemberID, DepositDate">
<xsl:variable name="key" select="current-grouping-key()"/>
<xsl:for-each-group select="current-group()/DepositInfo" group-by="DepositType">
<xsl:value-of select="$key, current-grouping-key(), sum(current-group()/Amount)" separator="|"/>
<xsl:text> </xsl:text>
</xsl:for-each-group>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
Or
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:for-each-group select="Report/Deposit_Data/DepositInfo" composite="yes" group-by="../MemberID, ../DepositDate, DepositType">
<xsl:value-of select="current-grouping-key(), sum(current-group()/Amount)" separator="|"/>
<xsl:text> </xsl:text>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>