【问题标题】:XSLT 1.0 adding values together from multiple nodesXSLT 1.0 将多个节点的值加在一起
【发布时间】:2012-09-04 19:45:06
【问题描述】:

假设我有以下 XML

    <A>100</A>
    <B>200</B>
    <C>300</C>

以及以下 XSLT

  <TEST>
    <xsl:value-of select="A + B + C"/>
  </TEST>

它产生以下输出

<TEST>600</TEST>

但是,当其中一个节点为空白时

    <A></A>
    <B>200</B>
    <C>300</C>

我得到以下信息。

<TEST>NaN</TEST>

我只想添加有效数字的节点。如果 xsl 允许我通过添加到已经存在的变量来动态替换变量值,我可以这样做,但即使这样也会很麻烦。我想我想念一个简单的方法吗?

我只想要 XSLT 1.0 的答案。

谢谢!

【问题讨论】:

  • 不是重复的,因为另一个是一个节点名称的总和,这是不同节点的总和。加上那是 xslt 2.0。我要的是 1.0。
  • 当然不是完全相同的副本,但包含有关如何针对空节点进行测试的提示(不特定于 xslt 2.0)。
  • 我已经知道如何使用过滤器来测试空节点。我试图一次测试三个不同节点的问题给了我这个问题。试过 A[.!=''] + B[.!=''] + C[.!=''] 并且有同样的问题。在我看到更好的答案总和(A[.!=''] | B[.!=''] | C[.!=''])之前得到了这个。问题是我的没有测试它是否是一个数字,而且我在一个中使用了三个过滤器。

标签: xslt xslt-1.0


【解决方案1】:
  <TEST>
    <xsl:value-of select="sum((A | B | C)[number(.) = .])"/>
  </TEST>

也就是说,将元素A、B、C的子集相加,这些元素的内容可以用作数字。

请注意,number('') 产生 NaN,而 (NaN = NaN) 为 false,因此这将不包括没有文本内容的元素。

我们测试https://stackoverflow.com/a/3854389/423105 中讨论的数字

【讨论】:

  • 如果没有模式,或者如果模式表明 A、B 和 C 是数字,它将在 XPath 2.0 中工作。您可以将 xs:double 与 xs:untypedAtomic 进行比较。
  • @MichaelKay:嗯。上述错误是我使用 XPath 2.0 在没有关联架构的 XML 文档上收到的。这是在 Oxygen XML Editor 中的 XPath 2.0 评估器中。我想知道是否有一些我不知道的隐藏或默认架构?
  • @LarsH。谢谢我正在寻找这样简单的东西。我有一个解决方案,但它似乎有点矫枉过正和混乱。
  • 对不起,我错了。 [number(.)=.] 表示 [number(.)=xs:double(data(.))],与 number() 不同,xs:double() 不会将 '' 转换为 NaN,它会引发错误.
  • @james31rock:很高兴为您提供帮助。还要考虑 Dimitre 的答案,它更长一些,但对错误更健壮(尤其是在 XPath 2.0 中)。
【解决方案2】:

LarsH 的回答略有不同

sum((A|B|C)[number(.) = number(.)])

谓词中的表达式在 XPath 2.0 中不会导致任何类型错误,因为 = 的两个参数属于同一类型 -- xs:double。

【讨论】:

    【解决方案3】:

    还有:

    对于 XSLT 1.0:

    sum((A|B|C)[string(number())!='NaN'])
    

    对于 XSLT 2.0:

    sum((A,B,C)[string(number())!='NaN'])
    

    出于兴趣,这是另一个。它适用于 XSLT 1.0 和 2.0

    sum((A|B|C)[number()>-99999999])
    

    在上面,将 -99999999 替换为比可能值的下限小一。这是因为 NaN > any-thing 总是返回 false。这可能是迄今为止最有效的解决方案,但它可能看起来有点难看。

    例如,如果您知道 A、B 或 C 都不是负值,您可以输入:

    sum((A|B|C)[number()>0])
    

    ...看起来更干净一些,但仍然可以安静地阅读。

    【讨论】:

      【解决方案4】:
      <xsl:value-of select="sum(/root/*[self::A or self::B or self::C][.!=''])"/>
      

      只要值不为空,这将在“根”元素下添加来自 A、B 和 C 的值。

      【讨论】:

      • 我不想总结其他元素。我特别想要元素 A、B 和 C。
      • 更新它以检查元素名称,尝试新的。
      • 谢谢@Parker。你的答案会奏效,但我选择了 LarsH。还是 +1
      猜你喜欢
      • 2015-03-20
      • 2021-12-05
      • 1970-01-01
      • 2016-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 2020-12-12
      相关资源
      最近更新 更多