Рассчитать общую сумму корзины в XSLT 1.0 с рекурсией
Я не могу найти ошибку в моей рекурсии. Я надеялся, что ты поможешь мне. Я пытаюсь рассчитать общую стоимость товаров в корзине, но приведенный ниже код дает гораздо более высокий результат, чем ожидалось.
Вот 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 ответ
Ваша рекурсия занимает один <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>