xmltodict.parse()默认不保留xml属性,需显式设置xml_attribs=true才能将属性解析为以@为前缀的键,如@id、@type,且属性仅属于其所在标签的直接字典层级。

xmltodict.parse() 默认不保留属性,必须显式启用 xml_attribs
很多人一上来直接 xmltodict.parse(xml_str),发现 XML 里的 id="123"、type="user" 全没了——不是 bug,是默认行为。xmltodict 把属性当“元信息”处理,默认丢弃,只留文本和嵌套结构。
要让属性进字典,必须传 xml_attribs=True:
import xmltodict
data = xmltodict.parse('<user id="123" type="admin"><name>Alice</name></user>', xml_attribs=True)
这时 data['user']['@id'] 是 "123",data['user']['@type'] 是 "admin"。注意属性全被挂到 @xxx 键下,这是固定前缀,不能改。
属性和子元素同名时,@xxx 和 xxx 会并存,别误判为重复键
XML 允许 <item id="1"><id>2</id></item> 这种写法。启用 xml_attribs=True 后,解析结果里 item 字典会同时有 @id 和 id 两个键,值不同。
常见踩坑:用 for k in data['item']: 遍历时以为 id 是唯一字段,结果漏掉属性或覆盖子元素内容。
- 属性永远走
@xxx路径,子元素走xxx路径,二者不冲突但需主动区分 - 如果业务上属性和子元素语义相同(比如都表示 ID),得在解析后手动合并,xmltodict 不做自动去重
-
xml_attribs=False时,属性彻底消失,连@键都不会出现
嵌套层级深时,@ 前缀容易被忽略,查不到属性就先 print(type(data))
XML 套三四层标签后,比如 <a><b attr="x"><c>text</c></b></a>,启用 xml_attribs=True 后,attr 在 data['a']['b']['@attr'],不是 data['a']['@attr']。
新手常犯错误:对着原始 XML 直接猜路径,没实际打印结构就写 data.get('@id') 或 data['root'].get('@id'),结果是 KeyError 或 None。
- 务必先
print(data)或pprint(data)看清嵌套结构 - 属性只属于它所在 XML 标签的直接父字典,不会“透传”到上层
- 如果 XML 有命名空间(
xmlns:ns="..."),属性前缀可能变成@ns:attr,更得看实际输出
force_list 和 xml_attribs 一起用时,属性仍挂在每个列表项的字典里
遇到多个同名标签(如 <item id="1"></item><item id="2"></item>),默认会被转成 list,但属性不会丢失——只要开了 xml_attribs=True,每个 list 里的 dict 都带 @id。
示例:
xml = '<root><item id="1"></item><item id="2"></item></root>' data = xmltodict.parse(xml, xml_attribs=True, force_list=['item'])
此时 data['root']['item'][0]['@id'] == "1",data['root']['item'][1]['@id'] == "2"。
容易忽略的点:
-
force_list只影响结构(是否强制为 list),不影响属性提取逻辑 - 如果没设
force_list,单个<item></item>会是 dict;两个以上会自动变 list —— 属性依然存在,但代码要兼容两种类型 - 想统一处理,建议始终配
force_list,避免运行时类型判断
@ 前缀写没写对、嵌套位置找没找准。少检查任何一处,拿到的都是半截数据。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










