Of Grouping, Counting, and Context
by John E. Simpson
|
Pages: 1, 2
What that predicate is doing is a form of the so-called Muenchian method
for grouping data in ways not "built-in" to the structure of the source
tree. The name of this technique, by the way, comes from Steve Muench of
Oracle Corporation, who first popularized it on the XSL-List mailing list. It
takes advantage of a couple of features of the XSLT generate-id()
function:
|
Related Reading
XSLT |
- An XSLT processor isn't required to follow any particular algorithm in generating a unique identifier for a given node in the source tree.
- However, whatever algorithm it uses, an XSLT processor must generate the same key value for any given "seed value" (such as a node's string-value) in a given processing instance. (It need not generate the same key value for a given seed value in every processing instance.)
Essentially, this predicate says to restrict the node-set located by the
select attribute to just those Scorer attributes
whose generated IDs are identical to that of the current Scorer
attribute. This is where the grouping occurs: instead of getting a separate
table row for every single Scorer attribute (which would yield,
say, two rows for O'Reilly and three for Humble), you get one row for each
unique Scorer attribute value.
The other boldfaced portion of the template rule is where the goals are
counted for each unique Scorer attribute value. The
count() function takes one argument, an XPath expression -- a
relative location path, here. The location path tells the count()
function to count all Goal element children of the current node's
"grandparent" (that's the ../../ portion of the location path),
as long as those Goal elements' Scorer
attributes have the same value as the current Scorer
attribute.
|
Also in XML Q&A | |
By the way, note the use of the current() function in the
predicate. Under most circumstances, the current node is the same as the
context node. Within an xsl:for-each block in particular, though
the two will not necessarily be the same. At the point of the call to the
current() function in that xsl:value-of element's
select attribute, the context node has shifted to the
Goal element selected by the portion of the count()
function's argument which precedes the predicate. Of course this element's
string-value is never equal to that of the Scorer attribute, so
(a) the predicate is never true, (b) no matching nodes are ever selected, and
(c) the number of goals is therefore always zero. The current node,
on the other hand, is unaffected by the xsl:value-of's resetting
of the context node: the current node, in this case, is always the node
established by the current pass through the xsl:for-each loop --
that is, the current (keyed) Scorer attribute value.
The third column in the table simply shows how the
generate-id() function works for each unique
Scorer value. Again, remember the two rules in the preceding list: a
given key must be unique for any given "seed value," and an XSLT processor is
free to use any key-generation algorithm it wants as long as it results in the
same key (a generated ID, in this case) for a given seed value in a given
processing instance. Here's how Microsoft's MSXML processor formats the table
in a typical instance:
If you use the Saxon processor to transform the source tree with the above XSLT code, you might get something like the following instead (results obtained from Saxon 6.2):

Note (in the third column) that the two processors employ quite different rules for generating the IDs, but still produce the same results in the important columns: counts of goals, grouped by scorer. Remove that third column and the two processors (as should all other compliant processors) produce identical results.
Do you use keys and count() in your XSLT stylesheets? Share your experience in our forum.
(* You must be a member of XML.com to use this feature.)
Comment on this Article
| Titles Only | Titles Only | Newest First |
- key() example
2005-01-06 11:24:00 struglin [Reply]
Finally.. an example using key() I can understand. Thank you!!
- Same names in both teams
2003-06-09 20:59:44 Michael Leung [Reply]
I tried to modify the XML file that it looks like the following:
<?xml version="1.0"?>
<Match>
<Team Name="Liverpool">
<Goal Scorer="O'Reilly"/>
<Goal Scorer="Smith"/>
<Goal Scorer="O'Reilly"/>
</team>
<Team Name="Real Madrid">
<Goal Scorer="Charles"/>
<Goal Scorer="Humble"/>
<Goal Scorer="Humble"/>
<Goal Scorer="Santana"/>
<Goal Scorer="Humble"/>
<Goal Scorer="O'Reilly"/>
</Team>
</Match>
and how come "O'Reilly" in Real Madrid doesn't get shown in the Real Madrid scoring table? How can you overcome that ?
Many thanks,
Michael.
- Couldn't get it to work
2003-01-14 16:03:25 Brian Hagelin [Reply]
When I tried to run the example code given for the soccer teams XML doc...I got the following error:
The XML page cannot be displayed
Cannot view XML input using XSL style sheet. Please correct the error and then click the Refresh button, or try again later.
--------------------------------------------------------------------------------
Keyword xsl:key may not be used in namespace http://www.w3.org/TR/WD-xsl.

