python - Can ElementTree be told to preserve the order of attributes? -
i've written simple filter in python using elementtree munge contexts of xml files. , works, more or less.
but reorders attributes of various tags, , i'd not that.
does know switch can throw make keep them in specified order?
context this
i'm working , on particle physics tool has complex, oddly limited configuration system based on xml files. among many things setup way paths various static data files. these paths hardcoded existing xml , there no facilities setting or varying them based on environment variables, , in our local installation in different place.
this isn't disaster because combined source- , build-control tool we're using allows shadow files local copies. thought data fields static xml isn't, i've written script fixing paths, attribute rearrangement diffs between local , master versions harder read necessary.
this first time taking elementtree spin (and fifth or sixth python project) maybe i'm doing wrong.
abstracted simplicity code looks this:
tree = elementtree.elementtree.parse(inputfile) = tree.getiterator() e in i: e.text = filter(e.text) tree.write(outputfile)
reasonable or dumb?
related links:
with @bobince's answer , these 2 (setting attribute order, overriding module methods)
i managed monkey patched it's dirty , i'd suggest using module better handles scenario when isn't possibility:
# ======================================================================= # monkey patch elementtree import xml.etree.elementtree et def _serialize_xml(write, elem, encoding, qnames, namespaces): tag = elem.tag text = elem.text if tag et.comment: write("<!--%s-->" % et._encode(text, encoding)) elif tag et.processinginstruction: write("<?%s?>" % et._encode(text, encoding)) else: tag = qnames[tag] if tag none: if text: write(et._escape_cdata(text, encoding)) e in elem: _serialize_xml(write, e, encoding, qnames, none) else: write("<" + tag) items = elem.items() if items or namespaces: if namespaces: v, k in sorted(namespaces.items(), key=lambda x: x[1]): # sort on prefix if k: k = ":" + k write(" xmlns%s=\"%s\"" % ( k.encode(encoding), et._escape_attrib(v, encoding) )) #for k, v in sorted(items): # lexical order k, v in items: # monkey patch if isinstance(k, et.qname): k = k.text if isinstance(v, et.qname): v = qnames[v.text] else: v = et._escape_attrib(v, encoding) write(" %s=\"%s\"" % (qnames[k], v)) if text or len(elem): write(">") if text: write(et._escape_cdata(text, encoding)) e in elem: _serialize_xml(write, e, encoding, qnames, none) write("</" + tag + ">") else: write(" />") if elem.tail: write(et._escape_cdata(elem.tail, encoding)) et._serialize_xml = _serialize_xml collections import ordereddict class orderedxmltreebuilder(et.xmltreebuilder): def _start_list(self, tag, attrib_in): fixname = self._fixname tag = fixname(tag) attrib = ordereddict() if attrib_in: in range(0, len(attrib_in), 2): attrib[fixname(attrib_in[i])] = self._fixtext(attrib_in[i+1]) return self._target.start(tag, attrib) # =======================================================================
then in code:
tree = et.parse(pathtofile, orderedxmltreebuilder())
Comments
Post a Comment