在XSLT中实现product()

时间:2014-10-27 00:33:28

标签: xslt

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)。

我尝试了几件事,但他们刚刚破坏了这个功能。有没有办法实现这个目标?是否有可能以更好,更精简的方式实现它(原始函数并不意味着返回单例序列)?

1 个答案:

答案 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>