Re: [xsl] Identity Transform Grouping Question

Subject: Re: [xsl] Identity Transform Grouping Question
From: Anton Triest <anton@xxxxxxxx>
Date: Tue, 19 Oct 2004 10:09:58 +0200
Hi Ethan,

Unfortunately, I could not get a successful result. The source tree I had supplied with my post was simplified to (besides make it easier for people on the list to read!) illustrate the nature of my problem. When I run your solution against that simplified tree it appears to produce the correct result. However, when I use a slightly more complex source tree (e.g. multiple cities with multiple offices), the result is inconsistent.

The problem is noticeable by looking at the transformed U.S. cities. Both cities (Miami and New York) have the same <location> children appearing under their respective <city> parent elements. The problem seems to be the grouping done on offices in different cities in the same country. However, for offices in the same city in the same country, the grouping appears to work just fine (see London results).

Yes: that was a bug. In template match="city", the grouping of the office elements included all offices in the current country (rather than the current city).
Here's the fixed template (added "cities/city=current()" to the predicate):

<xsl:template match="city">
<name><xsl:value-of select="."/></name>
<!-- group 'office' elements *located in this city* by their english name -->
<xsl:apply-templates select="ancestor::offices/office
[cities/city=current() and count(.|key('offices',
<xsl:sort select="names/name[@lang='en']"/>

I like using the iterative ("for-each") approach that he used, and had rewritten his solution without having to rely on the seemed to produce similar results, so I would have used it instead if I were able to get the additional grouping level working.

No doubt you have noticed I like working with apply-templates, it's a matter of personal taste I guess. I like it because it breaks down the program flow in smaller pieces (modular) and the nesting level is not so deep. But in most cases both approaches are interchangeable. It shouldn't be too difficult to convert my stylesheet to a one-template stylesheet with nested for-each loops.

The Muenchian grouping is getting a bit complicated because of the additional country check in the key. For the offices, I don't know if you really need it. If the office names in your input are unique (ie. there cannot be offices with the same name in different countries), you can simplify the key and just use "names/name[@lang='en']".

An alternative might be to work in two passes: first generate a temporary xml file sorted by city and office name, and then take that file as input for a second transform. Or use node-set to do it in one pass (exslt is more portable than msxml). Then you can use the preceding-sibling axis to do the grouping. But I think, Muenchian grouping is more efficient. And of course, in XSLT 2.0 these things are much easier..

Good luck!

Current Thread