XSL условное суммирование - PullRequest
       9

XSL условное суммирование

3 голосов
/ 09 декабря 2010

Можно ли выполнить условное суммирование в xsl?

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

<?xml version="1.0" encoding="utf-8"?>
<export>
<stats set="1">
  <columns>
    <column id="0">
      <sum>100</sum>
    </column>
    <column id="1">
      <sum>102</sum>
    </column>
    <column id="2">
      <sum>12</sum>
    </column>
  </columns>
</stats>
  <stats set="2">
    <columns>
      <column id="0">
        <sum>100</sum>
      </column>
      <column id="1">
        <sum>101</sum>
      </column>
      <column id="2">
        <sum>19</sum>
      </column>
    </columns>
  </stats>
</export>

Можно ли вычислить сумму всех столбцов в каждом наборе статов, гдеони не равны друг другу?Таким образом, будет выведено следующее:

               Set 1       Set 2       Diff(Set 1 - Set 2)
Total (Diff)   114         120           -6
column 2       102         101            1  
column 3       12          19            -7 

Таким образом, в выходном столбце 1 будет опущено, так как сумма в двух наборах статов одинакова.столбцы, которые отличаются, но не знают, как их суммировать и поместить в итоговую строку.

Большое спасибо,

Андез

1 Ответ

1 голос
/ 09 декабря 2010

Это преобразование (64 строки):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:key name="kColByPosAndVal" match="column"
  use="concat(count(preceding-sibling::*),
              '+',
              sum)"/>
 <xsl:key name="kIdByVal" match="column/@id"
  use="."/>

 <xsl:template match="/*">
  <xsl:variable name="vsum1" select=
   "sum(stats[@set=1]/*/column
                  [not(key('kColByPosAndVal',
                            concat(count(preceding-sibling::*),
                                  '+',
                                   sum)
                           )[2]
                       )])"/>
  <xsl:variable name="vsum2" select=
   "sum(stats[@set=2]/*/column
                  [not(key('kColByPosAndVal',
                            concat(count(preceding-sibling::*),
                                  '+',
                                   sum)
                           )[2]
                       )])"/>

                 Set 1          Set 2       Diff(Set 1 - Set 2)
  Total (Diff)   <xsl:text/>
  <xsl:value-of select="$vsum1"/>
  <xsl:text>             </xsl:text>
  <xsl:value-of select="$vsum2"/>
  <xsl:text>             </xsl:text>
  <xsl:value-of select="$vsum1 -$vsum2"/>
  <xsl:text>&#xA;</xsl:text>

  <xsl:for-each select=
   "*/*/column/@id
       [generate-id()
       = generate-id(key('kIdByVal',.)[1])
       ]
       [not(key('kColByPosAndVal',
                concat(count(../preceding-sibling::*),
                       '+',
                       ../sum)
                )[2]
            )]">
    <xsl:variable name="vcolSet1" select=
     "/*/stats[@set=1]/*/column[@id=current()]/sum"/>

    <xsl:variable name="vcolSet2" select=
     "/*/stats[@set=2]/*/column[@id=current()]/sum"/>
  Column <xsl:value-of select=".+1"/><xsl:text/>
    <xsl:text>       </xsl:text>
    <xsl:value-of select="$vcolSet1"/>
    <xsl:text>             </xsl:text>
    <xsl:value-of select="$vcolSet2"/>
    <xsl:text>             </xsl:text>
    <xsl:value-of select="$vcolSet1 -$vcolSet2"/>
    <xsl:text>&#xA;</xsl:text>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

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

<export>
<stats set="1">
  <columns>
    <column id="0">
      <sum>100</sum>
    </column>
    <column id="1">
      <sum>102</sum>
    </column>
    <column id="2">
      <sum>12</sum>
    </column>
  </columns>
</stats>
  <stats set="2">
    <columns>
      <column id="0">
        <sum>100</sum>
      </column>
      <column id="1">
        <sum>101</sum>
      </column>
      <column id="2">
        <sum>19</sum>
      </column>
    </columns>
  </stats>
</export>

дает желаемый, правильный результат :

                 Set 1          Set 2       Diff(Set 1 - Set 2)
  Total (Diff)   114             120             -6

  Column 2       102             101             1

  Column 3       12             19             -7

Объяснение

  1. Ключ с именем kColByPosAndVal используется для выбора всех столбцов, которые имеют заданную позицию (среди всех column братьев и сестер) и заданное значение для их sum дочернего элемента.

  2. Ключ с именем kIdByVal используется в мюнхенской группировке для поиска всех различных значений атрибута id .

  3. Два итога рассчитываются суммированием только тех столбцов, чья клавиша kColByPosAndVal выбирает только один элемент column (если он выбирает два элемента column, они оба совпадают позиции и имеют одинаковые sum).

  4. Остальное должно быть легко понять .

...