我有以下函数,它完成了将 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 标记中文本数据的字符串,则必须以某种方式显式地将它们转换为整数。)
