Использование XSL для поддержания промежуточного итога - PullRequest
4 голосов
/ 18 июня 2010

У меня есть следующий XML:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="disp.xsl"?>
<root>
 <node type="a"> 
  <value>4</value>
 </node>
 <node type="b">
  <value>2</value>
 </node>
 <node type="a">
  <value>3</value>
 </node>
 <node type="b">
  <value>1</value>
 </node>
</root

Я хочу создать отчет, который суммирует элементы значений каждого типа и сохраняет промежуточный итог. Я хочу:

type: a total:7 cumulative total:7
type: b total:3 cumulative total:10

Вот мой XSL:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="eachtype" match="node" use="@type" />
<xsl:template match="/root">
  <html>
  <body>
   <xsl:for-each select="node">
    Value: <xsl:value-of select="value"/> (Cumulative value: <xsl:variable name="temp" select="sum(preceding-sibling::node/value)+value"/><xsl:value-of select="$temp"/>)<br />
   </xsl:for-each>
   <hr />
   <xsl:for-each select="node">
    <xsl:variable name="thisType" select="@type"/>
    type: <xsl:value-of select="$thisType" /> Value: <xsl:value-of select="value"/> (Cumulative value: <xsl:variable name="temp2" select="sum(preceding-sibling::node/value)+value"/><xsl:value-of select="$temp2"/>)<br />
   </xsl:for-each>
   <hr />
      <xsl:for-each select="node[generate-id(.)=generate-id(key('eachtype',@type)[1])]">
    <xsl:variable name="thisType" select="@type"/>
    type: <xsl:value-of select="$thisType" /> Total: <xsl:value-of select="sum(/root/node[@type=$thisType]/value)"/> (Cumulative value: <xsl:variable name="temp2" select="sum(preceding-sibling::value)+value"/><xsl:value-of select="$temp2"/>)<br />
   </xsl:for-each>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

, который производит следующий вывод:

Value: 4 (Cumulative value: 4)
Value: 3 (Cumulative value: 7)
Value: 2 (Cumulative value: 9)
Value: 1 (Cumulative value: 10)

--------------------------------------------------------------------------------
type: a Value: 4 (Cumulative value: 4)
type: a Value: 3 (Cumulative value: 7)
type: b Value: 2 (Cumulative value: 9)
type: b Value: 1 (Cumulative value: 10)

--------------------------------------------------------------------------------
type: a Total: 7 (Cumulative value: 4)
type: b Total: 3 (Cumulative value: 2)

Я не могу найти способ получить правильное значение для совокупного итога в последних двух строках. Есть ли какие-нибудь ветераны XSL, которые могут помочь мне в моей первой попытке с XSL?

1 Ответ

3 голосов
/ 19 июня 2010

Это преобразование :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:key name="kType" match="@type" use="."/>

 <xsl:template match="/">
  <xsl:for-each select=
   "*/*/@type
          [generate-id()
          =
           generate-id(key('kType', .)[1])
           ]">
    <xsl:value-of  select=
     "concat('type: ', .,
             ' total: ', sum(/*/*[@type = current()]/value),

             ' cumulative total: ',
             /*/*[@type = current()][last()]/value
            +
             sum(/*/*[@type = current()][last()]/preceding-sibling::*/value),

             '&#xA;'
              )
     "/>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному XML-документу :

<root>
    <node type="a">
        <value>4</value>
    </node>
    <node type="a">
        <value>3</value>
    </node>
    <node type="b">
        <value>2</value>
    </node>
    <node type="b">
        <value>1</value>
    </node>
</root>

производит иск, правильный результат :

type: a total: 7 cumulative total: 7
type: b total: 3 cumulative total: 10

Обратите внимание, что это решение неэффективно .Я приведу более эффективный (рекурсивный) после торможения.:)

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