XPath 2.0(和3.0)具有方便的聚合函数sum()和avg(),但没有任何返回数值原子值序列的乘积。
虽然在允许赋值语句的语言中实现这样的函数是微不足道的,但在XSLT中似乎并不那么容易。我发现获得聚合产品的唯一方法是使用递归:
<xsl:function name="fn:products">
<xsl:param name="input" />
<xsl:param name="total" />
<xsl:if test="exists($input)">
<xsl:variable name="x" select="$input[1] * $total"/>
<xsl:sequence select="$x"/>
<xsl:sequence select="fn:products(subsequence($input,2),$x)"/>
</xsl:if>
</xsl:function>
但上面的内容实际上是我对Michael Kay的书XSLT 2.0和XPath 2.0第4版的p.994中出现的功能的改编。原始函数通过递归地添加一系列数字来输出一系列运行余额。
我的版本只是将数字相乘,而不是添加它们。结果是一系列正在运行的产品&#34;。例如,fn:products((4,0.75,10,0.7),1)返回序列4,3,30,21。
由于我只对所有数字的乘积感兴趣,所以我只使用过滤器表达式输出输出的最后一项:fn:products((4,0.75,10,0.7),1)[last ()]。
有效。但只是为了制作好的代码,我想知道是否有办法让函数直接将最后一项作为聚合产品返回(即在上面的例子中只得到21)。
我尝试了几件事,但他们刚刚破坏了这个功能。有没有办法实现这个目标?是否有可能以更好,更精简的方式实现它(原始函数并不意味着返回单例序列)?
答案 0 :(得分:1)
如果你使用其中一个花哨的处理器,你可以使用dyn:evaluate。
<?xml version="1.0" encoding="UTF-8"?>
<test>
<num>4</num>
<num>0.75</num>
<num>10</num>
<num>0.7</num>
</test>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dyn="http://exslt.org/dyn/dyn.xml"
extension-element-prefixes="dyn"
>
<xsl:template match="/">
<xsl:variable name="run">
<xsl:for-each select="test/num"><xsl:value-of select="."/><xsl:if test="position() != last()"> * </xsl:if></xsl:for-each>
</xsl:variable>
<xsl:value-of select="dyn:evaluate(string($run))"/>
</xsl:template >
</xsl:stylesheet>