Xslt 1 and the sum function

I am creating an account management system using xml and PHP, but the latest version of PHP does not support XSLT 2.0 - so I should look for an alternative to sum (). How to convert the actual xslt 2 function "sum (unitprice * quantity)" to xslt 1.0?

XML Material Based on "Examples"

I tried it using node-set, but it is not supported "xmlXPathCompOpEval: function node-set not found in"

+2
source share
3 answers

Actually, sum(price*quantity) not valid with XSLT 2.0 syntax. I assume you mean something like `sum (for $ x in * return $ x / price * $ x / quantity).

Summation over a calculated value in XSLT 1.0 can be done in the following ways:

  • two-pass solution, create a node-set in which the nodes store the calculated values, then sum over the node-set

  • Recursive solution: write a recursive template that passes the total value as a parameter, adds the sum of the sum for the current node, and then recurses to process the remaining nodes

  • higher order solution: use the FXSL Dimitre Novatchev library

  • extension: use extension functions like saxon: sum ()

+6
source

You can simply create a sumNumbers template that adds two values. Addition can be performed in the select statement:

 <xsl:template name="sumNumbers"> <xsl:param name="num1"/> <xsl:param name="num2"/> <xsl:value-of select="$num1 + $num2" /> </xsl:template> 

must work

+1
source

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"/> <!-- This transformation is to be applied on: salesMap.xml It contains the code of the "sum of products" from the article "The Functional Programming Language XSLT" --> <test-map-product:test-map-product/> <xsl:output method="text"/> <xsl:template match="/"> <!-- Get: map product /sales/sale --> <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> <!-- Get sum map product /sales/sale --> <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 
+1
source

Source: https://habr.com/ru/post/1390889/


All Articles