I am trying to make a crosstab tables from the XML file from ToDoList (http://www.abstractspoon.com/tdl_resources.html) Here is an example XML file:
<?xml version="1.0" encoding="utf-16" ?>
<TODOLIST PROJECTNAME="Projects">
<TASK TITLE="proj1" ID="1" NUMPERSON="1" PERSON="Chris" NUMTAGS="1" TAG="Caro" CALCTIMEESTIMATE="36"/>
<TASK TITLE="proj2" ID="2" NUMPERSON="1" PERSON="Chris" NUMTAGS="1" TAG="Nat" CALCTIMEESTIMATE="8" />
<TASK TITLE="proj4" ID="4" NUMPERSON="1" PERSON="Chris" NUMTAGS="1" TAG="Caro" CALCTIMEESTIMATE="36" />
<TASK TITLE="proj5" ID="5" NUMPERSON="1" PERSON="Sahb" NUMTAGS="1" TAG="Nat" CALCTIMEESTIMATE="128" />
<TASK TITLE="proj32" ID="32" NUMPERSON="2" PERSON="Seb" PERSON1="Chris" NUMTAGS="1" TAG="Nat" CALCTIMEESTIMATE="0.90" />
</TODOLIST>
Each task is an element and all the info are attributes. I want to make a table like this with the tags as the top row and the persons as the first column.
<table>
<tr>
<td></td>
<td>Caro</td>
<td>Nat</td>
</tr>
<tr>
<td>Chris</td>
<td>72</td>
<td>8</td>
</tr>
<tr>
<td>Sahb</td>
<td>128</td>
<td>0</td>
</tr>
<tr>
<td>Seb, Chris</td>
<td>0</td>
<td>9</td>
</tr>
</table>
As you can see the same person can have many projects and I want to add up the CALCTIMEESTIMATE for each person based on the tag(s). I can get the first row with
<xsl:key name="dtag" match="/TODOLIST/TASK/@TAG" use="." />
<xsl:for-each select="TASK/@TAG[generate-id() = generate-id(key('dtag', .)[1])]">
<td>
<xsl:value-of select="."/>
</td>
</xsl:for-each>
But the sum function does not give the desired results. What I’m I missing? Is there an easy way to do the sum based on two attributes? ToDoList uses XSLT 1.0, that’s why I couldn’t use distinct-values.
Here is the full XSLT, I’ve tried alot of different thing, Here I was trying to get it working just for Chris but it would not add up his 2 projects.
<xsl:template match="TODOLIST">
<xsl:text disable-output-escaping="yes"><!DOCTYPE html></xsl:text>
<html>
<head>
<title>Projects..</title>
</head>
<body>
<table>
<caption>Projects..</caption>
<thead>
<tr>
<td></td>
<xsl:for-each select="TASK/@TAG[generate-id() = generate-id(key('dtag', .)[1])]">
<th scope="col">
<xsl:value-of select="."/>
</th>
</xsl:for-each>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="TASK/@PERSON[generate-id() = generate-id(key('dperson', .)[1])]" />
</tbody>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="TASK/@PERSON">
<tr>
<th scope="row">
<xsl:value-of select="."/>
</th>
<xsl:apply-templates select="/TODOLIST/TASK/@TAG[generate-id() = generate-id(key('dtag', .)[1])]" />
</tr>
</xsl:template>
<xsl:template match="/TODOLIST/TASK/@TAG">
<td>
<xsl:value-of select="sum(../@CALCTIMEESTIMATE[../@PERSON = 'Chris'])" />
</td>
</xsl:template>
To get your sum to work, you need to know both the current person and the current tag.
In your current template that matches TASK/@PERSON, you should pass the current value of the attribute to the next template
Then, in your template that matches @TAG, you could access the ‘dperson’ key in the SUM, so you sum all tasks for that person, and for the current tag, like so: