我似乎无法在递归中发现错误。我希望你能伸出援助之手。我正在尝试计算购物车中商品的总价格,但下面的代码产生的结果远高于预期。
这是XML:
<products>
<entry id="123">
<price>100</price>
</entry>
<entry id="456">
<price>150</price>
</entry>
</products>
<storage>
<item id="123" count="2" />
<item id="456" count="3" />
</storage>
和XSLT:
<xsl:apply-templates select="products/entry" />
<xsl:template match="products/entry">
<xsl:param name="running-total" select="0"/>
<xsl:variable name="price" select="price" />
<xsl:variable name="quantity" select="storage/item[@id = current()/@id]/@count" />
<xsl:choose>
<xsl:when test="following-sibling::entry[1]">
<xsl:apply-templates select="following-sibling::entry[1]">
<xsl:with-param name="running-total" select="$price * $quantity + $running-total"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$price * $quantity + $running-total"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
谢谢!我很欣赏任何关于我做错事的提示。
答案 0 :(得分:2)
您的递归一次需要一个<entry>
,您需要使用第一个递归,而不是所有。做
<xsl:apply-templates select="products/entry[1]" />
提供正确的输出:
650
另外,正如@ zx485在评论中所说,这个
<xsl:variable name="quantity" select="storage/item[@id = current()/@id]/@count" />
在<entry>
的上下文中工作,所以它不能像那样工作。如果您当前获得/root/storage/item[...]
作为结果,请使用类似NaN
的绝对路径。
话虽如此,您可以稍微简化递归模板:
<xsl:template match="products/entry">
<xsl:param name="running-total" select="0"/>
<xsl:variable name="quantity" select="/root/storage/item[@id = current()/@id]/@count" />
<xsl:apply-templates select="following-sibling::entry[1]">
<xsl:with-param name="running-total" select="price * $quantity + $running-total"/>
</xsl:apply-templates>
<xsl:if test="not(following-sibling::entry)">
<xsl:value-of select="price * $quantity + $running-total"/>
</xsl:if>
</xsl:template>
您也可以使用<xsl:key>
进行更清晰的“数量”查询:
<xsl:key name="quantity" match="storage/item/@count" use="../@id" />
<xsl:template match="products/entry">
<xsl:param name="running-total" select="0"/>
<xsl:variable name="total" select="price * key('quantity', @id) + $running-total" />
<xsl:apply-templates select="following-sibling::entry[1]">
<xsl:with-param name="running-total" select="$total"/>
</xsl:apply-templates>
<xsl:if test="not(following-sibling::entry)">
<xsl:value-of select="$total"/>
</xsl:if>
</xsl:template>