Use Groovy to Sort XML File

groovy, sorting

Solution

Here's a modification to @dmahapatro's answer that preserves the nested node structure.

import groovy.xml.MarkupBuilder

String xml = '''
<List>
    <Person name="fff"/>
    <Person name="ggg">
        <PhoneNum>
            <AreaCode>555</AreaCode>
            <Number>1234567</Number>
        </PhoneNum>
    </Person>
    <Person name="eee"/>
    <Person name="ccc"/>
    <Person name="jjj"/>
    <Person name="ddd">
        <PhoneNum>
            <AreaCode>555</AreaCode>
            <Number>7654321</Number>
        </PhoneNum>
    </Person>
    <Person name="aaa"/>
    <Person name="bbb"/>
    <Person name="ttt"/>
</List>
'''

def rootNode = new XmlParser().parseText(xml)
rootNode.children().sort(true) {it.attribute('name')}
new XmlNodePrinter().print(rootNode)

Here's what's going on:

- Using `XmlParser` instead of `XmlSlurper` generates nodes that can be printed using `XmlNodePrinter`.

- The children of the node are sorted by name using `sort {it.attribute('name')}`

- The `true` attribute to sort mutates the underlying list, which reorders the child nodes.

- The `XmlNodePrinter` prints the re-sorted xml document to standard out.

Problem

Is there a way I can sort an xml file base on certain attributes with Groovy? Here's my xml ``` <List> <Person name="fff"/> <Person name="ggg"> <PhoneNum> <AreaCode>555</AreaCode> <Number>1234567</Number> </PhoneNum> </Person> <Person name="eee"/> <Person name="ccc"/> <Person name="jjj"/> <Person name="ddd"> <PhoneNum> <AreaCode>555</AreaCode> <Number>7654321</Number> </PhoneNum> </Person> <Person name="aaa"/> <Person name="bbb"/> <Person name="ttt"/> </List> ``` and I want the output to be ``` <List> <Person name="aaa"/> <Person name="bbb"/> <Person name="ccc"/> <Person name="ddd"> <PhoneNum> <AreaCode>555</AreaCode> <Number>7654321</Number> </PhoneNum> </Person> <Person name="eee"/> <Person name="fff"/> <Person name="ggg"> <PhoneNum> <AreaCode>555</AreaCode> <Number>1234567</Number> </PhoneNum> </Person> <Person name="jjj"/> <Person name="ttt"/> </List> ``` I've looked into XMLSlurper but I can't quite seem to figure out how to do this.

Original source