在XSLT 1.0使用FXSL使得这样的问题易于解决:
<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>
当在最初发布源XML文档被应用于这种转变,正确的结果产生:
在XSLT 2.0中使用相同的解决方案使用FXSL 2.0可以通过一个XPath单行来表达:
sum(f:zipWith(f:multiply(),
/*/*[xs:decimal(@repid) eq 1]/@amount/xs:decimal(.),
/*/*[xs:decimal(@repid) eq 1]/@rate/xs:decimal(.)
)
)
整个变换:
<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"/>
<!-- To be applied on testFunc-zipWith4.xml -->
<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>
同样,这变换产生了正确的答案:
请注意以下:
的f:zipWith()
函数采用作为自变量的函数fun()
(两个参数),并具有相同长度的物品的两个列表。它会生成一个相同长度的新列表,其中的项目是fun()
成对应用于两个列表中相应的k
项目的结果。
f:zipWith()
如在表达式接收功能对应的“ammount
”和“rate
”的f:multiply()
和两个序列属性。该sesult是一个序列,其中每个项目是相应的“ammount
”和“rate
”的产品。
最后,产生该序列的sum。
没有必要写一个明确的递归和它也保证了内f:zipWith()
使用的背后的幕后递归永远不会崩溃(适用于所有实际情况)与“堆栈溢出”
我不知道你可以创建全新的节点,将它分配给一个变量,然后查询它。整洁,谢谢约翰,将测试它。 – staterium 2009-08-26 11:49:27
@Ravish:你不能,直到XSLT 2.0。在1.0中,你需要node-set()扩展函数。 – Tomalak 2009-08-26 12:09:16