如何重写此函数以实现OrderedDict?

我有以下功能,可以完成将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'],

    'aaaaa': ['5']

}}


a

aa

aaaa

aaa

aaaaa

我如何实现collections.OrderedDict以便可以确定节点的正确顺序?


XML文件供参考:


<root>

    <a>1</a>

    <aa>

        <b>

            <c>2</c>

        </b>

        <b>2</b>

    </aa>

    <aaa>3</aaa>

    <aaaa>

        <bb>4</bb>

    </aaaa>

    <aaaaa>5</aaaaa>

</root>


桃花长相依
浏览 533回答 3
3回答

料青山看我应如是

你可以使用新的将其加入到标准库的子模块2.7版本✶。实际上,您需要的是一个不存在的+ 组合-但可以通过如下所示的子类创建一个+ 组合:OrderedDictdictcollectionsOrdereddefaultdictOrderedDict✶如果您的Python版本没有该版本,则OrderedDict应该可以使用Raymond Hettinger的Py2.4 ActiveState食谱的有序词典作为基类。import collectionsclass OrderedDefaultdict(collections.OrderedDict):&nbsp; &nbsp; """ A defaultdict with OrderedDict as its base class. """&nbsp; &nbsp; def __init__(self, default_factory=None, *args, **kwargs):&nbsp; &nbsp; &nbsp; &nbsp; if not (default_factory is None&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; or isinstance(default_factory, collections.Callable)):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise TypeError('first argument must be callable or None')&nbsp; &nbsp; &nbsp; &nbsp; super(OrderedDefaultdict, self).__init__(*args, **kwargs)&nbsp; &nbsp; &nbsp; &nbsp; self.default_factory = default_factory&nbsp; # called by __missing__()&nbsp; &nbsp; def __missing__(self, key):&nbsp; &nbsp; &nbsp; &nbsp; if self.default_factory is None:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise KeyError(key,)&nbsp; &nbsp; &nbsp; &nbsp; self[key] = value = self.default_factory()&nbsp; &nbsp; &nbsp; &nbsp; return value&nbsp; &nbsp; def __reduce__(self):&nbsp; # optional, for pickle support&nbsp; &nbsp; &nbsp; &nbsp; args = (self.default_factory,) if self.default_factory else tuple()&nbsp; &nbsp; &nbsp; &nbsp; return self.__class__, args, None, None, self.iteritems()&nbsp; &nbsp; def __repr__(self):&nbsp; # optional&nbsp; &nbsp; &nbsp; &nbsp; return '%s(%r, %r)' % (self.__class__.__name__, self.default_factory,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;list(self.iteritems()))def simplexml_load_file(file):&nbsp; &nbsp; from lxml import etree&nbsp; &nbsp; tree = etree.parse(file)&nbsp; &nbsp; root = tree.getroot()&nbsp; &nbsp; def xml_to_item(el):&nbsp; &nbsp; &nbsp; &nbsp; item = el.text or None&nbsp; &nbsp; &nbsp; &nbsp; child_dicts = OrderedDefaultdict(list)&nbsp; &nbsp; &nbsp; &nbsp; for child in el.getchildren():&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; child_dicts[child.tag].append(xml_to_item(child))&nbsp; &nbsp; &nbsp; &nbsp; return collections.OrderedDict(child_dicts) or item&nbsp; &nbsp; def xml_to_dict(el):&nbsp; &nbsp; &nbsp; &nbsp; return {el.tag: xml_to_item(el)}&nbsp; &nbsp; return xml_to_dict(root)x = simplexml_load_file('routines/test.xml')print(x)for y in x['root']:&nbsp; &nbsp; print(y)测试XML文件产生的输出如下所示:{'root':&nbsp; &nbsp; OrderedDict(&nbsp; &nbsp; &nbsp; &nbsp; [('a', ['1']),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;('aa', [OrderedDict([('b', [OrderedDict([('c', ['2'])]), '2'])])]),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;('aaa', ['3']),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;('aaaa', [OrderedDict([('bb', ['4'])])]),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;('aaaaa', ['5'])&nbsp; &nbsp; &nbsp; &nbsp; ]&nbsp; &nbsp; )}aaaaaaaaaaaaaaa我认为这接近您想要的。小更新:添加了一种__reduce__()方法,该方法将允许对类的实例进行正确的酸洗和酸洗。这个问题不是必需的,但是是类似的问题。

眼眸繁星

martineau的食谱对我有用,但是从DefaultDict继承的copy()方法有问题。以下方法可解决此缺陷:class OrderedDefaultDict(OrderedDict):&nbsp; &nbsp; #Implementation as suggested by martineau&nbsp; &nbsp; def copy(self):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return type(self)(self.default_factory, self)请考虑,此实现没有深度复制,这对于默认词典来说尤其如此,在大多数情况下是正确的选择
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python