Re: [xsl] Customised sorting

Subject: Re: [xsl] Customised sorting
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Thu, 5 Apr 2001 09:40:14 +0100
Hi Mille,

> Now, my problem is very similar to this example but with the
> addition that I need to sort the groups in a specific order. In the
> example this would correspond to order the groups for example by the
> size of captial of each country. This ordering information needs to
> bes supplied with the style-sheet and not with the XML-document.

OK - the first thing is to have the data about the size of the capital
of each country somewhere. You could define it as a global variable
within the stylesheet, but it would be cleaner, easier to maintain and
have the advantage of working without extension functions (or XSLT
1.1) if you defined it in a separate document:

---- cities.xml ----
<cities>
   <city name="Paris" country="France" population="1" />
   <city name="Roma" country="Italy" population="6"/>
   <city name="Nice" country="France" population="3"/>
   <city name="Madrid" country="Espana" population="9"/>
   <city name="Milano" country="Italia" population="5"/>
   <city name="Firenze" country="Italia" population="4"/>
   <city name="Napoli" country="Italia" population="7"/>
   <city name="Lyon" country="France" population="2"/>
   <city name="Barcelona" country="Espana" population="8"/>
</cities>
----

You can access this information with the document() function, so you
can make a variable that holds the city elements in the above with:

<xsl:variable name="populations"
              select="document('cities.xml')/cities/city" />

Now, given the name and country of a city, you can find the population
of that city by querying into the $populations variable:

  $populations[@name = $city-name and @country = $country-name]/@population

To do the sorting, you need xsl:sort within the xsl:for-each:

   <xsl:for-each select="//city[@country=current()]">
      <xsl:sort />
      <city>
         <xsl:value-of select="@name"/>
      </city>
   </xsl:for-each>

You can choose what to sort by using the select attribute on xsl:sort.
You want to sort by the population of each city, retrieved via the
$populations variable. Within the select attribute, the current node
is the node that you're sorting (i.e. a city element), so the select
attribute needs to be:

   <xsl:sort select="$populations[@name = current()/@name and
                                  @country = current()/@country]
                        /@population" />

As a final touch, remember that the population values are numbers, so
you need to change the data-type of the sort to 'number' rather than
'text' (the default):

   <xsl:sort select="$populations[@name = current()/@name and
                                  @country = current()/@country]
                        /@population"
             data-type="number" />

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