4

I'm using Python and ElementTree to modify some attributes of XML files. Everything works fine, but the order of attributes of the modified files is not anymore the same as it was before. To maintain the order, I tried it with this hack:

ordered_keys = ('t', 's', 'sp', 'id', 'le')

for k in ordered_keys:
    if k in sp.attrib:
        sp.set(k, sp.attrib[k])

tree.write("output.xml", encoding='utf-8', xml_declaration=True)

But it didn't work either :( Have you got any idea to maintain the order?

Cristian Ciupitu
  • 20,270
  • 7
  • 50
  • 76
MarkF6
  • 493
  • 6
  • 21
  • 2
    XML infoset specification (http://www.w3.org/TR/xml-infoset/#infoitem.element) states that attributes in an element constitute an *unordered* collection. I. e., the order has no significance, and implementations are allowed to reorder the attributes freely. – ach Jun 23 '14 at 14:10

2 Answers2

2

XML node attributes are unordered by definition. In other words, it doesn't matter in which order attributes are followed.

See also:

Community
  • 1
  • 1
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
2

For a computer, there's no need to order the elements - it's not necessary, and an unordered dictionary makes sense.

However, if you want them to be ordered for a user to read, this isn't a violation of the spec. It looks like you can do this by hacking (or forking) the standard ElementTree a small amount. The file is ElementTree.py in xml.etree under lib.

First, the Element object by default uses a standard, unordered dictionary for the attributes. Change it to use an ordered dictionary. That class definition is ~line 450 in my python 2.6 one. In py2.7+ this is in collections, in py2.6 you can find a backported implementation on the web.

Second, by default it sorts the keys when it writes (to help make sense of them). You need to turn this off. It's in ElementTree.write(), and the line just says something like items.sort(). Comment that out. This is line ~688 in the python 2.6 version.

Those two together allow you to create a tree and write the attributes in your own order. If you want to read files in order too (I haven't actually tested this part), you also need to modify the parser:

looks like the functions are _start and _start_list (inside XMLTreeBuilder) which both declare attrib = {}, change that as well to be an ordered dictionary.

Corley Brigman
  • 11,633
  • 5
  • 33
  • 40
  • Thanks for this comment! For my purpose, I think this is too complicate. But another idea I just had: is it possible to simply add all attributes as a line of strings? – MarkF6 Jun 23 '14 at 14:40
  • Very good answer! @MarkF6 could you describe why do you need attributes in the specific order? – alecxe Jun 23 '14 at 14:57
  • it's possible, instead of attributes, to add subtags. i.e. instead of ``, do something like `xy`. they will be forced to be ordered, but you access them differently. otherwise, they are pretty much equivalent. – Corley Brigman Jun 24 '14 at 02:04