Python 如何重写此函数以实现OrderedICT?

Python 如何重写此函数以实现OrderedICT?,python,xml,collections,lxml,Python,Xml,Collections,Lxml,我有下面的函数,它完成了将XML文件解析为字典的粗略工作 不幸的是,由于Python字典没有排序,因此我无法按照自己的意愿循环遍历节点 如何更改此设置,使其输出一个有序字典,当与for循环时,该字典反映节点的原始顺序 def simplexml_load_file(file): import collections from lxml import etree tree = etree.parse(file) root = tree.getroot()

我有下面的函数,它完成了将XML文件解析为字典的粗略工作

不幸的是,由于Python字典没有排序,因此我无法按照自己的意愿循环遍历节点

如何更改此设置,使其输出一个有序字典,当与
for
循环时,该字典反映节点的原始顺序

def simplexml_load_file(file):
    import collections
    from lxml import etree

    tree = etree.parse(file)
    root = tree.getroot()

    def xml_to_item(el):
        item = None
        if el.text:
            item = el.text
        child_dicts = collections.defaultdict(list)
        for child in el.getchildren():
            child_dicts[child.tag].append(xml_to_item(child))
        return dict(child_dicts) or item

    def xml_to_dict(el):
        return {el.tag: xml_to_item(el)}

    return xml_to_dict(root)

x = simplexml_load_file('routines/test.xml')

print x

for y in x['root']:
    print y
产出:

{'root':{
“a”:[1'],
'aa':[{'b':[{'c':['2']},'2']}],
'aaaa':[{'bb':['4']}],
“aaa”:[3'],
“AAAA”:[5']
}}
A.
aa
aaaa
aaa
AAAA
如何实现
collections.OrderedDict
,以确保获得正确的节点顺序

供参考的XML文件:


1.
2.
2.
3.
4.
5.

答案中列出了许多可能的OrderedICT实施方案:

通过复制其中一个实现,您可以创建自己的OrderedICT模块,以便在自己的代码中使用。我假设您没有访问OrderedDict的权限,因为您正在运行的Python版本

您问题的一个有趣方面是可能需要defaultdict功能。如果需要,可以实现
\uuuuu missing\uuuu
方法以获得所需的效果。

您可以使用新的
dict
子类,该子类在2.7版中添加到标准库的
集合
模块中✶
。实际上,您需要的是一个不存在的
有序的
+
defaultdict
组合,但是可以通过子类化
orderedict
来创建一个组合,如下所示:

如果您的Python版本没有
OrderedDict
,那么您应该可以使用Raymond Hettinger的ActiveState配方作为基类。

测试XML文件生成的输出如下所示:

{'root':
有序的(
[('a',['1']),
("aa","OrderedDict"("b","OrderedDict"("c","2"),"2,
('aaa',['3']),
("aaaa","OrderedDict"(""bb","4")]],,
(‘AAAA’,[‘5’]))
]
)
}
A.
aa
aaa
aaaa
AAAA
我认为这很接近你想要的

次要更新:


添加了一个
\uuuu reduce\uuu()
方法,该方法将允许正确地对类的实例进行pickle和unpickle。对于这个问题,这不是必需的,但是在一个问题中出现了。

来自martineau的配方对我有效,但是它与从DefaultDict继承的方法copy()有问题。以下方法解决了这一缺点:

class OrderedDefaultDict(OrderedDict):
    #Implementation as suggested by martineau

    def copy(self):
         return type(self)(self.default_factory, self)

请考虑,这个实现没有深度拷贝,这似乎是默认字典,而不是在大多数情况下做的正确的事情。一些修复:A)在3.x中,您需要更改

.iterms()
.items()
的调用(或者您可以使用
six
库来实现2.x/3.x兼容性b),除非您希望具有任意或不同的顺序。@smci:我已经修改了该代码,使其在Python 2.7和3.2+中都能工作。您不需要在Python 3.6+中使用它。您可以只使用defaultdict,默认情况下它维护键的顺序
class OrderedDefaultDict(OrderedDict):
    #Implementation as suggested by martineau

    def copy(self):
         return type(self)(self.default_factory, self)