乘以2个数字然后求和

10 xslt xslt-2.0 xslt-1.0

我正在努力做一些似乎应该很容易做的事情.我基本上想要在一个节点中乘以2个数字,然后将所有节点的总数加起来.这是我尝试过的XSLT代码.

<xsl:value-of select="sum(Parts/Part/Quantity * Parts/Part/Rate)"/>
Run Code Online (Sandbox Code Playgroud)

此代码导致出现"函数和的参数1无法转换为节点集"的错误.

有没有人知道什么是错的或我怎么能完成我想要做的事情?

Dim*_*hev 38

这有三种可能的解决方案:

Solution1 XSLT2:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

    <xsl:template match="/">
      <xsl:sequence select="sum(/*/*/(rate * quantity))"/>
    </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

将此转换应用于以下XML文档时:

<parts>
  <part>
        <rate>0.37</rate>
    <quantity>10</quantity>
  </part>
  <part>
        <rate>0.03</rate>
    <quantity>10</quantity>
  </part>
</parts>
Run Code Online (Sandbox Code Playgroud)

产生了想要的结果:

4

XSLT 2.0解决方案使用的是,在实际上的XPath 2.0是允许的最后一个"/"运算符的右参数可以是一个表达式或一般的功能.此表达式/函数应用于到目前为止所选择的每个节点充当上下文节点,并且每个函数应用程序生成一个结果.

Solution2 XSLT 1.0:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

    <xsl:template match="/">
      <xsl:call-template name="sumProducts">
        <xsl:with-param name="pList" select="*/*"/>
      </xsl:call-template>
    </xsl:template>

    <xsl:template name="sumProducts">
        <xsl:param name="pList"/>
        <xsl:param name="pAccum" select="0"/>

        <xsl:choose>
          <xsl:when test="$pList">
            <xsl:variable name="vHead" select="$pList[1]"/>

            <xsl:call-template name="sumProducts">
              <xsl:with-param name="pList" select="$pList[position() > 1]"/>
              <xsl:with-param name="pAccum"
               select="$pAccum + $vHead/rate * $vHead/quantity"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$pAccum"/>
          </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

应用于上述XML文档时,会生成正确的结果:

4

这是典型的XSLT 1.0递归解决方案.请注意sumProducts模板如何递归调用自身,直到$pList处理完参数传递的整个输入列表.

Solution3 FXSL(XSLT 1.0):

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common"
xmlns:test-map-product="test-map-product"
exclude-result-prefixes="xsl 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" match="*[namespace-uri() = '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>
Run Code Online (Sandbox Code Playgroud)

将此转换应用于以下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>
Run Code Online (Sandbox Code Playgroud)

产生了正确的结果:

7.5600000000000005

在每个最后一种情况下sale,我们计算的产品price,quantity以及所有可用的(可变数量的)discount-s.

FXSL 是高阶函数的纯XSLT实现.在此示例中,高阶函数f:map()用于f:product()在每个sale元素的子元素列表上映射函数.然后将结果相加以产生最终结果.