Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preserve order of attributes when modifying with minidom

Is there a way I can preserve the original order of attributes when processing XML with minidom?

Say I have: <color red="255" green="255" blue="233" /> when I modify this with minidom the attributes are rearranged alphabetically blue, green, and red. I'd like to preserve the original order.

I am processing the file by looping through the elements returned by elements = doc.getElementsByTagName('color') and then I do assignments like this e.attributes["red"].value = "233".

like image 545
Fredrick Avatar asked Mar 19 '09 15:03

Fredrick


3 Answers

To keep the attribute order I made this slight modification in minidom:

from collections import OrderedDict

In the Element class :

__init__(...)
    self._attrs = OrderedDict()
    #self._attrs = {}
writexml(...)
    #a_names.sort()

Now this will only work with Python 2.7+ And I'm not sure if it actually works => Use at your own risks...

And please note that you should not rely on attribute order:

Note that the order of attribute specifications in a start-tag or empty-element tag is not significant.

like image 111
dudu Avatar answered Nov 13 '22 06:11

dudu


Is there a way I can preserve the original order of attributes when processing XML with minidom?

With minidom no, the datatype used to store attributes is an unordered dictionary. pxdom can do it, though it is considerably slower.

like image 9
bobince Avatar answered Nov 13 '22 07:11

bobince


It is clear that xml attribute are not ordered. I just have found this strange behavior !

It seems that this related to a sort added in xml.dom.minidom.Element.writexml function !!

class Element(Node):
... snip ...

    def writexml(self, writer, indent="", addindent="", newl=""):
        # indent = current indentation
        # addindent = indentation to add to higher levels
        # newl = newline string
        writer.write(indent+"<" + self.tagName)

        attrs = self._get_attributes()
        a_names = attrs.keys()
        a_names.sort()
--------^^^^^^^^^^^^^^
        for a_name in a_names:
            writer.write(" %s=\"" % a_name)
            _write_data(writer, attrs[a_name].value)
            writer.write("\"")

Removing the line restore a behavior which keep the order of the original document. It is a good idea when you have to check with diff tools that there is not a mistake in your code.

like image 3
VGE Avatar answered Nov 13 '22 06:11

VGE