Python 为什么';从lxml常见问题解答工作中得到什么?

Python 为什么';从lxml常见问题解答工作中得到什么?,python,lxml,Python,Lxml,在中,它们提供了以下内容: >>> r = requests.get('http://localhost:8983/solr/admin/cores?action=STATUS') >>> xml_dict = recursive_dict(lxml.etree.parse(StringIO.StringIO(r.content))) AttributeError: 'lxml.etree._ElementTree' object has no attrib

在中,它们提供了以下内容:

>>> r = requests.get('http://localhost:8983/solr/admin/cores?action=STATUS')
>>> xml_dict = recursive_dict(lxml.etree.parse(StringIO.StringIO(r.content)))

AttributeError: 'lxml.etree._ElementTree' object has no attribute 'tag'
如何将XML树映射到dict的dict中?

我很高兴你问:

但是,当我尝试使用它时,我得到以下结果:

>>> r = requests.get('http://localhost:8983/solr/admin/cores?action=STATUS')
>>> xml_dict = recursive_dict(lxml.etree.parse(StringIO.StringIO(r.content)))

AttributeError: 'lxml.etree._ElementTree' object has no attribute 'tag'

是否缺少将ElementTree转换为元素的步骤?

lxml.etree.parse
返回一个
ElementTree
对象,而不是
元素
对象。从:

ElementTree主要是围绕具有根的树的文档包装器 节点。它提供了两种序列化和通用的方法 文件处理

ElementTree.getroot()
返回文档的根元素:

xml_doc = lxml.etree.parse(StringIO.StringIO(r.content))
xml_dict = recursive_dict(xml_doc.getroot())
编辑

下面是一个可能更适合的
递归dict
变体:

def recursive_dict(element):
    retval = {}
    retval["tag"] = element.tag
    if element.text:
        retval["text"] = element.text

    if element.tail:
        retval["tail"] = element.tail

    if element.attrib:
        retval["attributes"] = element.attrib

    if len(element) > 0:
        retval["children"] = [recursive_dict(child_element) for child_element in element]

    return retval

我确实意识到我在这方面已经晚了大约7.5年,但次优的实现仍然没有改变,我想在这里分享我的解决方案,因为在寻找有关这方面的答案时,它是一个突出的搜索结果,最终可能会有人发现它很有用

对于我的用例,我想要一个介于FAQ和codeape之间的版本。此版本允许仅通过其标记访问子节点,但如果有多个子节点具有相同的标记,则将有一个字典列表,而不仅仅是最后一个值的字典。如果你需要更多的铃铛和口哨,它也应该很容易适应

这就是我最终使用的:

def递归命令(元素):
“”“获取lxml元素并返回相应的嵌套python字典。
如果有多个子元素具有相同的标记,它将有一个它们的列表。
改进https://lxml.de/FAQ.html#how-can-i-map-an-xml-tree-in-a-dict-of-dicts”“”
#普通大小写只返回元素文本。
如果len(元素)==0:
返回元素.text
#嵌套大小写返回正确的字典。
其他:
retval={}
对于元素中的子元素:
#已计算递归调用,但尚未放置。
递归=递归(子)
#没有以前的条目意味着它现在是单个条目。
如果child.tag不在(retval)中:
retval[child.tag]=递归
#以前的单个条目表示它现在是一个列表。
elif类型(retval[child.tag])不是列表:
oldval=retval[child.tag]
retval[child.tag]=[oldval,recurse]
#上一个列表条目意味着添加列表。
其他:
oldlist=retval[child.tag]
retval[child.tag]=oldlist+[recurse]
返回返回

Hm,这会停止
AttributeError
,但结果dict与XML文档本身相比相当贫乏。递归dict非常有限。例如:a)没有属性值b)如果一个元素有两个(或更多)具有相同标记名的子元素,那么dict中只会有一个子元素。可以很容易地创建一个更好的递归dict(),它将子元素作为列表,将属性作为每个节点的单独dict。是的,奇怪的是,它在FAQ中的格式如此糟糕。谢谢。