开发者

XSL Conditional Totalling

Is it possible to perform conditional totalling in xsl?

I have the following xml sample:

<?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>
      <开发者_如何学C/column>
      <column id="2">
        <sum>19</sum>
      </column>
    </columns>
  </stats>
</export>

Is it possible to compute the total of all columns in each stat set where they are not equal to one another? So it would output the following:

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

So in the output column 1 would be omitted as the sum in the two stat sets is the same.

I can get my xsl to output the columns that are different but unsure how to total these up and put in the total row.

Many thanks,

Andez


This transformation (64 lines):

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

when applied on the provided XML document:

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

produces the wanted, correct result:

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

  Column 2       102             101             1

  Column 3       12             19             -7

Explanation:

  1. The key named kColByPosAndVal is used to select all columns that have a given position (among all column siblings) and a given value for their sum child-element.

  2. The key named kIdByVal is used in Muenchian grouping to find all different values for the id attribute.

  3. The two totals are calculated summing only those columns, whose kColByPosAndVal key selects only one column element (if it selects two column elements, they both are at the same position and have the same sum).

  4. The rest should be easy to understand.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜