求助:XSLT 1.0递归计算购物车总价结果异常
Hey there! Let's figure out why your recursive XSLT 1.0 calculation is spitting out way higher totals than expected for your shopping cart. Recursion in XSLT can trip you up if you're not careful with node traversal or value accumulation—here are the most common pitfalls to check and fix:
Common Issues & Fixes
1. Accidentally reprocessing the same nodes over and over
This is the #1 culprit for inflated totals. If your recursive template doesn't narrow down the nodes it processes each time, you'll end up adding the same item prices repeatedly (or even infinitely).
Example of problematic code:
<xsl:template name="calculateTotal"> <xsl:param name="items" select="/cart/items/item"/> <xsl:param name="total" select="0"/> <xsl:choose> <xsl:when test="$items"> <!-- Oops: we're adding the price of all items every time, not just one --> <xsl:call-template name="calculateTotal"> <xsl:with-param name="total" select="$total + $items/price"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$total"/> </xsl:otherwise> </xsl:choose> </xsl:template>
Fixed version:
Pass only the remaining unprocessed nodes each time to avoid repeats:
<xsl:template name="calculateTotal"> <xsl:param name="remainingItems" select="/cart/items/item"/> <xsl:param name="currentTotal" select="0"/> <xsl:choose> <xsl:when test="$remainingItems"> <xsl:call-template name="calculateTotal"> <!-- Pass all items except the first one we just processed --> <xsl:with-param name="remainingItems" select="$remainingItems[position() > 1]"/> <!-- Add only the first item's price to the total --> <xsl:with-param name="currentTotal" select="$currentTotal + $remainingItems[1]/price"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$currentTotal"/> </xsl:otherwise> </xsl:choose> </xsl:template>
2. Unintentionally including nested elements or extra text
If your <price> node has child elements (like <price><amount>20</amount></price>) or extra whitespace, directly adding $item/price might sum all nested values or parse unexpected text into numbers.
Fix:
Target the exact value you need explicitly:
<!-- If price has a child amount node --> <xsl:with-param name="currentTotal" select="$currentTotal + $remainingItems[1]/price/amount"/> <!-- Or if price contains raw text, ensure you grab just the text value --> <xsl:with-param name="currentTotal" select="$currentTotal + number($remainingItems[1]/price/text())"/>
3. Forgetting to convert string values to numbers
If your price includes non-numeric characters (like $15 or 15.99 USD), XSLT's automatic type conversion might fail or produce unexpected values.
Fix:
Use number() and translate() to clean and convert the value:
<xsl:with-param name="currentTotal" select="$currentTotal + number(translate($remainingItems[1]/price, '$ ', ''))"/>
4. Missing or incorrect recursion base case
If your template never hits the stop condition (the otherwise branch), it will keep recursing indefinitely, leading to an astronomically high total. Double-check that $remainingItems[position() > 1] will eventually become an empty node set to trigger the stop.
If none of these fix your issue, feel free to share your actual XML and XSLT code—I can pinpoint the exact problem then!
内容的提问来源于stack exchange,提问作者Elizabeta

