常见错误是编码不匹配或含BOM头,需用'utf-8-sig'或'gbk'显式指定;命名空间需用字典映射或通配符;attrib只含显式属性,应用get()安全访问;大文件须用iterparse()配合clear()释放内存。

用 xml.etree.ElementTree.parse() 读取本地 XML 文件时为什么报错 ParseError: not well-formed
常见原因是文件编码不匹配或含 BOM 头。ElementTree 默认按 UTF-8 解析,但 Windows 编辑器保存的 XML 常带 UTF-8-BOM 或 GBK 编码。
实操建议:
- 先用
open('file.xml', 'rb').read()[:10]查看前几个字节,确认是否有b'\xef\xbb\xbf'(BOM) - 显式指定编码:用
ET.parse(open('file.xml', 'r', encoding='utf-8-sig'))——utf-8-sig自动跳过 BOM - 若文件是 GBK 编码,必须写
encoding='gbk',否则解析直接失败,不会自动 fallback - 避免用
ET.fromstring()直接传入含中文路径的字符串(Windows 下易因路径转义出错),优先走open()+parse()
用 findall() 和 iter() 提取带命名空间的节点总返回空列表
XML 中出现 xmlns="http://example.com/ns" 时,所有未加前缀的元素都属于该默认命名空间,而 findall('item') 实际匹配的是无命名空间的 item,自然找不到。
实操建议:
- 先提取命名空间映射:用
root.nsmap(仅 lxml 支持)——但标准xml.etree.ElementTree不提供此属性,得手动构造 - 正确做法:定义命名空间字典,如
ns = {'ns': 'http://example.com/ns'},再调用root.findall('.//ns:item', ns) - 若不确定命名空间 URI,可用通配符:
root.findall('.//{*}item')(Python 3.8+ 支持,匹配任意命名空间下的 item) -
iter()不支持命名空间前缀,但支持通配符:list(root.iter('{*}item'))
提取 attrib 字典时发现某些属性值是空字符串而非 None
ElementTree 对缺失属性不做补全,elem.attrib 只包含 XML 中**显式声明**的属性;而 elem.get('attr_name') 在属性不存在时返回 None(可设默认值),这是关键区别。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
实操建议:
- 不要依赖
elem.attrib['id']—— 属性不存在会抛KeyError - 统一用
elem.get('id'),需要默认值就写elem.get('id', 'default') - 若需检查属性是否存在,用
'id' in elem.attrib,而不是elem.get('id') is not None(因为属性值可能被设为空字符串,如id="") -
elem.attrib是普通 dict,修改它会影响序列化结果;但改完后需重新调用ET.tostring()才能体现变化
处理大 XML 文件时内存暴涨甚至 OOM
ET.parse() 会将整个文档加载为内存树结构,对百 MB 级 XML 很危险。真正流式解析要用 iterparse(),但它默认仍保留已解析节点引用,需手动清理。
实操建议:
- 用
for event, elem in ET.iterparse(file_obj, events=('start', 'end')):分阶段处理 - 在
event == 'end'且确认不再需要该节点时,立即调用elem.clear()清空子节点,并用elem.clear()后再del elem(虽然 Python 通常不需要,但大文件下显式释放更稳) - 只在
event == 'start'时做标签名判断,event == 'end'时做数据提取,避免重复遍历 - 别用
iterparse()配合.findall()—— 此时树尚未完整构建,会返回空结果
实际项目里最常被忽略的是命名空间处理和 iterparse() 中的 clear() 调用时机:不清理,内存不释放;清理太早,子节点还没收全。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










