如何在XSLT中对几个节点的值求和

时间:2010-01-29 12:32:15

标签: xml xslt

我需要一个循环到特定节点position()和这些节点的总和。例如:

  • 如果我的位置是2,那么节点[1] +节点[2]
  • 如果我的位置是5,则节点[1] +节点[2] +节点[3] +节点[4] +节点[5]

如何在XSLT中完成?

有以下xml

<?xml-stylesheet type="text/xsl" href="sum.xsl"?><root><FIDetail Node1="5" Node2="2" Node3="9" Node4="5" Node5="1" Node6="6" Node7="5" Node8="5" Node9="12" Node10="6" Node11="4" Node12="8" Node13="4" Node14="6" Node15="5" Node16="6" Node17="2" Node18="7" Node19="4" Node20="5" Node21="4" Node22="6" Node23="4" Node24="11" Node25="5" Node26="1" Node27="7" Node28="1" Node29="4" Node30="2" Node31="5" Node32="2" Node33="6" Node34="4" Node35="7" Node36="7" Node37="9" Node38="10" Node39="3" Node40="8" Node41="8" Node42="5" Node43="5" Node44="2" Node45="5" Node46="12" Node47="9" Node48="14" Node49="18" Node50="1"/></root>

我正在尝试将输出显示如下

节点1的总和

Node1 + Node2的总和

节点1 +节点2 +节点3的总和

.... Node1 + ... + Node50的总和

任何人请帮助我XSL

不工作xsl如下

<?xml version="1.0" encoding="UTF-8"?>

         

    <xsl:for-each select="//FIDetail/@*">
        <br/>
        <xsl:value-of select="sum(preceding-sibling::*) + ."/>
        =
        <xsl:for-each select="preceding-sibling::*">
            <xsl:value-of select="name()"/> +
        </xsl:for-each>
        <xsl:value-of select="name()"/>
    </xsl:for-each>

</xsl:template>

3 个答案:

答案 0 :(得分:3)

上下文节点和前一个兄弟节点之和的XPath查询是. + sum(./preceding-sibling::*)

E.g。如果您有以下XML ...

<a>
   <b id="a">1</b>
   <b id="b">2</b>
   <b id="c">3</b>
   <b id="d">4</b>
   <b id="e">5</b>
   <b id="f">6</b>
</a>

...您可以使用表达式

获取id =“c”的节点和前面的节点之和
/a/b[@id="c"]/(. + sum(./preceding-sibling::*))

答案 1 :(得分:2)

不漂亮,但确实有效:

<table>
  <xsl:for-each select="@*">
    <tr>
      <xsl:variable name="pos" select="position()"/>
      <xsl:variable name="earlier" select="../@*[position() &lt; $pos]"/>
      <td>
        <xsl:value-of select="sum($earlier) + ."/>
      </td>
      <td>
        <xsl:for-each select="$earlier">
          <xsl:value-of select="name()"/> +
        </xsl:for-each>
        <xsl:value-of select="name()"/>
      </td>
    </tr>
  </xsl:for-each>
</table>

答案 2 :(得分:1)

您或许可以拼凑出似乎有效的解决方案,但这是一个固有的问题,您的解决方案将会破裂。

问题是XML中的属性没有重要的顺序。您不能依赖于在XSLT内部或外部呈现给任何进程的属性,它们与文本中出现的顺序相同。坦率地说,我很惊讶XSLT甚至允许你在属性谓词中使用position()

(顺便说一句,这就是身份变换使用奇数模式select="node()|@*"的原因。@*是必需的,因为node()与属性不匹配。node()没有不匹配属性,因为属性不是节点。节点有位置,属性没有。)

如果您的应用程序依赖于属性的排序,那么它就会被破坏,您需要重新设计它。

但是,如果您可以依赖属性的名称来提供某种排序,那么还有一种方法,如您的示例所示:

<xsl:variable name="atts" select="@*"/>
<xsl:for-each select="$atts">
  <xsl:sort select="substring-after(name(), 'Node')" data-type="number"/>
  <td>
    <xsl:variable name="this" select="number(substring-after(name(), 'Node'))"/>
    <xsl:value-of select="sum($atts[
                  number(substring-after(name(), 'Node')) &lt;= $this])"/>
  </td>
</xsl:for-each>

那难看吗?你打赌。如果您稍微更改了属性命名方案,它就会中断。但它会起作用,但属性是有序的。

相关问题