views:

212

answers:

3

I am new to working with XSLT and am trying to create a pivot table using the Muenchian Method (since it appear that IE still doesn't support XSLT 2.0 I think I'm stuck with this). I am able to get the desired grouping however I am trying to get the sum of an attribute for each group. To do the sum of the attribute can I use the aggregate sum function or do I have to loop through the keys and store the values into a variable? This is what I have so far:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
<xsl:output method="html" indent="yes" encoding="UTF-8"/>

<xsl:key name="Person" match="Record" use="@PersonID" />
<xsl:template match="/">
  <html>
  <body>
    <h2>Costs Per Person</h2>
    <table border = "1">
        <thead>
        <tr>
           <th>ID</th>
           <th>Cost</th>
        </tr>
        </thead>
        <tbody>
        <xsl:for-each select="Records/Record[generate-id() = 
         generate-id(key('Person', @PersonID)[1])]">
     <tr>
      <td>
       <xsl:value-of select="@PersonID" />
      </td>

      <td>
       <!-- Sum Of Cost -->
      </td>
     </tr> 
       </xsl:for-each> 
       </tbody>
    </table>
  </body>
  </html>
</xsl:template>
A: 

You should be able to use sum if you can use an xpath to select the attribute for the desired record(s).

Without knowing the structure of your input xml i don't know what this would be but I guess in your case something like <xsl:value-of select="sum(@cost)"/>

Chris R
+1  A: 

Because your current context node inside the loop is a Record element, you will need to ensure your 'sum' includes all Records with a matching PersonID attribute. Something like this should do:

<xsl:value-of select="sum(../Record[@PersonID=current()/@PersonID]/@Cost)" />

Or, because you know the current Record element is the first with a particular PersonID attribute, you could also do this in this case

<xsl:value-of select="number(@Cost) + sum(following-sibling::Record[@PersonID=current()/@PersonID]/@Cost)" />
Tim C
Thanks for pointing out some syntax that I was unaware of. Only have spent a couple days with XSLT so far and all examples help!
jwarzech
+1  A: 

Easy - you where already there. See full solution below.

On a different note, I advise against the use of <xsl:for-each> in favor of <xsl:apply-templates>. The code gets a bit longer, but readability and code structure improves, IMHO.

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:output method="html" indent="yes" encoding="UTF-8"/>

  <xsl:key name="Person" match="Record" use="@PersonID" />

  <xsl:template match="/">
    <html>
      <body>
        <h2>Costs Per Person</h2>
        <table border = "1">
          <thead>
            <tr>
               <th>ID</th>
               <th>Cost</th>
            </tr>
          </thead>
          <tbody>
            <xsl:apply-templates select="Records/Record" />
          </tbody>
        </table>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="Records/Record">
    <xsl:variable name="thisGroup" select"key('Person', @PersonID)" />

    <xsl:if test="generate-id() = generate-id($thisGroup[1])">
      <tr>
        <td>
          <xsl:value-of select="@PersonID" />
        </td>
        <td>
          <!-- Sum Of Cost -->
          <xsl:value-of select="sum($thisGroup/@Cost)" />
        </td>
      </tr>   
    </xsl:if>  
  </xsl:template>
</xsl:stylesheet>
Tomalak
That works, thanks for your help!
jwarzech