XSL Conditional Totalling
Is it possible to perform conditional totalling in xsl?
I have the following xml sample:
<?xml version="1.0" encoding="utf-8"?>
<export>
<stats set="1">
<columns>
<column id="0">
<sum>100</sum>
</column>
<column id="1">
<sum>102</sum>
</column>
<column id="2">
<sum>12</sum>
</column>
</columns>
</stats>
<stats set="2">
<columns>
<column id="0">
<sum>100</sum>
</column>
<column id="1">
<sum>101</sum>
<开发者_如何学C/column>
<column id="2">
<sum>19</sum>
</column>
</columns>
</stats>
</export>
Is it possible to compute the total of all columns in each stat set where they are not equal to one another? So it would output the following:
Set 1 Set 2 Diff(Set 1 - Set 2)
Total (Diff) 114 120 -6
column 2 102 101 1
column 3 12 19 -7
So in the output column 1 would be omitted as the sum in the two stat sets is the same.
I can get my xsl to output the columns that are different but unsure how to total these up and put in the total row.
Many thanks,
Andez
This transformation (64 lines):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="kColByPosAndVal" match="column"
use="concat(count(preceding-sibling::*),
'+',
sum)"/>
<xsl:key name="kIdByVal" match="column/@id"
use="."/>
<xsl:template match="/*">
<xsl:variable name="vsum1" select=
"sum(stats[@set=1]/*/column
[not(key('kColByPosAndVal',
concat(count(preceding-sibling::*),
'+',
sum)
)[2]
)])"/>
<xsl:variable name="vsum2" select=
"sum(stats[@set=2]/*/column
[not(key('kColByPosAndVal',
concat(count(preceding-sibling::*),
'+',
sum)
)[2]
)])"/>
Set 1 Set 2 Diff(Set 1 - Set 2)
Total (Diff) <xsl:text/>
<xsl:value-of select="$vsum1"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$vsum2"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$vsum1 -$vsum2"/>
<xsl:text>
</xsl:text>
<xsl:for-each select=
"*/*/column/@id
[generate-id()
= generate-id(key('kIdByVal',.)[1])
]
[not(key('kColByPosAndVal',
concat(count(../preceding-sibling::*),
'+',
../sum)
)[2]
)]">
<xsl:variable name="vcolSet1" select=
"/*/stats[@set=1]/*/column[@id=current()]/sum"/>
<xsl:variable name="vcolSet2" select=
"/*/stats[@set=2]/*/column[@id=current()]/sum"/>
Column <xsl:value-of select=".+1"/><xsl:text/>
<xsl:text> </xsl:text>
<xsl:value-of select="$vcolSet1"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$vcolSet2"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$vcolSet1 -$vcolSet2"/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<export>
<stats set="1">
<columns>
<column id="0">
<sum>100</sum>
</column>
<column id="1">
<sum>102</sum>
</column>
<column id="2">
<sum>12</sum>
</column>
</columns>
</stats>
<stats set="2">
<columns>
<column id="0">
<sum>100</sum>
</column>
<column id="1">
<sum>101</sum>
</column>
<column id="2">
<sum>19</sum>
</column>
</columns>
</stats>
</export>
produces the wanted, correct result:
Set 1 Set 2 Diff(Set 1 - Set 2)
Total (Diff) 114 120 -6
Column 2 102 101 1
Column 3 12 19 -7
Explanation:
The key named
kColByPosAndVal
is used to select all columns that have a given position (among allcolumn
siblings) and a given value for theirsum
child-element.The key named
kIdByVal
is used in Muenchian grouping to find all different values for theid
attribute.The two totals are calculated summing only those columns, whose
kColByPosAndVal
key selects only onecolumn
element (if it selects twocolumn
elements, they both are at the same position and have the samesum
).The rest should be easy to understand.
精彩评论