xmltodict处理同名节点需设force_list参数,否则默认合并为字典;属性转为@key,文本为#text,嵌套结构需手动提取;不规范XML应先用ElementTree校验。

用 xmltodict 处理单层同名节点最直接
当 XML 中存在多个同级同名标签(比如 ),xmltodict.parse() 默认会把它们合并成一个字典,而不是列表——这是最容易踩的坑。必须显式传入 force_list 参数才能保留为列表结构。
常见错误现象:
{'root': {'item': {'name': 'a'}}}(只留了一个)而非 {'root': {'item': [{'name': 'a'}, {'name': 'b'}]}}
- 对所有
item标签强制转为列表:force_list=['item'] - 若想统一处理所有重复标签,可设
force_list=True,但要注意这会让所有标签都变成列表(包括只出现一次的),后续取值需写[0] - 配合
process_namespaces=False(默认值)避免命名空间干扰,除非你明确需要解析带xmlns的 XML
嵌套结构里 list 和 dict 混用要手动 flatten
xmltodict 不会自动“扁平化”路径,比如 解析后是
{'data': {'items': {'item': {'name': 'A'}}}},而你想要的是 [{'name': 'A'}]。这时候不能只靠参数,得自己提取路径。
- 先用
xmltodict.parse(xml_str, force_list=['item'])得到嵌套结构 - 再用字典键路径访问:例如
result['data']['items']['item']—— 注意这里已经是列表(因为加了force_list) - 如果不确定某层是否存在,用
.get('items', {}).get('item', [])避免KeyError
遇到属性(@attr)和文本(#text)要小心类型混杂
XML 中的属性(如 )会被 xmltodict 转成 {'@id': '123', '#text': 'abc'}。如果你只需要纯内容,这些键名会干扰字段一致性。
立即学习“Python免费学习笔记(深入)”;
- 遍历列表时逐个清理:
{k[1:]: v for k, v in item.items() if k.startswith('@')}提取属性,或过滤掉@和#text - 若文本是唯一内容且无属性,可用
item.get('#text', item)回退取值 - 不要依赖
str(item)或json.dumps直接输出——#text会导致字段名不统一
不用第三方库?标准库 xml.etree.ElementTree 更可控但更啰嗦
如果项目禁用外部依赖,xml.etree.ElementTree 是唯一选择,但它不自动生成字典,得手写递归逻辑。好处是能精确控制每个节点怎么转,坏处是容易漏掉属性、文本、命名空间等边缘情况。
- 用
elem.attrib取属性,elem.text.strip()取文本内容 - 子节点用
list(elem)遍历,对每个子节点递归调用转换函数 - 判断是否为同名多节点:先收集所有
elem.findall('item'),再逐个转字典,最后汇总成列表
import xml.etree.ElementTree as ETdef elem_to_dict(elem): result = {k: v for k, v in elem.attrib.items()} if elem.text and elem.text.strip(): result['#text'] = elem.text.strip() for child in elem: child_data = elem_to_dict(child) if child.tag not in result: result[child.tag] = child_data else:
已存在,转为列表
if not isinstance(result[child.tag], list): result[child.tag] = [result[child.tag]] result[child.tag].append(child_data) return resultroot = ET.fromstring(xml_str) data = {root.tag: elem_to_dict(root)}
真正麻烦的不是转换本身,而是 XML 源数据是否规范——有没有混用属性和文本、有没有缺闭合标签、有没有非法字符。建议先用
xml.etree.ElementTree.parse()尝试加载,捕获ParseError,比硬转字典更早发现问题。










