XSLT的sort元素是XSLT转换过程中实现数据排序的核心组件,它通常配合xsl:for-each或者xsl:apply-templates指令使用,能够对XML节点集合按照指定规则进行排序后输出。sort元素支持多种排序维度配置,可以满足大部分XML数据排序的需求。

XSLT sort元素基本语法
sort元素属于XSLT命名空间下的指令,基本语法结构如下:
<xsl:sort select="表达式" order="ascending|descending" data-type="text|number|qname" case-order="upper-first|lower-first" lang="语言代码" />
各个属性的作用说明如下:
- select:指定排序的依据,通常是XML节点的路径表达式,默认值为当前节点。
- order:指定排序顺序,ascending表示升序,descending表示降序,默认值为ascending。
- data-type:指定排序的数据类型,text表示文本排序,number表示数值排序,默认值为text。
- case-order:指定大小写字母的排序优先级,仅在data-type为text时生效。
- lang:指定排序使用的语言规则,影响特定语言的字符排序逻辑。
单字段排序实现
假设我们有一个存储学生信息的XML文件,内容如下:
<students>
<student>
<name>张三</name>
<score>85</score>
</student>
<student>
<name>李四</name>
<score>92</score>
</student>
<student>
<name>王五</name>
<score>78</score>
</student>
</students>
如果需要按照分数升序排列学生信息,对应的XSLT转换代码如下:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h3>学生成绩升序排列</h3>
<ul>
<xsl:for-each select="students/student">
<!-- 按照score子元素的数值升序排序 -->
<xsl:sort select="score" data-type="number" order="ascending"/>
<li>
姓名:<xsl:value-of select="name"/>,分数:<xsl:value-of select="score"/>
</li>
</xsl:for-each>
</ul>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
上述代码中,xsl:for-each遍历所有student节点,xsl:sort指定按照score节点的数值升序排列,最终输出的学生列表会按照分数从低到高展示。
多字段排序实现
当单字段排序出现相同值需要二次排序时,可以使用多个xsl:sort元素实现多字段排序。比如先按照分数降序排列,分数相同的再按照姓名升序排列,XSLT代码如下:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h3>学生成绩多字段排序</h3>
<ul>
<xsl:for-each select="students/student">
<!-- 第一排序规则:分数降序 -->
<xsl:sort select="score" data-type="number" order="descending"/>
<!-- 第二排序规则:姓名文本升序 -->
<xsl:sort select="name" data-type="text" order="ascending"/>
<li>
姓名:<xsl:value-of select="name"/>,分数:<xsl:value-of select="score"/>
</li>
</xsl:for-each>
</ul>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
多个xsl:sort元素的优先级按照出现的先后顺序确定,先定义的排序规则优先级更高,只有当前面的排序规则无法区分顺序时,才会使用后面的排序规则。
自定义排序规则
如果需要按照自定义的顺序排序,比如学生等级按照优秀、良好、及格、不及格的顺序排列,可以通过select属性配合自定义的表达式实现。假设XML中student节点有level子元素,XSLT代码如下:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h3>自定义等级排序</h3>
<ul>
<xsl:for-each select="students/student">
<!-- 自定义顺序映射,优秀对应1,良好对应2,以此类推 -->
<xsl:sort select="translate(level, '优秀良好及格不及格', '1234')" data-type="number"/>
<li>
姓名:<xsl:value-of select="name"/>,等级:<xsl:value-of select="level"/>
</li>
</xsl:for-each>
</ul>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
上述代码通过translate函数将等级文本转换为对应的数字,再按照数字升序排列,从而实现自定义的顺序效果。
注意事项
- xsl:sort必须作为xsl:for-each或者xsl:apply-templates的第一个子元素,否则不会生效。
- 排序时如果select表达式返回多个节点,会取第一个节点的 value 作为排序依据。
- 数值排序时一定要指定data-type为number,否则会按照文本规则排序,导致数值10排在2的前面。
- 不同XSLT处理器对lang属性的支持程度不同,如果需要跨平台使用,建议尽量不依赖特定语言的排序规则。