乘积之和
Sum of Multiplied Values
我有一个相当复杂的 XML 文件,我需要使用 XSL 对其中的几个值进行加权平均。我能够完成权重的总和或值的总和,但我无法进行乘法运算。我收到一个错误:
XPTY0004: A sequence of more than one item is not allowed as the first
operand of '*'
我无法分享 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>
这个 Whosebug 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)"/>
要遵循您链接到的那个问题中的示例,您将在 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>
为了完整起见,如果您想在 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 是计算数量的函数。
我有一个相当复杂的 XML 文件,我需要使用 XSL 对其中的几个值进行加权平均。我能够完成权重的总和或值的总和,但我无法进行乘法运算。我收到一个错误:
XPTY0004: A sequence of more than one item is not allowed as the first operand of '*'
我无法分享 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>
这个 Whosebug 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)"/>
要遵循您链接到的那个问题中的示例,您将在 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>
为了完整起见,如果您想在 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 是计算数量的函数。