I. Probably one of the simplest solutions :
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="Sal"> <xsl:param name="pSum" select="0"/> <xsl:apply-templates select="following::Sal[1]"> <xsl:with-param name="pSum" select="$pSum + ."/> </xsl:apply-templates> </xsl:template> <xsl:template match="Sal[not(following::Sal)]"> <xsl:param name="pSum" select="0"/> <xsl:value-of select="$pSum + ."/> </xsl:template> <xsl:template match="/"> <xsl:apply-templates select="descendant::Sal[1]"/> </xsl:template> </xsl:stylesheet>
When this conversion is applied to the provided XML document :
<EmpCollection> <Emp> <Name>Sai</Name> <Sal>7000</Sal> </Emp> <Emp> <Name>Nari</Name> <Sal>7400</Sal> </Emp> <Emp> <Name>Hari</Name> <Sal>9000</Sal> </Emp> <Emp> <Name>Suri</Name> <Sal>8900</Sal> </Emp> </EmpCollection>
the desired, correct result is output:
32300
II. A more general solution is to use FXSL 2.x f:foldl() :
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:f="http://fxsl.sf.net/" exclude-result-prefixes="f"> <xsl:import href="../f/func-foldl.xsl"/> <xsl:import href="../f/func-Operators.xsl"/> <xsl:output encoding="UTF-8" omit-xml-declaration="yes"/> <xsl:template match="/"> <xsl:value-of select="f:foldl(f:add(), 0, /*/*/Sal)"/> </xsl:template> </xsl:stylesheet>
When this XSLT 2.0 transformation is applied to the same XML document (see above), the same correct and desired result is obtained :
32300
You can pass any function with two arguments as an argument to f:foldl() and create solutions to various problems .
For example, passing f:mult() instead of f:add() (and changing the argument "zero" to 1 ) results in a salary product:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:f="http://fxsl.sf.net/" exclude-result-prefixes="f"> <xsl:import href="../f/func-foldl.xsl"/> <xsl:import href="../f/func-Operators.xsl"/> <xsl:output encoding="UTF-8" omit-xml-declaration="yes"/> <xsl:template match="/"> <xsl:value-of select="f:foldl(f:mult(), 1, /*/*/Sal)"/> </xsl:template> </xsl:stylesheet>
The result of applying this transformation in the same XML document is now the product of all Sal elements :
4.14918E15
III. In XSLT 3.0 (XPath 3.0), you can use the standard fold-left() or fold-right() in the same way as in the previous solution .