使用XSLT重写XML树:按item的name属性排序不同父节点元素的问题
解决方案:用XSLT实现XML中
<item>元素按name属性排序 嘿,这个问题用XSLT就能完美解决——这是处理XML结构转换和排序的首选工具。我分两种常见的需求场景给你写示例:
场景1:提取所有<item>元素并按name排序导出
如果你的目标是把所有层级的<item>都提取出来,按name属性字母序排列后输出,用下面的XSLT:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <!-- 匹配根节点,启动处理 --> <xsl:template match="/"> <sorted-items> <!-- 遍历所有item元素,按name属性排序 --> <xsl:for-each select="//item"> <xsl:sort select="@name" data-type="text" order="ascending"/> <!-- 复制整个item节点(包括子元素和属性) --> <xsl:copy-of select="."/> </xsl:for-each> </sorted-items> </xsl:template> </xsl:stylesheet>
执行这个XSLT后,你会得到一个包含所有排序后item的新XML:
<sorted-items> <item name="aaa">...</item> <item name="bbb">...</item> <item name="ccc">...</item> <item name="ddd">...</item> <item name="eee">...</item> <item name="fff">...</item> </sorted-items>
场景2:保持原XML层级结构,仅对每个节点下的<item>排序
如果你想保留原来的XML嵌套结构,只是让每个父节点下的<item>按name排序,用这个XSLT:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <!-- 递归复制所有非item元素的结构 --> <xsl:template match="*[not(self::item)]"> <xsl:copy> <xsl:copy-of select="@*"/> <!-- 先处理当前节点下的非item子元素 --> <xsl:apply-templates select="*[not(self::item)]"/> <!-- 对当前节点下的item按name排序后输出 --> <xsl:for-each select="item"> <xsl:sort select="@name" data-type="text" order="ascending"/> <xsl:copy-of select="."/> </xsl:for-each> </xsl:copy> </xsl:template> <!-- 不需要单独处理item,因为上面的模板已经覆盖了 --> </xsl:stylesheet>
这个XSLT会保留原有的<cat>、<cat2>等层级结构,只把每个节点下的item排序。比如原<cat5>下的item会变成aaa在前,fff在后;<cat>下的ccc位置不变(因为它是唯一的item)。
怎么执行这个XSLT?
你可以用很多工具来运行XSLT转换:
- 命令行工具:比如
xsltproc(Linux/macOS自带),执行命令:xsltproc your-transform.xsl your-input.xml > sorted-output.xml - 编程语言:Python可以用
lxml库,Java用javax.xml.transform包,C#用XslCompiledTransform类,都能轻松实现。
内容的提问来源于stack exchange,提问作者Arkahys
相关产品推荐
相关产品推荐

