如何在 XSLT 中对多个节点的值求和 [英] How to sum the values of several nodes in XSLT

查看:32
本文介绍了如何在 XSLT 中对多个节点的值求和的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  • 如果我的位置是 2 那么 node[1] + node[2]
  • 如果我的位置是 5,那么 node[1] + node[2] + node[3] + node[4] + node[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 和

Node1 + Node2 7 和

Node1 + Node2 + Node3 的 16 和

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

任何人请帮我看看什么是 XSL

不工作的 xsl 如下

 <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:模板>

解决方案

您或许可以拼凑出一个看似有效的解决方案,但存在一个固有的问题,您的解决方案将会失效.

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

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

如果您的应用程序依赖于属性的顺序,那么它就坏了,您需要重新设计它.

不过,如果您可以依靠属性的名称来提供某种排序,则有一条出路,如您的示例所示:

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

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

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

  • 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 that be done in XSLT?

do have 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 output as below

5 sum of Node1

7 sum of Node1 + Node2

16 sum of Node1 + Node2 + Node3

.... sum of Node1 + ... + Node50

any one please help me that what will be XSL

not working xsl is as 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>

解决方案

You may be able to cobble together a solution that appears to work, but there's an inherent problem, and your solution is going to break.

The problem is that attributes in XML don't have significant order. You can't rely on attributes being presented to any process, in or out of XSLT, in the same order they appear in the text. Frankly, I'm surprised that XSLT even allows you to use position() in an attribute predicate.

(Incidentally, this is the reason that the identity transform uses that odd pattern select="node()|@*". The @* is required because node() doesn't match attributes. node() doesn't match attributes because attributes aren't nodes. Nodes have position, and attributes don't.)

If your application depends on the ordering of attributes, it's broken and you need to redesign it.

There's a way out, though, if you can rely on the attributes' names to provide some kind of ordering, 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 that ugly? You bet. And it breaks if you ever change your attribute naming scheme in the slightest. But it'll work however the attributes are ordered.

这篇关于如何在 XSLT 中对多个节点的值求和的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆