在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