Here is source xml. We have 1 header level tag. Line level tags are contained under 1 header level.
<Tran>
<Company>ABC corp</Company>
<Country>IN</Country>
<Line>
<No>1</No>
<Type>Item</Type>
<Amount>100</Amount>
</Line>
<Line>
<No>2</No>
<Type>Item</Type>
<Amount>200</Amount>
</Line>
<Line>
<No>3</No>
<Type>Freight</Type>
<Amount>50</Amount>
</Line>
<Line>
<No>4</No>
<Type>Freight</Type>
<Amount>60</Amount>
</Line>
<Line>
<No>5</No>
<Type>Tax</Type>
<Amount>100</Amount>
</Line>
<Tran>
I would like to group by header level <Company>
and line level <Type>
.
But not sure how to group by xsl.
Expected result is splitting header level by header level and line level . and expected result is here.
<Pmtheader>
<Comp>ABC corp</Comp>
<Type>Item</Type>
<CountLine>2</CountLine>
<TotalAmt>300</TotalAmt>
<Pmtline>
<No>1</No>
<Amt>100</Amt>
</Pmtline>
<Pmtline>
<No>2</No>
<Amt>200</Amt>
</Pmtline>
</Pmtheader>
<Pmtheader>
<Comp>ABC corp</Comp>
<Type>Freight</Type>
<CountLine>2</CountLine>
<TotalAmt>110</TotalAmt>
<Pmtline>
<No>3</No>
<Amt>50</Amt>
</Pmtline>
<Pmtline>
<No>4</No>
<Amt>60</Amt>
</Pmtline>
<Pmtheader>
<Comp>ABC corp</Comp>
<Type>Tax</Type>
<CountLine>1</CountLine>
<TotalAmt>100</TotalAmt>
<Pmtline>
<No>5</No>
<Amt>100</Amt>
</Pmtline>
</Pmtheader>
I never use xsl:for-each-group and for-each function. So I am not sure where I start. Please give me any advise.
Here is an example using XSLT 3:
<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"
expand-text="yes">
<xsl:output method="xml" indent="yes"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="/" name="xsl:initial-template">
<xsl:copy>
<xsl:for-each-group select="//Tran/Line" composite="yes" group-by="../Company, Type">
<Pmtheader>
<Comp>{current-grouping-key()[1]}</Comp>
<Type>{current-grouping-key()[2]}</Type>
<CountLine>{count(current-group())}</CountLine>
<TotalAmt>{sum(current-group()/Amount)}</TotalAmt>
<xsl:apply-templates select="current-group()"/>
</Pmtheader>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="Line">
<Pmtline>
<xsl:apply-templates/>
</Pmtline>
</xsl:template>
<xsl:template match="Line/Type"/>
</xsl:stylesheet>