Как суммировать значения нескольких узлов в XSLT - PullRequest
4 голосов
/ 29 января 2010

Мне нужен цикл до определенного узла 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>

Я пытаюсь показать вывод, как показано ниже

5 сумм Узла1

7 сумма Node1 + Node2

16 сумм Node1 + 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>

Ответы [ 3 ]

3 голосов
/ 29 января 2010

Запрос XPath на сумму узла контекста и предшествующих элементов имеет значение . + sum(./preceding-sibling::*).

например. если у вас есть следующий 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::*))
2 голосов
/ 29 января 2010

Не красиво, но работает:

<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>
1 голос
/ 29 января 2010

Возможно, вам удастся собрать решение, которое кажется работающим, но есть неотъемлемая проблема, и ваше решение сломается.

Проблема в том, что атрибуты в XML не имеют значительного порядка. Вы не можете полагаться на атрибуты, представленные какому-либо процессу, в XSLT или вне его, в том же порядке, в котором они появляются в тексте. Честно говоря, я удивлен, что XSLT даже позволяет вам использовать position() в предикате атрибута.

(Кстати, по этой причине преобразование идентичности использует этот нечетный шаблон select="node()|@*". Требуется @*, поскольку node() не соответствует атрибутам. node() не соответствует атрибутам, поскольку атрибуты не являются ' узлы t. Узлы имеют позицию, а атрибуты - нет.)

Если ваше приложение зависит от порядка атрибутов, оно сломано, и вам необходимо изменить его.

Однако есть выход, если вы можете полагаться на имена атрибутов для обеспечения некоторого порядка, как показано в вашем примере:

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

Это уродливо? Вы ставите. И это сломается, если вы когда-нибудь измените свою схему именования атрибутов. Но это будет работать, однако атрибуты упорядочены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...