乘以值的总和

时间:2015-01-14 19:14:54

标签: xslt

我有一个相当复杂的XML文件,我需要使用XSL对其中的一些值进行加权平均。我能够完成值的权重OR的总和,但我无法使乘法工作。我收到一个错误:

  

XPTY0004:第一个不允许包含多个项目的序列   ' *'

的操作数

我无法共享XML,但我已将XML简化为以下示例(假设有大量的foos):

<group>
<fooList>
    <foo>
        <attributeList>
            <Attribute ID="1" Weight="0.5">
                <otherParams />
            </Attribute>
        </attributeList>
        <Properties>
            <PhysicalProperties>
                <Volume Average="125" Unknown="50" />
            </PhysicalProperties>
        </Properties>
     </foo>
</fooList>
</group>

我目前获得加权平均值的尝试如下:

<xsl:variable name="WeightedVolume" select="sum(/group/fooList/foo[attributeList/Attribute/[@ID=$test_id]]/attributeList/Attribute/@Weight * /group/fooList/foo[attributeList/Attribute/[@ID=$test_id]]/Properties/PhysicalProperties/Volume/@Average)"/>

我知道有类似的问题可用 - 但大多数问题都涉及到汇总和乘法foo等问题

<foo>
    <Weight>0.5</Weight>
    <VolumeAverage>125</VolumeAverage>
</foo>

这个StackOverflow Question的答案对我有吸引力,但我似乎无法使其发挥作用。

我使用Saxonica的Saxon-HE 9.5.1.1N,使用Visual Studio 2013.

被修改 我能够为XSL 2获得一些工作,但需要为XSL1提供支持。

<xsl:variable name="WeightedVolume" select="sum(for $i in /group/FooList/foo[attributeList/Attribute[@ID=$test_id] return $i/AttributeList/Attribute/@Weight * $i/Properties/PhysicalProperties/Volume/@Average)"/>

2 个答案:

答案 0 :(得分:2)

要按照您链接到的问题中的示例,您将在XSLT 2.0 / XPath 2.0中使用它:

<xsl:variable name="FoosToCalculate"
              select="/group/fooList/foo[attributeList/Attribute/@ID = $test_id]" />
<xsl:variable name="WeightedVolume" 
              select="sum($FoosToCalculate/(attributeList/Attribute/@Weight * 
                                 Properties/PhysicalProperties/Volume/@Average)
                          )"/>

在XSLT 1.0中进行此求和涉及更多,并且通常涉及使用递归模板或node-set()函数的某些表现形式。以下是后者的一个例子:

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

  <xsl:template match="/">
    <!-- determine $test_id however you need to -->
    <xsl:variable name="products">
      <xsl:for-each 
           select="/group/fooList/foo[attributeList/Attribute/@ID = $test_id]">
        <product>
          <xsl:value-of select="attributeList/Attribute/@Weight * 
                                Properties/PhysicalProperties/Volume/@Average" />
        </product>
      </xsl:for-each>
    </xsl:variable>

    <xsl:value-of select="sum(ex:node-set($products)/product)"/>
  </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

为了完整性,如果要在XSLT 1.0中对计算数量求和,有三种方法:

(a)递归:编写一个递归模板,逐个处理序列中的项目,计算总数。

(b)创建一个XML树,其中计算的数量是节点值,然后使用sum()函数处理此树。要在单个样式表中执行此操作,您将需要exslt:node-set()扩展函数。

(c)使用XSLT供应商提供的扩展功能,或使用供应商提供的设施进行用户编写以调用外部功能。

在XSLT 2.0中,始终可以使用构造

来完成
sum(for $x in node-set return f($x))

其中f是计算数量的函数。