Read XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition Online
Authors: Michael Kay
Sorting the Groups
If there are any
The
select
expression in an
select
expression is evaluated with this item as the context item, with the position of this item relative to the initial items of other groups as the context position, and with the number of groups as the context size.
If any of the attributes of the
select
expression of the containing
If there are no
“Processed before” does not refer to the actual order of execution; the system can process the groups in any order, or in parallel. What it means is that the results of processing group G appear in the final result sequence ahead of the results of processing group H.
In practice, if the groups are sorted at all then they are nearly always sorted by the value of the grouping key:
group the addresses in each city, sorting the groups by city
. This can be conveniently coded as:
The functions
current-group()
and
current-grouping-key()
are described on page 739 in Chapter 13.
An
The
You can also use the
Usage and Examples
The following sections give a number of examples of how
group-by
,
group-adjacent
,
group-starting-with
, and
group-ending-with
.
Using group-by
This is by far the most common kind of grouping. We'll start with a simple case.
Example: Single-Level Grouping by Value
This example groups a set of employees according to the department in which they work.
Source
We'll start with the following simple data file (
staff.xml
):
Output
The requirement is to output an HTML document in which the staff are listed by department:
sales department
John Jones
Maria Gomez
personnel department
Barbara Jenkins
Wesley Thomas
transport department
Cormac O'Donovan
Stylesheet
This output is simple to achieve. The full stylesheet is in
group-by-dept.xsl
:
A number of variations are possible on this theme. To sort the deparments, use an
sorted-depts.xsl
):
This general design pattern, where
The example above was expressed as a grouping problem (“list the employees grouped by department”), so it is easy to see that
Example: Multilevel Grouping by Value
Sometimes there is a need to do multilevel grouping. For example, you might want to group the employees by department, and the departments by location. Assume that the
Source
The data is now like this (
staff-locations.xml
):
department=“sales”
location=“New York”/>
department=“personnel”
location=“Los Angeles”/>
department=“transport”
location=“New York”/>
department=“personnel”
location=“Los Angeles”/>
department=“sales”
location=“Seattle”/>
Output
You might want the output presented like this:
Location: Los Angeles
Department: Personnel
Barbara Jenkins
Wesley Thomas
Location: New York
Department: Sales
John Jones
Department: Transport
Cormac O'Donovan
Location: Seattle
Department: Sales
Maria Gomez
Stylesheet
Assume that the indentation is achieved using CSS styles, so you can concentrate on getting the structure of the information right. To do this multilevel grouping, just use two levels of
multi-level.xsl
):
A similar requirement is where there is a composite grouping key (“group employees that have the same department and the same location”). There are two ways of handling this. You can either treat it as a single level of grouping, using the concatenation of the two values as the grouping key, or you can treat it as two nested groupings in which the outer level does nothing (
composite.xsl
):
. . .
The two techniques are not completely identical. For example, with a single-level grouping using a concatenated key, the value of
position()
while processing a department will run continuously from 1 up to the total number of groups, but with a two-level grouping,
position()
will start again at 1 for each location.