Sort xml with python by tag

python, sorting, xml

Solution

You need to:

- get the children elements for every top-level "node"

- sort them by the `tag` attribute (node's name)

- reset the child nodes of each top-level node

Sample working code:

from operator import attrgetter
from xml.etree import ElementTree as et

data = """  <root>
 <node1>
  <B>text</B>
  <A>another_text</A>
  <C>one_more_text</C>
 </node1>
 <node2>
  <C>one_more_text</C>
  <B>text</B>
  <A>another_text</A>
 </node2>
</root>"""


root = et.fromstring(data)
for node in root.findall("*"):  # searching top-level nodes only: node1, node2 ...
    node[:] = sorted(node, key=attrgetter("tag"))

print(et.tostring(root))

Prints:

<root>
 <node1>
  <A>another_text</A>
  <B>text</B>
  <C>one_more_text</C>
 </node1>
 <node2>
  <A>another_text</A>
  <B>text</B>
  <C>one_more_text</C>
  </node2>
</root>

Note that we are not using `getchildren()` method here (it is actually deprecated since Python 2.7) - using the fact that each `Element` instance is an iterable over the child nodes.

Problem

I have an xml ``` <root> <node1> <B>text</B> <A>another_text</A> <C>one_more_text</C> </node1> <node2> <C>one_more_text</C> <B>text</B> <A>another_text</A> </node2> </root> ``` I want get output like: ``` <root> <node1> <A>another_text</A> <B>text</B> <C>one_more_text</C> </node1> <node2> <A>another_text</A> <B>text</B> <C>one_more_text</C> </node2> </root> ``` I tried with some code like: ``` from xml.etree import ElementTree as et tr = et.parse(path_in) root = tr.getroot() for children in root.getchildren(): for child in children.getchildren(): # sort it tr.write(path_out) ``` I cannot use standard function `sort` and `sorted` because it sorted wrong way (not by tag). Thanks in advance.

Original source