如何使用XSLT和XPath按元素属性对XML进行排序
按XML元素lastname属性排序的解决方案
问题描述
需要按employee元素的lastname属性对XML文件进行排序,示例输入XML如下:
<employees> <employee firstname="Mary" lastname="Poppins" age="30" hobby="Flying"/> <employee firstname="Captain" lastname="Hook" age="40" hobby="Crocodile hunting"/> <employee firstname="Thomas" lastname="Tankengine" age="102" hobby="Steam trains"/> <employee firstname="Ant" lastname="Man" age="37" hobby="hero"/> <employee firstname="Peter" lastname="Pan" age="13" hobby="Flying"/> </employees>
期望得到的排序后XML:
<employees> <employee firstname="Captain" lastname="Hook" age="40" hobby="Crocodile hunting" /> <employee firstname="Ant" lastname="Man" age="37" hobby="hero" /> <employee firstname="Peter" lastname="Pan" age="13" hobby="Flying" /> <employee firstname="Mary" lastname="Poppins" age="30" hobby="Flying" /> <employee firstname="Thomas" lastname="Tankengine" age="102" hobby="Steam trains" /> </employees>
尝试的错误XSLT代码:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/employees"> <xsl:apply-templates select = "employee"/> </xsl:template> <xsl:template match="employee"> <xsl:apply-templates> <xsl:sort select="@lastname" order="ascending"/>" </xsl:apply-templates> <xsl:copy/> </xsl:template> </xsl:stylesheet>
问题分析
原代码存在几个核心问题:
- 未保留根节点
<employees>的结构,直接输出employee元素,缺少外层包裹 - 在
employee模板内错误地对空的子节点应用排序,而非对employee元素本身排序 <xsl:copy/>仅复制空的employee标签,丢失了原有的属性信息
修正后的XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 默认模板:复制所有节点和属性,保留原内容 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 处理根节点,对employee元素按lastname排序 --> <xsl:template match="employees"> <xsl:copy> <xsl:apply-templates select="employee"> <xsl:sort select="@lastname" order="ascending"/> </xsl:apply-templates> </xsl:copy> </xsl:template> </xsl:stylesheet>
代码说明
- 默认模板:
match="@*|node()"会匹配所有属性和节点,复制它们并处理内部内容,确保原XML的结构和属性不丢失。 - 根节点处理:匹配
<employees>节点后,先复制自身,再对其下的employee元素应用模板,同时通过<xsl:sort>指定按lastname属性升序排序。 - 排序逻辑:
<xsl:sort select="@lastname"直接定位到employee的lastname属性,实现按姓氏字母顺序排序。
使用该XSLT转换后,即可得到符合预期的排序结果。
内容的提问来源于stack exchange,提问作者Andy L
相关产品推荐
相关产品推荐

