使用递归计算XSLT 1.0中的购物车总数

时间:2018-03-10 19:13:43

标签: xslt

我似乎无法在递归中发现错误。我希望你能伸出援助之手。我正在尝试计算购物车中商品的总价格,但下面的代码产生的结果远高于预期。

这是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>

谢谢!我很欣赏任何关于我做错事的提示。

1 个答案:

答案 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>