按元素对XML文件排序
我想按相同级别的元素按字母顺序对xml文件进行排序。这意味着,在第一级对元素进行排序,然后在每个元素内部递归地对其子元素进行排序,以此类推。它必须是多层次的,而不仅仅是一个层次(在另一个问题中解决)。例如(请忽略内容和含义):按元素对XML文件排序,xml,Xml,我想按相同级别的元素按字母顺序对xml文件进行排序。这意味着,在第一级对元素进行排序,然后在每个元素内部递归地对其子元素进行排序,以此类推。它必须是多层次的,而不仅仅是一个层次(在另一个问题中解决)。例如(请忽略内容和含义): 托弗 贾尼 提醒 头 头 这个周末别忘了我! 布拉布拉 布拉布拉 致: 布拉布拉 布拉布拉 这个周末别忘了我! 贾尼 提醒 头 头 托弗 xml可以包含数千行和多个级别的元素您应该能够使用标识转换并添加xsl:sort来对name()或local-name()进行
托弗
贾尼
提醒
头
头
这个周末别忘了我!
布拉布拉
布拉布拉
致:
布拉布拉
布拉布拉
这个周末别忘了我!
贾尼
提醒
头
头
托弗
xml可以包含数千行和多个级别的元素您应该能够使用标识转换并添加
xsl:sort
来对name()
或local-name()
进行排序
例如
XML输入(格式良好,比原始输入稍微复杂。)
托弗
贾尼
提醒
头
头
这个周末别忘了我!
布拉布拉
布拉布拉
文本
XSLT1.0
<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:sort select="local-name()"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
XML输出
<example>
<djh><!-- comment --><?PI?>
<baz>
<bar>
<baz/>
<foo/>
</bar>
<foo>
<bar/>
<baz/>
</foo>
</baz>
<foo attr="test">
<bar>
<baz>text</baz>
<foo><!--comment--></foo>
</bar>
<baz attr="test">
<bar/>
<foo/>
</baz>
</foo>
</djh>
<next>
<a>blabla</a>
<c>blabla</c>
</next>
<note>
<body>Don't forget me this weekend!</body>
<from>Jani</from>
<heada>head</heada>
<headb>head</headb>
<heading>Reminder</heading>
<to>Tove</to>
</note>
</example>
文本
布拉布拉
布拉布拉
这个周末别忘了我!
贾尼
头
头
提醒
托弗
请注意,注释和处理指令最终会浮动到排序顺序的顶部
还请注意,如果您有混合内容(同一父级中的元素和文本节点),则可能希望跳过该元素的排序。否则,文本将按排序顺序排在第一位(如注释和处理说明)
这里有一种跳过混合内容元素的方法(注释和处理指令输出会发生变化,因此您可能需要进行实验):
对于我的示例,可能的副本不起作用,因为该副本中只有一个级别。我将在另一篇文章中询问我的问题。注意,如果一个元素上有多个属性,则此解决方案会出现XTDE0410错误:无法在包含元素的子元素之后创建属性节点(attr1)(至少使用saxon)
<example>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<headb>head</headb>
<heada>head</heada>
<body>Don't forget me this weekend!</body>
</note>
<next>
<c>blabla</c>
<a>blabla</a>
</next>
<djh>
<!-- comment -->
<foo attr="test">
<bar>
<baz>text</baz>
<foo><!--comment--></foo>
</bar>
<baz attr="test">
<foo/>
<bar/>
</baz>
</foo>
<?PI?>
<baz>
<bar>
<foo/>
<baz/>
</bar>
<foo>
<bar/>
<baz/>
</foo>
</baz>
</djh>
</example>
<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:sort select="local-name()"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<example>
<djh><!-- comment --><?PI?>
<baz>
<bar>
<baz/>
<foo/>
</bar>
<foo>
<bar/>
<baz/>
</foo>
</baz>
<foo attr="test">
<bar>
<baz>text</baz>
<foo><!--comment--></foo>
</bar>
<baz attr="test">
<bar/>
<foo/>
</baz>
</foo>
</djh>
<next>
<a>blabla</a>
<c>blabla</c>
</next>
<note>
<body>Don't forget me this weekend!</body>
<from>Jani</from>
<heada>head</heada>
<headb>head</headb>
<heading>Reminder</heading>
<to>Tove</to>
</note>
</example>
<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="*[not(text())]">
<xsl:copy>
<xsl:apply-templates select="@*|node()">
<xsl:sort select="local-name()"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>