In XSLT 1.0, you can use the FXSL map() function / template function (and the FXSL sum() function or the standard XPath sum() function) , as shown in the following example:
Availability of this XML document :
<sales> <sale> <price>3.5</price> <quantity>2</quantity> <Discount>0.75</Discount> <Discount>0.80</Discount> <Discount>0.90</Discount> </sale> <sale> <price>3.5</price> <quantity>2</quantity> <Discount>0.75</Discount> <Discount>0.80</Discount> <Discount>0.90</Discount> </sale> </sales>
we want to get the sum from all sales - this is the sum of products: price* quantity * discount1 * discount2 ...* discountN for each sale.
Convert XSLT 1.0 :
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:f="http://fxsl.sf.net/" xmlns:ext="http://exslt.org/common" xmlns:test-map-product="test-map-product" exclude-result-prefixes="xsl f ext test-map-product" > <xsl:import href="sum.xsl"/> <xsl:import href="map.xsl"/> <xsl:import href="product.xsl"/> <test-map-product:test-map-product/> <xsl:output method="text"/> <xsl:template match="/"> <xsl:variable name="vSalesTotals"> <xsl:variable name="vTestMap" select="document('')/*/test-map-product:*[1]"/> <xsl:call-template name="map"> <xsl:with-param name="pFun" select="$vTestMap"/> <xsl:with-param name="pList1" select="/sales/sale"/> </xsl:call-template> </xsl:variable> <xsl:call-template name="sum"> <xsl:with-param name="pList" select="ext:node-set($vSalesTotals)/*"/> </xsl:call-template> </xsl:template> <xsl:template name="makeproduct" mode="f:FXSL" match="test-map-product:*"> <xsl:param name="arg1"/> <xsl:call-template name="product"> <xsl:with-param name="pList" select="$arg1/*"/> </xsl:call-template> </xsl:template> </xsl:stylesheet>
when applied to the above XML document, it creates the desired, correct result :
7.5600000000000005
II. XPath 2.0 Solution :
A simplified task (originally hosted) can be solved using the simple XPath 2.0 single-line interface. If we have this XML document:
<sales> <sale> <price>3.5</price> <quantity>2</quantity> </sale> <sale> <price>3.5</price> <quantity>2</quantity> </sale> </sales>
then this is an XPath 2.0 expression :
sum(/*/sale/(price*quantity))
upon evaluation, creates the desired amount :
14
Here is a confirmation of this fact based on XSLT 2.0:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:template match="/*"> <xsl:sequence select="sum(sale/(price*quantity))"/> </xsl:template> </xsl:stylesheet>
When this conversion is performed in the XML document above, the desired, correct result is obtained :
14