我使用xml和PHP创建发票管理系统,但最新的PHP版本不支持XSLT 2.0 - 因此我必须寻找sum()替代方案。如何将有效的xslt 2函数“sum(unitprice * quantity)”转换为xslt 1.0?
XML内容基于John's Examples
我尝试使用节点集,但不支持“xmlXPathCompOpEval:找不到函数节点集”
答案 0 :(得分:6)
实际上,sum(price*quantity)
不是有效的XSLT 2.0语法。我想你的意思是“总和($ x in * return $ x / price * $ x / quantity)。
可以通过以下方式对XSLT 1.0中的计算值求和:
两遍解决方案,创建一个节点集,其中节点保存计算值,然后在节点集上求和
递归解决方案:编写一个递归模板,传递总数到参数,为当前节点添加sum *数量,然后递归以处理剩余的节点
高阶解决方案:使用Dimitre Novatchev的FXSL库
扩展解决方案:使用像saxon:sum()
答案 1 :(得分:1)
您只需创建一个模板sumNumbers即可添加两个数量。可以在select语句中执行添加:
<xsl:template name="sumNumbers">
<xsl:param name="num1"/>
<xsl:param name="num2"/>
<xsl:value-of select="$num1 + $num2" />
</xsl:template>
应该有效
答案 2 :(得分:1)
在XSLT 1.0中,您可以使用FXSL的map()
函数/模板(以及FXSL的sum()
函数或标准XPath sum()
)函数< / strong>,如以下示例所示:
拥有此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