使用ElementTree将xml转换为字典

OHL*_*ÁLÁ 28 python xml dictionary elementtree

我正在寻找使用ElementTree的XML到字典解析器,我已经找到了一些,但它们排除了属性,在我的情况下,我有很多属性.

K3-*_*rnc 38

以下XML-to-Python-dict片段解析实体以及遵循此XML-to-JSON"规范"的属性:

from collections import defaultdict

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.items():
                dd[k].append(v)
        d = {t.tag: {k: v[0] if len(v) == 1 else v
                     for k, v in dd.items()}}
    if t.attrib:
        d[t.tag].update(('@' + k, v)
                        for k, v in t.attrib.items())
    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
Run Code Online (Sandbox Code Playgroud)

它用于:

from xml.etree import cElementTree as ET
e = ET.XML('''
<root>
  <e />
  <e>text</e>
  <e name="value" />
  <e name="value">text</e>
  <e> <a>text</a> <b>text</b> </e>
  <e> <a>text</a> <a>text</a> </e>
  <e> text <a>text</a> </e>
</root>
''')

from pprint import pprint

d = etree_to_dict(e)

pprint(d)
Run Code Online (Sandbox Code Playgroud)

此示例的输出(按照上面链接的"规范")应该是:

{'root': {'e': [None,
                'text',
                {'@name': 'value'},
                {'#text': 'text', '@name': 'value'},
                {'a': 'text', 'b': 'text'},
                {'a': ['text', 'text']},
                {'#text': 'text', 'a': 'text'}]}}
Run Code Online (Sandbox Code Playgroud)

不一定很漂亮,但它是明确的,更简单的XML输入导致更简单的JSON.:)


更新

如果你想反过来,从JSON/dict发出一个XML字符串,你可以使用:

try:
  basestring
except NameError:  # python3
  basestring = str

def dict_to_etree(d):
    def _to_etree(d, root):
        if not d:
            pass
        elif isinstance(d, str):
            root.text = d
        elif isinstance(d, dict):
            for k,v in d.items():
                assert isinstance(k, str)
                if k.startswith('#'):
                    assert k == '#text' and isinstance(v, str)
                    root.text = v
                elif k.startswith('@'):
                    assert isinstance(v, str)
                    root.set(k[1:], v)
                elif isinstance(v, list):
                    for e in v:
                        _to_etree(e, ET.SubElement(root, k))
                else:
                    _to_etree(v, ET.SubElement(root, k))
        else:
            assert d == 'invalid type', (type(d), d)
    assert isinstance(d, dict) and len(d) == 1
    tag, body = next(iter(d.items()))
    node = ET.Element(tag)
    _to_etree(body, node)
    return node

print(ET.tostring(dict_to_etree(d)))
Run Code Online (Sandbox Code Playgroud)

  • 有反转(dict - > xml)转换的例子吗? (3认同)
  • 正如@Basj所说 - 这是我曾经尝试过的最好的XML-> dict实现.我尝试了很多. (3认同)
  • 这是我用过的最好的xml - > dict之一(有很多:`xmltodict`,几个网站上的几个食谱等) (2认同)

Fre*_*Foo 26

def etree_to_dict(t):
    d = {t.tag : map(etree_to_dict, t.iterchildren())}
    d.update(('@' + k, v) for k, v in t.attrib.iteritems())
    d['text'] = t.text
    return d
Run Code Online (Sandbox Code Playgroud)

打电话给

tree = etree.parse("some_file.xml")
etree_to_dict(tree.getroot())
Run Code Online (Sandbox Code Playgroud)

只要您实际上没有属性text,这就可以工作; 如果这样做,则更改函数体中的第三行以使用其他键.此外,您无法使用此处理混合内容.

(在LXML上测试过.)

  • 我在iterchildren中遇到了一个错误所以我改为getchildren,这个例子我得到了属性,但是节点值是空的,例如:{'Tag':'Lidars','lidars_list':[{'positive_towards_LOS' :'false','scanner_3D':'true','lidar':[{'name':[]},名字是LNAC但是我得到一个空字典 (5认同)

alb*_*rji 6

对于将 XML 与 Python 字典进行转换,xmltodict对我来说非常有用:

import xmltodict

xml = '''
<root>
  <e />
  <e>text</e>
  <e name="value" />
  <e name="value">text</e>
  <e> <a>text</a> <b>text</b> </e>
  <e> <a>text</a> <a>text</a> </e>
  <e> text <a>text</a> </e>
</root>
'''

xdict = xmltodict.parse(xml)
Run Code Online (Sandbox Code Playgroud)

xdict 现在看起来像

OrderedDict([('root',
              OrderedDict([('e',
                            [None,
                             'text',
                             OrderedDict([('@name', 'value')]),
                             OrderedDict([('@name', 'value'),
                                          ('#text', 'text')]),
                             OrderedDict([('a', 'text'), ('b', 'text')]),
                             OrderedDict([('a', ['text', 'text'])]),
                             OrderedDict([('a', 'text'),
                                          ('#text', 'text')])])]))])
Run Code Online (Sandbox Code Playgroud)

如果您的 XML 数据不是原始字符串/字节形式,而是某些 ElementTree 对象,则只需将其打印为字符串并再次使用 xmldict.parse 即可。例如,如果您使用 lxml 来处理 XML 文档,那么

from lxml import etree
e = etree.XML(xml)
xmltodict.parse(etree.tostring(e))
Run Code Online (Sandbox Code Playgroud)

将产生与上面相同的字典。