Python xml.etree.ElementTree乱码 中文写入XML文件乱码修复

5次阅读

必须显式指定encoding=”utf-8″并设置xml_declaration=true,否则xml文件无编码声明,windows记事本等工具误判为gbk导致中文显示为问号或方块。

Python xml.etree.ElementTree乱码 中文写入XML文件乱码修复

写入XML时中文变成问号或方块,根本原因是编码没指定

python 3 默认用 UTF-8,但 xml.etree.ElementTreewrite() 方法默认不写 bom、也不显式声明编码,如果用记事本等工具打开,容易误判为 ANSI(如 GBK),导致中文显示为乱码。这不是解析失败,是「保存格式」和「查看方式」错配。

  • 必须显式传入 encoding="utf-8" 参数给 write()
  • 必须在 XML 声明中体现编码,即开头要有 <?xml version="1.0" encoding="utf-8"?>
  • 如果用 open() 手动写入,文件句柄也得用 encoding="utf-8",否则 write() 写进去的仍是字节流乱码

tree.write() 必须带 encoding 和 xml_declaration=True

write() 不加参数时默认用 ASCII 编码写入,中文直接报错或静默丢弃。即使你用 UTF-8 打开文件,没声明 encoding 就等于没告诉 XML 解析器“这串字节该按 UTF-8 解”,外部工具(比如浏览器、IE、旧版记事本)会瞎猜。

  • 正确调用:tree.write("out.xml", encoding="utf-8", xml_declaration=True)
  • 漏掉 xml_declaration=True → 没有 <?xml ...?> 行,部分工具无法识别编码
  • 只写 encoding="utf-8" 但不写 xml_declaration=True → 文件内容是 UTF-8 字节,但没声明,等于“穿了衣服不挂牌”
  • Windows 记事本尤其依赖这一行才能正确加载 UTF-8 中文

用 open() + write() 时,文件打开模式不能用 “w” 简单替代

有人想绕过 write(),改用 open("x.xml", "w").write(tree.tostring(...).decode()),这非常危险:一旦节点含特殊字符(如 &),<code>tostring() 返回的是已转义的字节,直接 decode 再 write 容易二次转义或解码失败。

  • 不要手动 decode / encode tostring() 结果 —— 它返回 bytes,应直接用二进制模式写入
  • 安全写法:with open("out.xml", "wb") as f: f.write(etree.tostring(tree, encoding="utf-8", xml_declaration=True))
  • 注意:这里 encoding="utf-8" 是给 tostring() 用的,不是给 open() 的;open() 必须是 "wb",否则文本模式会尝试按系统默认编码再编码一次

ElementTree 对中文属性值和文本内容本身无限制,乱码只出在 IO 环节

很多人以为 Element.text = "你好" 会出问题,其实不会。ElementTree 内部全用 Unicode 字符串,中文赋值完全正常。所有乱码都发生在「从内存写到磁盘」这一步,和解析、构建、查找完全无关。

立即学习Python免费学习笔记(深入)”;

  • 确认乱码是否真存在:用 cat out.xml(Linux/macOS)或 type out.xml(Windows PowerShell)看原始字节,比记事本更可信
  • 如果终端能正常显示中文,但记事本打不开 → 几乎肯定是缺 xml_declaration=True
  • 如果连 cat 都显示 或空格 → 写入时用了错误的 encoding(比如写成了 gbk)或 open 模式错了

写 XML 文件这件事,核心就卡在「声明编码」和「匹配写入方式」两个动作上,少一个,中文就大概率消失。别信“自动识别”,XML 没那功能。

text=ZqhQzanResources