|
Summary
A method of ordering XML using an arbitrarily defined sort order.
There are some scenarios where the sort order of the output needs to be based upon some pre-defined order precedence which is deduced from data in the input XML.
Take for example that you have a passenger list - where each passenger element has a age/gender (man, woman, girl, boy, etc.) - and you want to create a list of passengers in order of precedence of who is to go into the lifeboats first (yes - the ship is sinking and yes, writing XSLT when the ship is sinking may not be your highest priority!).
So the order is according to the old addage Women and Children first. So if you simply order by the data (alphabetically) you would incorrectly end up with...
- boy
- girl
- man
- woman
So we need a way to define the correct sort precedence of:- girl/boy, woman then man. One way to achieve this is to define as a variable containing a string list containing the possible values in their appropriate sequence, e.g.
<xsl:variable name=lifeboat-precedence select='girl|boy|woman|man'/>
(The '|' bar character is simply used as the delimeter between the values). Then we can use the relative position of where the value is found in that string to determine the sort precedence, e.g.
<xsl:sort select=string-length(substring-before($lifeboat-precedence,concat('|',@age_gender))) data-type=number order=ascending/>
(Note that the '|' character is used within the concat() function when looking for the position of the value within the string variable - this is to ensure that the position is correct, e.g. that 'man' is not found at then end of 'woman')
This will now work in all scenarios where all the possible values can be predicted and placed in the sort precedence string variable. However, there will be circumstances where all of the possible values are not always known - and any unkown values should be placed last in the sort order. Say for example we have a passenger who is an OAP (Old Age Pensioner) - the above sort sequence will place this anywhere in between the 'Girl' items - because the token 'OAP' was not found in the string variable. To overcome this we can redefine the string variable to cater for unknown values, e.g.
<xsl:variable name=lifeboat-precedence select='|*|man|boy|woman|girl'/>
(where the '*' token is inserted to push the 'Man' precedence to higher than any unkown). Now if the sort uses 'descending' rather than 'ascending' you will get the correct sort order, e.g.
<xsl:sort select=string-length(substring-before($lifeboat-precedence,concat('|',@age_gender))) data-type=number order=descending/>
The above examples are all case sensitive - but this can be overcome by using the translate() function if required.
This example is taken from the extensive sample stylesheets included with Xselerator (http://www.topxml.com/Xselerator).
Cheers - Marrow
| Further additional information | |
Updating comments...
Updating comments...
|