I am trying to sort a bunch of records in an XML file. The trick is that I need to sort using different elements for different nodes. To give a simple example, I want to do this: given an xml file
<?xml version="1.0" encoding="utf-8" ?> <buddies> <person> <nick>Jim</nick> <last>Zulkin</last> </person> <person> <first>Joe</first> <last>Bumpkin</last> </person> <person> <nick>Pumpkin</nick> </person> <person> <nick>Andy</nick> </person> </buddies>
I want to convert it to
Andy Joe Bumpkin Pumpkin Jim Zulkin
That is, a person can be specified by any subset of the name, surname and nickname. The sort key is the last name, if one is present, otherwise it is an alias if one is present, and the first name otherwise.
I'm having difficulty since using variables as xsl: sort keys are apparently not allowed .
My current best shot is a two-step conversion: add a custom tag to each entry using this stylesheet
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="no" indent="yes"/> <xsl:template match="/buddies"> <buddies> <xsl:for-each select="person"> <person2> <xsl:copy-of select="*"/> <sort-by> <xsl:choose> <xsl:when test="last"> <xsl:value-of select="last"/> </xsl:when> <xsl:otherwise> <xsl:choose> <xsl:when test="nick"> <xsl:value-of select="nick"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="first"/> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </sort-by> </person2> </xsl:for-each> </buddies>
And then sort the resulting xml
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/buddies"> <xsl:apply-templates> <xsl:sort select="sort-by"/> </xsl:apply-templates> </xsl:template> <xsl:template match="person2"> <xsl:value-of select="first"/> <xsl:value-of select="nick"/> <xsl:value-of select="last"/><xsl:text> </xsl:text> </xsl:template>
While this two-step conversion works, I wonder if there is a more elegant way to do this in just one go?
xml xpath xslt
ev-br
source share