Неа. ElementTree использует словарь для хранения значений атрибутов, поэтому он по сути неупорядочен.
Даже DOM не гарантирует, что вы упорядочите атрибуты, и DOM раскрывает гораздо больше деталей инфо-набора XML, чем ElementTree. (Есть некоторые DOM, которые предлагают его как функцию, но это не стандарт.)
Можно ли это исправить? Может быть. Вот удар, который заменяет словарь при разборе на упорядоченный (collections.OrderedDict()
).
from xml.etree import ElementTree
from collections import OrderedDict
import StringIO
class OrderedXMLTreeBuilder(ElementTree.XMLTreeBuilder):
def _start_list(self, tag, attrib_in):
fixname = self._fixname
tag = fixname(tag)
attrib = OrderedDict()
if attrib_in:
for i in range(0, len(attrib_in), 2):
attrib[fixname(attrib_in[i])] = self._fixtext(attrib_in[i+1])
return self._target.start(tag, attrib)
>>> xmlf = StringIO.StringIO('<a b="c" d="e" f="g" j="k" h="i"/>')
>>> tree = ElementTree.ElementTree()
>>> root = tree.parse(xmlf, OrderedXMLTreeBuilder())
>>> root.attrib
OrderedDict([('b', 'c'), ('d', 'e'), ('f', 'g'), ('j', 'k'), ('h', 'i')])
Выглядит потенциально многообещающе.
>>> s = StringIO.StringIO()
>>> tree.write(s)
>>> s.getvalue()
'<a b="c" d="e" f="g" h="i" j="k" />'
Бах, сериализатор выводит их в каноническом порядке.
Это похоже на линию обвинения, в ElementTree._write
:
items.sort() # lexical order
Создание подклассов или исправлений обезьян, которые будут раздражать, так как это прямо в середине большого метода.
Если вы не сделали что-то противное, например, подкласс OrderedDict
и взломали items
, чтобы вернуть специальный подкласс list
, который игнорирует вызовы sort()
. Нет, наверное, это еще хуже, и я должен идти спать, прежде чем придумать что-нибудь более ужасное, чем это.