10

anyone know of a way that I can load an XML file into and sort it and then save the file?

I have a xml file with a bunch of settings.. and now it is getting hard to manage because they are not in any natural sort order...

e.g.

<edit_screen_a>
<settings_font_size>
<edit_screen_b>
<display_screen>
<settings_font_name>

to sort to:

<display_screen>
<edit_screen_a>
<edit_screen_b>
<settings_font_name>
<settings_font_size>
ycomp
  • 8,316
  • 19
  • 57
  • 95

2 Answers2

9

You could use XSLT and run it from the command line. (I'd recommend Saxon, but Xalan would be ok.)

Here's an example...

XML Input

<doc>
  <edit_screen_a/>
  <settings_font_size/>
  <edit_screen_b/>
  <display_screen/>
  <settings_font_name/>
</doc>

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:copy>
  </xsl:template>

  <xsl:template match="doc">
    <doc>
      <xsl:apply-templates>
        <xsl:sort select="name()"/>
      </xsl:apply-templates>      
    </doc>
  </xsl:template>

</xsl:stylesheet>

XML Output

<doc>
   <display_screen/>
   <edit_screen_a/>
   <edit_screen_b/>
   <settings_font_name/>
   <settings_font_size/>
</doc>
Daniel Haley
  • 51,389
  • 6
  • 69
  • 95
  • works amazing! I put this xsl file into **Eclipse** and I just press "run" and choose my source xml and voila... almost perfect... just need to choose "format" in Eclipse to indent it all nicely again... thanks, this is really a great solution to this problem – ycomp Feb 07 '12 at 00:44
  • 1
    my memory (which isn't the best) seems to agree with my comment that it was working fine for me before... but now it doesn't seem to sort so well... maybe it is because I added something to this xml source file that the XSLT file didn't like... I am frequently updating the source file since it is a collection of strings that my program uses for localization. Any idea what sort of things could cause this XSLT file to not sort correctly? – ycomp Feb 09 '12 at 14:06
  • @ycomp - It's hard to say without examples of what isn't sorting correctly. If you update the question with a newer example, I can take a look. – Daniel Haley Feb 09 '12 at 16:13
  • it's ok, I was just wondering if there was anything you knew about off the the top of your head... – ycomp Feb 09 '12 at 16:26
  • I would have the same question for a multilevel xml file --> see http://stackoverflow.com/questions/30923547/sorting-xml-file-by-element?noredirect=1#comment49884623_30923547 – Weslor Jun 18 '15 at 20:04
1

If the accepted answer is giving you problems, consider this:

sort.xslt

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- for well formatted output -->
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="*">
        <!-- copy this node (but this does not copy the attributes ...) -->
        <xsl:copy>
            <!-- so, copy the attributes as well -->
            <xsl:copy-of select="@*"/>
            <!-- recurse on sorted (by tag name) list of child nodes -->
            <xsl:apply-templates>
                <xsl:sort select="name()"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

(Reference documentation on XSLT including the various operations used above may be found on MDN)

Compared to https://stackoverflow.com/a/9165464/5412249

  • does not assume any particular root node
  • preserves the attributes as well
  • uses a single template (and IMHO more easier to understand)

To actually apply this, on a Mac (and presumably on linux systems as well), you may use xsltproc

xsltproc sort.xslt test.xml

where, test.xml is any arbitrary xml file

  • Thanks for your solution. It works in most of the cases. I have a more complicated situation and tried to modify based on your solution, but failed. To make it simple, let say I have the xml: " Book 3 Book 2 Funny Store 001 ". , and can be sorted as expected. But for under , I would like to sort it by "Book/Name" instead of "name()"; otherwise, it is meaningless. – kzfid Oct 10 '22 at 03:47
  • What I want to achieve is to sort by node/tag name in general, but able to provide additional rule of sorting based on specific match/condition (like Books/Book example above) – kzfid Oct 10 '22 at 03:48
  • I was struggling to find a simple solution to sort XML files. Thanks @Jobin Jacob Kavalam. – Jardel Lucca Apr 07 '23 at 01:36
  • A quick note: this template is working fine with `xmlstarlet` too. – Jardel Lucca Apr 07 '23 at 01:37