I am very new to XSLT so please bear with me if my coding is sloppy or unnecessarily complicated. I am trying to create a list of songs that among other things needs to be alphabetized by title. For some of some of the songs I have listed titles in multiple languages. Is it possible to always sort alphabetically by Japanese, for example, but if there isn't one, then alphabetize by the english title. Here's an example:
<music-catalogue>
<song>
<title>
<romaji>Agechikuten</romaji>
<japanese>揚作田</japanese>
</title>
</song>
<song>
<title>
<romaji>Kamigami no Uta</romaji>
<japanese>神々の詩</japanese>
<english>Song of the Gods</english>
</title>
<artist>
<e-name>Himekami</e-name>
<j-name>姫神</j-name>
<link>&himekami;</link>
</artist>
</song>
<song>
<title>
<english>Freedom</english>
</title>
<artist>
<e-name>12 Girls Band</e-name>
<j-name>女子十二乐坊</j-name>
</artist>
</song>
<song>
<title>
<romaji>Tinsagu nu Hana</romaji>
<japanese>ティンサグぬ花</japanese>
</title>
</song>
</music-catalogue>
Currently, the songs are displayed by the content of the romaji element which would show:
Freedom is on top because there is not a romaji tag to be sorted. Is it possible to sort the songs by the content of the romaji element but if it doesn't exist, use the content of the english element to display this list:
Please let me know if I should include any more information or parts of my coding. Thank you!
This is similar to the solution proposed by @Tim C, but avoids the need to use string concatenation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/*">
<xsl:apply-templates select="song/title">
<xsl:sort select="romaji | self::*[not(romaji)]/english"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="title">
<xsl:text>
</xsl:text>
<xsl:value-of select=
"romaji | self::*[not(romaji)]/english"/>
</xsl:template>
</xsl:stylesheet>
When applied to the provided XML document (slightly modified to make it well-formed -- edited an undefined entity reference):
<music-catalogue>
<song>
<title>
<romaji>Agechikuten</romaji>
<japanese>揚作田</japanese>
</title>
</song>
<song>
<title>
<romaji>Kamigami no Uta</romaji>
<japanese>神々の詩</japanese>
<english>Song of the Gods</english>
</title>
<artist>
<e-name>Himekami</e-name>
<j-name>姫神</j-name>
<link>&himekami;</link>
</artist>
</song>
<song>
<title>
<english>Freedom</english>
</title>
<artist>
<e-name>12 Girls Band</e-name>
<j-name>女子十二乐坊</j-name>
</artist>
</song>
<song>
<title>
<romaji>Tinsagu nu Hana</romaji>
<japanese>ティンサグぬ花</japanese>
</title>
</song>
</music-catalogue>
the wanted, correct result is produced:
Agechikuten
Freedom
Kamigami no Uta
Tinsagu nu Hana
Explanation:
In this solution the wanted sort key is expressed precisely using set arithmetic:
romaji | self::*[not(romaji)]/english
where |
is the XPath union operator.
Do note, that this solution works correctly even if english
comes before (in document order) romaji
.