Возможно, это то, что вам нужно.
Я добавил пример документа в исходный код, но вы можете загрузить XML с диска или куда угодно.
Идея состоит в том, чтобы иметь рекурсивную функцию, которая принимает функцию произвольного условия (предиката) и sort
ключевую функцию; таким образом, вы можете выбрать, какие деревья должны быть переупорядочены - или, если вы хотите просто переупорядочить все, это может быть функция, которая всегда возвращает True.
import xml.etree.ElementTree as etree
def sort_tree(node, sort_cond, sort_key):
# If this node matches the condition,
if sort_cond(node):
# ... sort the children and reapply into the node.
node[:] = sorted(node, key=sort_key)
# Recurse down the tree.
for child in node:
sort_tree(child, sort_cond, sort_key)
tree = etree.XML("""
<document>
<x name="xxsomething">
<a name="BBB">some thing bbb</a>
<a name="AAA">aaa some thing</a>
<a name="CCC">some ccc thing</a>
</x>
<x name="aarandom">
<a name="ZXY">asdf</a>
<a name="888">ghkj</a>
<a name="uuu">tyiu</a>
</x>
</document>
""")
sort_tree(
tree,
sort_cond=lambda node: all(child.tag == "a" for child in node),
sort_key=lambda node: node.get("name"),
)
print(etree.tostring(tree, encoding='unicode'))
Вывод:
<document>
<x name="xxsomething">
<a name="AAA">aaa some thing</a>
<a name="BBB">some thing bbb</a>
<a name="CCC">some ccc thing</a>
</x>
<x name="aarandom">
<a name="888">ghkj</a>
<a name="ZXY">asdf</a>
<a name="uuu">tyiu</a>
</x>
</document>
(Обратите внимание, что теги x
не были переупорядочены, даже если они в неправильном порядке «имен», поскольку функция cond
применяется только в том случае, если все дочерние элементы узла являются a
узлами.)