[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: arbitrary sorting (Part III, long))
Oliver Becker's original question: >supposing I have elements with a month attribute <report month="Jan" /> <report month="Feb" /> >and so on. >Of course unordered :-) >Now I want them in chronological order.... >I know how to translate Jan->1, Feb->2 etc via a named template >[and] xsl:choose, but that doesn't help much in this case. Naturally, what you want is to map names to numbers using keys, which can be very efficient. Keys were made for just this purpose! So far, I've been able to get this to work if the month table is in the input document. Consider this input document: <?xml version="1.0"?> <doc> <monthtab> <entry><name>Jan</name><number>1</number></entry> <entry><name>January</name><number>1</number></entry> <entry><name>Feb</name><number>2</number></entry> <entry><name>February</name><number>2</number></entry> <entry><name>Mar</name><number>3</number></entry> <entry><name>March</name><number>3</number></entry> <entry><name>Apr</name><number>4</number></entry> <entry><name>April</name><number>4</number></entry> <entry><name>May</name><number>5</number></entry> <entry><name>Jun</name><number>6</number></entry> <entry><name>June</name><number>6</number></entry> <entry><name>Jul</name><number>7</number></entry> <entry><name>July</name><number>7</number></entry> <entry><name>Aug</name><number>8</number></entry> <entry><name>August</name><number>8</number></entry> <entry><name>Sep</name><number>9</number></entry> <entry><name>Sept</name><number>9</number></entry> <entry><name>September</name><number>9</number></entry> <entry><name>Oct</name><number>10</number></entry> <entry><name>October</name><number>10</number></entry> <entry><name>Nov</name><number>11</number></entry> <entry><name>November</name><number>11</number></entry> <entry><name>Dec</name><number>12</number></entry> <entry><name>December</name><number>12</number></entry> </monthtab> <bday person="Linda"><month>Apr</month><day>22</day></bday> <bday person="Marie"><month>September</month><day>9</day></bday> <bday person="Lisa"><month>March</month><day>31</day></bday> <bday person="Harry"><month>Sep</month><day>16</day></bday> <bday person="Ginny"><month>Jan</month><day>22</day></bday> <bday person="Pedro"><month>November</month><day>2</day></bday> <bday person="Bill"><month>Apr</month><day>4</day></bday> <bday person="Frida"><month>July</month><day>5</day></bday> </doc> The first part of the above document is the month table. For demonstration purposes, I have both abbreviated and full month names (look at September) as synonyms, and you could easily add names in other languages. There's a many-to-one structure: look up a name, get back the correct month number. The rest of the document is the set of records that we want to sort in chronological order. The <day> elements will work as a simple numeric sort, but that's secondary to the sort by months. Following Oliver's request, we want <xsl:sort select="key('MonthNum',month)" data-type="number"/> where we will take the <month> as a string and get its number out of the 'MonthNum' keyspace. I'll supply an example of the above sort working in an apply-templates situation, but it can work similarly in a for-each loop. The current node will be the outer <doc> element at the time we sort, so the keyspace definition will also be based on that context: <xsl:key name="MonthNum" match="monthtab/entry/number" use="../name" /> With that background, check out this stylesheet: <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:key name="MonthNum" match="monthtab/entry/number" use="../name" /> <xsl:template match="doc"> <out> <xsl:text>Birthdays in chronological order... </xsl:text> <xsl:apply-templates select="bday"> <xsl:sort select="key('MonthNum',month)" data-type="number" /> <xsl:sort select="day" data-type="number" /> </xsl:apply-templates> </out> </xsl:template> <xsl:template match="bday"> <xsl:value-of select="@person"/><xsl:text>: </xsl:text> <xsl:value-of select="month"/><xsl:text> </xsl:text> <xsl:value-of select="day"/><xsl:text> </xsl:text> </xsl:template> </xsl:stylesheet> The <out> element is just something we commonly use as a tracing aid. The above works on both Xalan and Saxon. Ideally, one would want to put the month table in a completely separate file, so it could be shared among all stylesheets that needed it. Depending on your situation, you might prefer to have the month table right in the stylesheet. Either way, you have to use document(), which certainly complicates the procedure. The point of this message is to show that key() can be used in sort keys. .................David Marston XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|