Question

The following code takes an XML and converts it into a dictionary:

import xml.etree.cElementTree as et
tree = et.parse(path_to_xml)
root = tree.getroot()      
xml_dict = etree_to_dict(root)

where:

def etree_to_dict(t):
    d = {t.tag: {} if t.attrib else None}
    children = list(t)
    if children:
        dd = defaultdict(list)

        for dc in map(etree_to_dict, children):
            for k, v in dc.iteritems():
                dd[k].append(v)
        d = {t.tag: {k:v[0] if len(v) == 1 else v for k, v in dd.iteritems()}}

    if t.attrib:
        d[t.tag].update(('@' + k, v) for k, v in t.attrib.iteritems())
    if t.text:
        text = t.text.strip()
        if children or t.attrib:
            if text:
              d[t.tag]['#text'] = text
        else:
            d[t.tag] = text
    return d

However, the function above returns an unordered dictionary. I would like it to instead return an ordered dictionary. It isn't clear to me how to replace some of the dictionary comprehensions and defaultdict calls for this.

An example of an input could be this one: http://www.w3schools.com/xml/plant_catalog.xml

Any thoughts on how to replace

Was it helpful?

Solution

It's fairly simple to replace dict comprehensions and defaultdict operations with equivalent operations on collections.OrderedDict instances. Note that OrderedDicts are a bit slower than regular dicts (and defaultdicts), but only by a constant factor (they still have the same big-O performance).

Rather than a defaultdict, create an OrderedDict and use setdefault to create default values when necessary:

dd = OrderedDict()

for dc in map(etree_to_dict, children):
    for k, v in dc.iteritems():
        dd.setdefault(k, []).append(v)

Replace dict comprehensions with a calls to OrderedDict with a list or generator expression that yields (key, value) tuples, e.g.:

d = OrderedDict([(t.tag, OrderedDict((k, v[0] if len(v) == 1 else v)
                                     for k, v in dd.iteritems()))])
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top