В XSLT 1.0 вы можете использовать функцию / шаблон FXSL * map()
(и либо функцию sum()
FXSL, либо стандартную XPath sum()
) , так какпоказано в следующем примере:
Имея этот XML-документ :
<sales>
<sale>
<price>3.5</price>
<quantity>2</quantity>
<Discount>0.75</Discount>
<Discount>0.80</Discount>
<Discount>0.90</Discount>
</sale>
<sale>
<price>3.5</price>
<quantity>2</quantity>
<Discount>0.75</Discount>
<Discount>0.80</Discount>
<Discount>0.90</Discount>
</sale>
</sales>
, мы хотим получить сумму от всех продаж - это суммапродукты: price* quantity * discount1 * discount2 ...* discountN
для каждой продажи.
Это преобразование XSLT 1.0 :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/"
xmlns:ext="http://exslt.org/common"
xmlns:test-map-product="test-map-product"
exclude-result-prefixes="xsl f ext test-map-product"
>
<xsl:import href="sum.xsl"/>
<xsl:import href="map.xsl"/>
<xsl:import href="product.xsl"/>
<!-- This transformation is to be applied on:
salesMap.xml
It contains the code of the "sum of products" from the
article "The Functional Programming Language XSLT"
-->
<test-map-product:test-map-product/>
<xsl:output method="text"/>
<xsl:template match="/">
<!-- Get: map product /sales/sale -->
<xsl:variable name="vSalesTotals">
<xsl:variable name="vTestMap" select="document('')/*/test-map-product:*[1]"/>
<xsl:call-template name="map">
<xsl:with-param name="pFun" select="$vTestMap"/>
<xsl:with-param name="pList1" select="/sales/sale"/>
</xsl:call-template>
</xsl:variable>
<!-- Get sum map product /sales/sale -->
<xsl:call-template name="sum">
<xsl:with-param name="pList" select="ext:node-set($vSalesTotals)/*"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="makeproduct" mode="f:FXSL"
match="test-map-product:*">
<xsl:param name="arg1"/>
<xsl:call-template name="product">
<xsl:with-param name="pList" select="$arg1/*"/>
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>
при применении к вышеуказанному XML-документу создает искомую,правильный результат :
7.5600000000000005
II.Решение XPath 2.0 :
Упрощенная проблема (первоначально опубликованная) может быть решена с помощью простой однострочной XPath 2.0.Если у нас есть этот XML-документ:
<sales>
<sale>
<price>3.5</price>
<quantity>2</quantity>
</sale>
<sale>
<price>3.5</price>
<quantity>2</quantity>
</sale>
</sales>
, то это выражение XPath 2.0 :
sum(/*/sale/(price*quantity))
при оценке выдает требуемую сумму :
14
Вот проверка этого факта на основе XSLT 2.0:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<xsl:sequence select="sum(sale/(price*quantity))"/>
</xsl:template>
</xsl:stylesheet>
Когда это преобразование выполняется над XML-документом выше, желаемый, правильный результат выдается :
14