Hello --
I'm trying to group and sort a list of tasks by category, where one
<task> may have multiple categories identified by <context> tags. I find
that I get different results depending on the ordering in the source XML:
<tasks>
<task>
<subject>This is to be done at home</subject>
<context>home</context>
</task>
<task>
<subject>No context so skip this one.</subject>
</task>
<task>
<subject>Make a phone call</subject>
<context>call</context>
</task>
<task>
<subject>This is to be done at home, and is a phone call</subject>
<context>home</context>
<context>call</context>
</task>
<task>
<subject>This is a call to be made from work</subject>
<context>work</context>
<context>call</context>
</task>
</tasks>
Using the following XSLT, I get what I want:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="tasks-by-context" match="task" use="context"/>
<xsl:template match="/">
<ul>
<xsl:for-each select="//task[count(. |
key('tasks-by-context', context)[1]) = 1][count(context)>0]">
<xsl:sort select="subject"/>
<xsl:variable name="c" select="context"/>
<li>
CONTEXT: <xsl:value-of select="$c"/>: (<xsl:value-of
select="count(key('tasks-by-context',$c))"/> tasks)
</li>
<ul>
<xsl:for-each select="key('tasks-by-context', $c)">
<li>
Task : <xsl:value-of select="subject"/>
</li>
</xsl:for-each>
</ul>
</xsl:for-each>
</ul>
</xsl:template>
</xsl:stylesheet>
As I'm skipping uncategorized tasks (i.e. with no <context> children), I
get the following output:
- CONTEXT: call: (3 tasks)
- Task : Make a phone call
- Task : This is to be done at home, and is a phone call
- Task : This is a call to be made from work
- CONTEXT: home: (2 tasks)
- Task : This is to be done at home
- Task : This is to be done at home, and is a phone call
However, this behavior differs if the original <task> elements are in a
different order. For example, moving the "Make a phone call" task to the
end of the <tasks> list reduces the output to the following:
- CONTEXT: home: (2 tasks)
- Task : This is to be done at home
- Task : This is to be done at home, and is a phone call
So it looks like my key definition is no longer picking up "call" as a
valid key item. I'm actually not sure whether I'm using the <xsl:key>
tag correctly here -- will it match and index a single <task> node
multiple times if it contains multiple tags?
Thanks in advance for your time.
Ramon