In XSLT 1.0, using FXSL solves the following problems:
<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" exclude-result-prefixes="xsl f ext" > <xsl:import href="zipWith.xsl"/> <xsl:output method="text"/> <xsl:variable name="vMultFun" select="document('')/*/f:mult-func[1]"/> <xsl:template match="/"> <xsl:call-template name="profitForId"/> </xsl:template> <xsl:template name="profitForId"> <xsl:param name="pId" select="1"/> <xsl:variable name="vrtfProducts"> <xsl:call-template name="zipWith"> <xsl:with-param name="pFun" select="$vMultFun"/> <xsl:with-param name="pList1" select="/*/*[@repid = $pId]/@amount"/> <xsl:with-param name="pList2" select="/*/*[@repid = $pId]/@rate"/> </xsl:call-template> </xsl:variable> <xsl:value-of select="sum(ext:node-set($vrtfProducts)/*)"/> </xsl:template> <f:mult-func/> <xsl:template match="f:mult-func" mode="f:FXSL"> <xsl:param name="pArg1"/> <xsl:param name="pArg2"/> <xsl:value-of select="$pArg1 * $pArg2"/> </xsl:template> </xsl:stylesheet>
When this transformation is applied to the originally placed XML source document, the correct result is obtained:
310
In XSLT 2.0, the same solution using FXSL 2.0 can be expressed in a single XPath layer:
sum(f:zipWith(f:multiply(), /*/*[xs:decimal(@repid) eq 1]/@amount/xs:decimal(.), /*/*[xs:decimal(@repid) eq 1]/@rate/xs:decimal(.) ) )
All conversion:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:f="http://fxsl.sf.net/" exclude-result-prefixes="f xs" > <xsl:import href="../f/func-zipWithDVC.xsl"/> <xsl:import href="../f/func-Operators.xsl"/> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:template match="/"> <xsl:value-of select= "sum(f:zipWith(f:multiply(), /*/*[xs:decimal(@repid) eq 1]/@amount/xs:decimal(.), /*/*[xs:decimal(@repid) eq 1]/@rate/xs:decimal(.) ) ) "/> </xsl:template> </xsl:stylesheet>
Again, this conversion gives the correct answer:
310
Please note the following :
The f:zipWith() function accepts the fun() function (of two arguments) and two lists of elements of the same length as arguments. It creates a new list of the same length, the elements of which are the result of the passive use of fun() for the corresponding k -th elements of two lists.
f:zipWith() , as in the expression, takes the function f:multiply() and the two sequences the corresponding attributes " ammount " and " rate ". Sesult is a sequence, each element of which is a product of the corresponding " ammount " and " rate ".
Finally, the sum of this sequence is created.
There is no need to write explicit recursion, and it is also guaranteed that the recursion behind the scenes used in f:zipWith() will never fail (for all practical cases) with a "stack overflow"
Dimitre novatchev
source share