2010-01-29 43 views
4

我需要一个循环直到特定节点position()和这些节点的总和。例如:如何总结XSLT中几个节点的值

  • 如果我的位置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> 

我试图显示输出如下Node1上

5总和

7节点1的节点1 +节点2

16总和的总和+ Node2 + Node3

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

+0

Marc Gravell,谢谢你的工作,你太棒了,我很欣赏你的快速回复 – Kedar 2010-01-29 14:01:17

回答

1

您可以凑齐,似乎工作的解决方案,但有一个内在的问题,你的解决方案是要打破。

问题是XML中的属性没有显着的顺序。您不能依靠呈现给XSLT的任何流程的属性,这些属性与它们在文本中出现的顺序相同。坦率地说,我很惊讶XSLT甚至允许你在属性谓词中使用position()

(顺便说一句,这是恒等变换使用,由于node()不匹配的属性奇数图案select="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> 

那是丑?你打赌。如果你稍微改变属性命名方案,它就会中断。但是它会工作,但属性是有序的。

+0

感谢Robert Rossney,这对我也很重要。 – Kedar 2010-02-03 10:28:43

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::*)) 
+0

+1。我认为'sum(。| preceding-sibling :: *)'更优雅。 – Tomalak 2010-01-29 12:53:31

+0

雅知道,你应该编辑你的问题,并添加:) – 2010-01-29 13:12:06

+1

@Kedar:从你原来的问题不清楚你是在谈论属性。如果没有依赖特定XSL转换器的实现细节,你试图实现的是不可能的。 XML规范指出属性顺序无关(第3.1章),并且未为属性节点指定XPath position()函数的行为。 – jarnbjo 2010-01-29 14:09:53

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

感谢它的工作,我很欣赏你的快速反应。 – Kedar 2010-01-29 13:59:21