按元素对XML文件排序

按元素对XML文件排序,xml,Xml,我想按相同级别的元素按字母顺序对xml文件进行排序。这意味着,在第一级对元素进行排序,然后在每个元素内部递归地对其子元素进行排序,以此类推。它必须是多层次的,而不仅仅是一个层次(在另一个问题中解决)。例如(请忽略内容和含义): 托弗 贾尼 提醒 头 头 这个周末别忘了我! 布拉布拉 布拉布拉 致: 布拉布拉 布拉布拉 这个周末别忘了我! 贾尼 提醒 头 头 托弗 xml可以包含数千行和多个级别的元素您应该能够使用标识转换并添加xsl:sort来对name()或local-name()进行

我想按相同级别的元素按字母顺序对xml文件进行排序。这意味着,在第一级对元素进行排序,然后在每个元素内部递归地对其子元素进行排序,以此类推。它必须是多层次的,而不仅仅是一个层次(在另一个问题中解决)。例如(请忽略内容和含义):


托弗
贾尼
提醒
头
头
这个周末别忘了我!
布拉布拉
布拉布拉
致:


布拉布拉
布拉布拉
这个周末别忘了我!
贾尼
提醒
头
头
托弗

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>