How to sum values โ€‹โ€‹of several nodes in XSLT

I need a loop to a specific node position() and the sum of these nodes. For instance:

  • if my position is 2, then node [1] + node [2]
  • if my position is 5, then node [1] + node [2] + node [3] + node [4] + node [5]

How can this be done in XSLT?

have the following 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> 

I am trying to show the output as below

5 amount Node1

7 amount Node1 + Node2

16 sum Node1 + Node2 + Node3

.... the amount of Node1 + ... + Node50

somebody please help me what will be XSL

xsl does not work as shown below

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

+4
source share
3 answers

You may be able to combine a solution that works, but there is an inherent problem and your solution will break.

The problem is that the attributes in XML are not significant. You cannot rely on attributes that are presented to any process, in or from XSLT, in the same order that they display in the text. Honestly, I'm surprised that XSLT even allows you to use position() in an attribute predicate.

(By the way, this is the reason that identity conversion uses this odd pattern select="node()|@*" . @* Is required because node() does not match attributes. node() does not match attributes because attributes aren ' t nodes. Nodes have a position but no attributes.)

If your application depends on the order of the attributes, it will break and you need to redesign it.

However, there is a way out if you can rely on attribute names to provide some sort of order, as shown in your example:

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

Is it ugly? You are betting. And it breaks if you ever change the attribute naming scheme. But it will work, however the attributes are ordered.

+1
source

XPath query for the sum of the context of the node and previous siblings . + sum(./preceding-sibling::*) . + sum(./preceding-sibling::*) .

eg. if you have the following 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> 

... you can get the sum of a node with id = "c" and previous nodes using the expression

 /a/b[@id="c"]/(. + sum(./preceding-sibling::*)) 
+3
source

Not really, but it works:

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

Source: https://habr.com/ru/post/1299738/


All Articles