将 2 个数字相乘,然后求和 [英] Multiply 2 numbers and then sum

查看:39
本文介绍了将 2 个数字相乘,然后求和的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在尝试做一些看起来应该很容易做的事情时遇到了困难.我基本上想将一个节点中的 2 个数字相乘,然后将所有节点的这些数字相加.这是我试过的 XSLT 代码.

I am having a difficult time trying to do something that seems like it should be really easy to do. I basically want to multiply 2 numbers in a node and then sum the total of those numbers for all the nodes. Here is the XSLT code I have tried.

<xsl:value-of select="sum(Parts/Part/Quantity * Parts/Part/Rate)"/>

此代码导致错误消息函数 sum 的参数 1 无法转换为节点集".

This code results in an error that says "Argument 1 of function sum cannot be converted to a node set."

有没有人知道哪里出了问题或者我如何完成我想要做的事情?

Does anyone have an idea of what is wrong or how I can accomplish what I am trying to do?

推荐答案

以下是三种可能的解决方案:

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

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

<parts>
  <part>
        <rate>0.37</rate>
    <quantity>10</quantity>
  </part>
  <part>
        <rate>0.03</rate>
    <quantity>10</quantity>
  </part>
</parts>

想要的结果产生:

4

XSLT 2.0 解决方案使用了这样一个事实:XPath 2.0 允许最后一个正确的参数/"运算符可以是表达式或通常是函数.该表达式/函数应用于迄今为止作为上下文节点选择的每个节点,并且每个函数应用程序产生一个结果.

The XSLT 2.0 solution uses the fact that in XPath 2.0 it is allowed that the right argument of the last "/" operator can be an expression or generally a function. This expression/function is applied for each of the nodes selected so far acting as the context node, and each function application produces one result.

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

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

4

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

This is a typical XSLT 1.0 recursive solution. Do note how the sumProducts template calls itself recursively, until the entire input list, passed in the parameter $pList is processed.

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

当此转换应用于以下 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>

产生正确的结果:

7.5600000000000005

7.5600000000000005

在最后一种情况下,对于每个 sale,我们计算 pricequantity 和所有可用(可变数量) 的乘积折扣-s.

In the last case for each sale we calculate the product of price, quantity and all available (variable number of) discount-s.

FXSL 是高阶函数的纯 XSLT 实现.在这个例子中,高阶函数 f:map() 用于将函数 f:product() 映射到每个 <代码>销售元素.然后将结果相加以产生最终结果.

FXSL is a pure XSLT implementation of higher order functions. In this example the higher-order function f:map() is used to map the function f:product() on the list of children of every sale element. Then the results are summed to produce the final result.

这篇关于将 2 个数字相乘,然后求和的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆