如何入门使用Python ElementTree模块进行XML操作?
- 内容介绍
- 相关推荐
本文共计932个文字,预计阅读时间需要4分钟。
不是它不能,而是默认忽略命名空间空间 — 所有的带有 xmlns 或前缀(如 ns:tag)的节点,在未明确声明时会被当作普通标签处理,find() 和 findall() 会直接找不到。
- 必须把命名空间映射成字典,例如:
{'ns': 'http://example.com/ns'} - 所有 XPath 查询中,标签名前要加前缀:
'.//ns:item',不能写'.//item' - 用
root.findall('.//ns:item', ns_map),其中ns_map是命名空间字典 - 如果 XML 中是默认命名空间(
xmlns="http://..."),前缀不能为空字符串,得设一个占位符,比如{'d': 'http://...'},再查'.//d:tag'
ElementTree.parse() 报 ParseError: not well-formed 怎么办?
常见于文件含 BOM、编码不匹配或混入控制字符。Python 3 默认按 UTF-8 解析,但 Windows 记事本保存的 XML 常带 UTF-8 BOM,而 parse() 不自动跳过。
- 先用
open(filename, 'rb')读二进制,再用etree.fromstring()配合encoding='utf-8-sig'(注意:这是xml.etree.ElementTree不支持的参数,得换用lxml.etree;标准库只能手动 strip BOM) - 更稳妥的做法:用
open(filename, encoding='utf-8-sig')读文本,再传给ET.fromstring() - 检查是否误把 HTML 当 XML 解析 ——
、©等实体在 XML 中不被识别,会直接报错 - 用
file.read(100)快速看开头是否有非法字符(如\x00、\xff\xfe)
如何安全地修改并写回 XML,避免格式崩坏?
ElementTree 默认不保留空白、缩进和注释,直接 tree.write() 会导致结构扁平化、换行消失,甚至破坏人可读性。
- 写入前务必指定
encoding和xml_declaration=True,否则中文可能变乱码,且无 XML 声明头 - 不要依赖
indent()—— 它是 Python 3.9+ 才加入的,旧版本需手动遍历加tail和text - 若需保留原始缩进/注释,标准库做不到,应改用
lxml.etree,它支持pretty_print=True和完整 DTD/注释解析 - 写文件时用
open(..., 'wb'),因为write()输出的是 bytes,不是 str
tree.write('output.xml', encoding='utf-8', xml_declaration=True)
用 .find() 找不到子元素?检查这三件事
看似简单,却是新手最高频的卡点。根本原因往往不在语法,而在树结构认知偏差。
立即学习“Python免费学习笔记(深入)”;
-
.find()只查**直接子元素**,不是全树搜索 —— 想查任意层级用.findall('.//tagname') - XML 是大小写敏感的:
<item></item>≠<item></item>,连空格都不能多一个 - 元素可能被包裹在
<root>下,但你对的是tree.getroot(),却调用了tree.find('item')(错误!应是root.find('item'))
print(etree.tostring(root, encoding='unicode')) 看一眼真实 DOM 树。本文共计932个文字,预计阅读时间需要4分钟。
不是它不能,而是默认忽略命名空间空间 — 所有的带有 xmlns 或前缀(如 ns:tag)的节点,在未明确声明时会被当作普通标签处理,find() 和 findall() 会直接找不到。
- 必须把命名空间映射成字典,例如:
{'ns': 'http://example.com/ns'} - 所有 XPath 查询中,标签名前要加前缀:
'.//ns:item',不能写'.//item' - 用
root.findall('.//ns:item', ns_map),其中ns_map是命名空间字典 - 如果 XML 中是默认命名空间(
xmlns="http://..."),前缀不能为空字符串,得设一个占位符,比如{'d': 'http://...'},再查'.//d:tag'
ElementTree.parse() 报 ParseError: not well-formed 怎么办?
常见于文件含 BOM、编码不匹配或混入控制字符。Python 3 默认按 UTF-8 解析,但 Windows 记事本保存的 XML 常带 UTF-8 BOM,而 parse() 不自动跳过。
- 先用
open(filename, 'rb')读二进制,再用etree.fromstring()配合encoding='utf-8-sig'(注意:这是xml.etree.ElementTree不支持的参数,得换用lxml.etree;标准库只能手动 strip BOM) - 更稳妥的做法:用
open(filename, encoding='utf-8-sig')读文本,再传给ET.fromstring() - 检查是否误把 HTML 当 XML 解析 ——
、©等实体在 XML 中不被识别,会直接报错 - 用
file.read(100)快速看开头是否有非法字符(如\x00、\xff\xfe)
如何安全地修改并写回 XML,避免格式崩坏?
ElementTree 默认不保留空白、缩进和注释,直接 tree.write() 会导致结构扁平化、换行消失,甚至破坏人可读性。
- 写入前务必指定
encoding和xml_declaration=True,否则中文可能变乱码,且无 XML 声明头 - 不要依赖
indent()—— 它是 Python 3.9+ 才加入的,旧版本需手动遍历加tail和text - 若需保留原始缩进/注释,标准库做不到,应改用
lxml.etree,它支持pretty_print=True和完整 DTD/注释解析 - 写文件时用
open(..., 'wb'),因为write()输出的是 bytes,不是 str
tree.write('output.xml', encoding='utf-8', xml_declaration=True)
用 .find() 找不到子元素?检查这三件事
看似简单,却是新手最高频的卡点。根本原因往往不在语法,而在树结构认知偏差。
立即学习“Python免费学习笔记(深入)”;
-
.find()只查**直接子元素**,不是全树搜索 —— 想查任意层级用.findall('.//tagname') - XML 是大小写敏感的:
<item></item>≠<item></item>,连空格都不能多一个 - 元素可能被包裹在
<root>下,但你对的是tree.getroot(),却调用了tree.find('item')(错误!应是root.find('item'))
print(etree.tostring(root, encoding='unicode')) 看一眼真实 DOM 树。
