Subject: Re: [xsl] grouping headers From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx> Date: Fri, 24 Aug 2001 10:42:41 +0100 |
Hi Jeroen, > I hope I'm making myself clear, I searched the archives for an > answer but I don't really know what I'm looking for... I'm surprised that searching for 'grouping' didn't give you an answer! :) This is a typical example of grouping-by-value. The most general approach is the Muenchian Method. In that method, you first define a key so that you can quickly access all the nodes that have a particular value. The name of the key is anything you want (e.g. people). The match attribute holds a pattern that matches the nodes that you want to index, in this case the 'person' elements. The use attribute holds a path from the matched node (the 'person' element) to the value that you're using to group them (their 'city' child). The key in your example looks like: <xsl:key name="people" match="person" use="city" /> With this key in place, you can find all the people from Amsterdam with: key('people', 'Amsterdam') So given a particular city, in a $city variable, you can find all the people in that city and generate a list of them with: <xsl:for-each select="key('people', $city)"> <xsl:value-of select="name" /><br /> </xsl:for-each> The trickier thing is to find all the cities, since I assume you don't know that in advance. If you went through all the person elements, then you would get all the cities, but you would get some of them repeated several times. You need to make sure that you only get the first occurrence of each city. Take 'Amsterdam' as the example. You want to find the city of the first person element who has a city of 'Amsterdam'. You know how to get all the person elements who have a city of 'Amsterdam' using the key (see above). You can use a predicate on the key to get just the first one: key('people', 'Amsterdam')[1] You need to look through all the person elements and find those that are the first returned for their particular city. This involves comparing two nodes; I find the most intuitive way is to use the generate-id() function, as follows: generate-id() = generate-id(key('people', city)[1]) So to get a list of all the person elements that are the first with a particular city, use: person[generate-id() = generate-id(key('people', city)[1])] You can use set logic instead, if you prefer: person[count(.|key('people', city)[1]) = 1] So you can iterate over those to get a list of them: <xsl:for-each select="person[count(.|key('people', city)[1]) = 1]"> <xsl:sort select="city" /> <!-- variable used for clarity --> <xsl:variable name="city" select="city" /> <xsl:value-of select="$city" /><br /> <xsl:for-each select="key('people', $city)"> <xsl:value-of select="name" /><br /> </xsl:for-each> <br /> </xsl:for-each> I hope that helps, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] grouping headers, Jeni Tennison | Thread | RE: [xsl] FW: Toggling radio button, Friedlander, Hal |
[xsl] number("Infinity")?, Ingo Schildmann | Date | Re: [xsl] grouping headers, Jeni Tennison |
Month |