我试图将所有商品价格的总和乘以他们购买的数量,例如(给定以下内容)......
<item>
<itemPrice>10</itemPrice>
<itemQty>5</itemQty>
</item>
<item>
<itemPrice>5</itemPrice>
<itemQty>7</itemQty>
</item>
我希望总价值85美元。我尝试了以下内容,但不是将每个计算项目购买添加到总变量,而是将所有值连接成一个字符串...
<xsl:template name="itemsTotal">
<xsl:variable name="total" select="0" />
<xsl:for-each select="item">
<xsl:value-of select="$total + (./itemQty * ./itemPrice)" />
</xsl:for-each>
</xsl:template>
获得我想要的东西的最佳途径是什么?我可以对我的模板进行修改吗?
答案 0 :(得分:1)
假设您正在使用XSLT 1.0并假设您的处理器支持EXSLT node-set()函数(几乎可以肯定),并假设我们在您的XML输入示例中添加了一个根元素,并假设您确实希望结果为是10 * 5 + 5 * 7 85 ,而不是 80 ,请尝试以下样式表:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/">
<!-- ... -->
<xsl:variable name="extPrices">
<xsl:for-each select="items/item">
<extPrice>
<xsl:value-of select="itemPrice*itemQty" />
</extPrice>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="subTotal" select="sum(exsl:node-set($extPrices)/extPrice)" />
<subTotal><xsl:value-of select="$subTotal" /></subTotal>
<!-- ... -->
</xsl:template>
</xsl:stylesheet>
应用于更正的输入:
<items>
<item>
<itemPrice>10</itemPrice>
<itemQty>5</itemQty>
</item>
<item>
<itemPrice>5</itemPrice>
<itemQty>7</itemQty>
</item>
</items>
结果是:
<?xml version="1.0" encoding="utf-8"?>
<subTotal>85</subTotal>
答案 1 :(得分:1)
迭代通过XSLT 1.0中的递归来解决。
<xsl:template name="itemTotal">
<xsl:param name="item" select="." />
<xsl:param name="carryOver" select="0" />
<xsl:variable name="runningTotal" select="
$carryOver + $item/itemPrice * $item/itemQty
" />
<xsl:variable name="nextItem" select="$item/following-sibling::item[1]" />
<xsl:choose>
<xsl:when test="not($nextItem)">
<xsl:value-of select="$runningTotal" />
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="itemTotal">
<xsl:with-param name="item" select="$nextItem" />
<xsl:with-param name="carryOver" select="$runningTotal" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
可以像这样调用
<xsl:call-template name="itemTotal">
<xsl:with-param name="item" select="root/item[1]" />
</xsl:call-template>
和输出
85
注释
itemTotal
模板是尾递归的,因此可能会被XSLT处理器优化为循环。在这种情况下,即使对于高<item>
计数,也不会发生堆栈溢出。 following-sibling
)。这适用于您的示例,但可能必须适应其他输入。node-set()
的解决方案,例如michael's answer节目。