按元素对XML文件进行排序

时间:2015-06-18 18:56:00

标签: xml

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

<example>
    <note>
        <to>Tove</to>
        <from>Jani</from>
        <heading>Reminder</heading>
            <headb>head</head3>
            <heada>head</head3>
        <body>Don't forget me this weekend!</body>
    </note>
    <next>
        <c>blabla</c>
        <a>blabla</a>
    </next>
</example>

要:

<example>
    <next>
        <a>blabla</a>
        <c>blabla</c>
    </next>
    <note>
        <body>Don't forget me this weekend!</body>
        <from>Jani</from>
        <heading>Reminder</heading>
            <heada>head</head3>
            <headb>head</head3>
        <to>Tove</to>
    </note>
</example>

xml可以包含数千行和多个元素级别

1 个答案:

答案 0 :(得分:1)

您应该能够使用身份转换并添加xsl:sort以对name()local-name()进行排序。

示例...

XML输入(格式良好,比原版稍微复杂一点。)

<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>

XSLT 1.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>

请注意,评论和处理说明最终会浮动到排序顺序的顶部。

另请注意,如果您有混合内容(同一父级中的元素和文本节点),您可能希望跳过该元素的排序。否则,文本将在排序顺序中排在第一位(如注释和处理说明)。

这是一种跳过混合内容元素的方法(注释和处理指令输出确实发生了变化,因此您可能需要进行实验):

<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>