Skip to main content
 首页 » 编程设计

python之我如何映射到字典而不是列表

2025年05月04日14cmt

我有以下函数,它完成了将 lxml 对象映射到字典的基本工作...

from lxml import etree  
 
tree = etree.parse('file.xml') 
root = tree.getroot() 
 
def xml_to_dict(el): 
    d={} 
    if el.text: 
        print '***write tag as string' 
        d[el.tag] = el.text 
    else: 
        d[el.tag] = {} 
    children = el.getchildren() 
    if children: 
        d[el.tag] = map(xml_to_dict, children) 
    return d 
 
    v = xml_to_dict(root) 

此刻它给了我....

>>>print v 
{'root': [{'a': '1'}, {'a': [{'b': '2'}, {'b': '2'}]}, {'aa': '1a'}]} 

但我想....

>>>print v 
{'root': {'a': ['1', {'b': [2, 2]}], 'aa': '1a'}} 

如何重写函数 xml_to_dict(el) 以获得所需的输出?

为了清楚起见,这是我正在解析的 xml。

<root> 
    <a>1</a> 
    <a> 
        <b>2</b> 
        <b>2</b> 
    </a> 
    <aa>1a</aa> 
</root> 

谢谢:)

请您参考如下方法:

嗯,map() 总是会返回一个列表,所以简单的答案是“不要使用 map()”。相反,通过遍历 children 并将 xml_to_dict(child) 的结果分配给您要使用的字典键,可以像现在这样构建一个字典。看起来您想使用标签作为键并将值作为带有该标签的项目列表,因此它会变成类似这样的内容:

import collections 
from lxml import etree 
 
tree = etree.parse('file.xml') 
root = tree.getroot() 
 
def xml_to_dict(el): 
    d={} 
    if el.text: 
        print '***write tag as string' 
        d[el.tag] = el.text 
    child_dicts = collections.defaultdict(list) 
    for child in el.getchildren(): 
        child_dicts[child.tag].append(xml_to_dict(child)) 
    if child_dicts: 
        d[el.tag] = child_dicts 
    return d 
 
xml_to_dict(root) 

这会将字典中的标记条目保留为默认字典;如果你出于某种原因想要一个普通的字典,使用 d[el.tag] = dict(child_dicts)。请注意,与以前一样,如果标签同时具有文本和子标签,则文本不会出现在字典中。您可能需要为您的字典考虑一种不同的布局来应对这种情况。

编辑:

将在您改写的问题中产生输出的代码不会在 xml_to_dict 中递归——因为您只需要外部元素的字典,而不是所有子标签的字典。所以,你会使用类似的东西:

import collections 
from lxml import etree 
 
tree = etree.parse('file.xml') 
root = tree.getroot() 
 
def xml_to_item(el): 
    if el.text: 
        print '***write tag as string' 
        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)} 
 
print xml_to_dict(root) 

这仍然不能很好地处理带有文本和子项的标签,它会将 collections.defaultdict(list) 变成一个普通的字典,所以输出(几乎)如你所料:

***write tag as string 
***write tag as string 
***write tag as string 
***write tag as string 
***write tag as string 
***write tag as string 
{'root': {'a': ['1', {'b': ['2', '2']}], 'aa': ['1a']}} 

(如果您确实需要整数而不是 b 标记中文本数据的字符串,则必须以某种方式显式地将它们转换为整数。)