我是XSLT的新手,所以如果我的编码草率或不必要的复杂,请耐心等待。我正在尝试创建一个歌曲列表,其中包括需要按标题按字母顺序排列的歌曲。对于一些歌曲,我列出了多种语言的标题。例如,是否可以按字母顺序按日语排序,但如果没有,则按英文标题按字母顺序排列。这是一个例子:
<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>
目前,歌曲由romaji元素的内容显示,该元素将显示:
自由是最重要的,因为没有要分类的罗马字标签。是否可以按照罗马字元素的内容对歌曲进行排序,但如果它不存在,请使用英语元素的内容来显示此列表:
如果我应该提供更多信息或我的编码部分,请告诉我。谢谢!
答案 0 :(得分:3)
我认为这可以通过 xsl:sort 元素实现,该元素可以与 xsl:for-each 和 xsl:apply-templates一起使用强>
<xsl:sort select="concat(title/romaji, title[not(romaji)]/english)" />
所以,这意味着罗马的标题,但如果没有,那么将使用英文标题。
这是一个简单的XSLT来演示
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/music-catalogue">
<ol>
<xsl:apply-templates select="song">
<xsl:sort select="concat(title/romaji, title[not(romaji)]/english)" />
</xsl:apply-templates>
</ol>
</xsl:template>
<xsl:template match="song">
<li>
<xsl:value-of select="concat(title/romaji, title[not(romaji)]/english)" />
</li>
</xsl:template>
</xsl:stylesheet>
当应用于您的示例XML时,将输出以下结果
<ol>
<li>Agechikuten</li>
<li>Freedom</li>
<li>Kamigami no Uta</li>
<li>Tinsagu nu Hana</li>
</ol>
答案 1 :(得分:1)
实现这种排序的常用方法是通过所需节点的联合:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="music-catalogue">
<xsl:copy>
<xsl:apply-templates select="song">
<xsl:sort select="title/romaji | title[not(romaji)]/english"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
产生
<music-catalogue>
<song>
<title>
<romaji>Agechikuten</romaji>
<japanese>揚作田</japanese>
</title>
</song>
<song>
<title>
<english>Freedom</english>
</title>
<artist>
<e-name>12 Girls Band</e-name>
<j-name>女子十二乐坊</j-name>
</artist>
</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/>
</artist>
</song>
<song>
<title>
<romaji>Tinsagu nu Hana</romaji>
<japanese>ティンサグぬ花</japanese>
</title>
</song>
</music-catalogue>
答案 2 :(得分:1)
这类似于@Tim C提出的解决方案,但是不需要使用字符串连接:
<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>
应用于提供的XML文档(稍加修改以使其格式正确 - 编辑未定义的实体引用):
<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>
产生了想要的正确结果:
Agechikuten
Freedom
Kamigami no Uta
Tinsagu nu Hana
<强>解释强>:
在此解决方案中,使用 set arithmetic:
精确表达所需的排序键 romaji | self::*[not(romaji)]/english
其中|
是XPath union 运算符。
请注意,即使english
之前出现(按文档顺序排列)romaji
,此解决方案也能正常运行。