#python #xml #sorting
#python #xml #сортировка
Вопрос:
У меня есть 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>
Я хочу получить вывод, подобный:
<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>
Я попытался с помощью некоторого кода, подобного:
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)
Я не могу использовать стандартную функцию sort
и sorted
, потому что она отсортирована неправильно (не по тегу).
Заранее спасибо.
Ответ №1:
Вам нужно:
- получите дочерние элементы для каждого «узла» верхнего уровня
- сортируйте их по
tag
атрибуту (имя узла) - сброс дочерних узлов каждого узла верхнего уровня
Пример рабочего кода:
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))
С принтами:
<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>
Обратите внимание, что здесь мы не используем getchildren()
метод (на самом деле он устарел начиная с Python 2.7) — используя тот факт, что каждый Element
экземпляр является итеративным для дочерних узлов.
Ответ №2:
Из аналогичного вопроса :
from lxml import etree
data = """<X>
<X03>3</X03>
<X02>2</X02>
<A>
<A02>Y</A02>
<A01>X</A01>
<A03>Z</A03>
</A>
<X01>1</X01>
<B>
<B01>Z</B01>
<B02>X</B02>
<B03>C</B03>
</B>
</X>"""
doc = etree.XML(data,etree.XMLParser(remove_blank_text=True))
for parent in doc.xpath('//*[./*]'): # Search for parent elements
parent[:] = sorted(parent,key=lambda x: x.tag)
print etree.tostring(doc,pretty_print=True)
Результат :
<X>
<A>
<A01>X</A01>
<A02>Y</A02>
<A03>Z</A03>
</A>
<B>
<B01>Z</B01>
<B02>X</B02>
<B03>C</B03>
</B>
<X01>1</X01>
<X02>2</X02>
<X03>3</X03>
</X>
Вы можете найти более подробную информацию здесь:http://effbot.org/zone/element-sort.htm