XML格式化仅美化缩进换行而不改变数据,因XML对空白不敏感;minidom可快速美化但需清理重复声明,lxml更健壮且支持命名空间,xmllint适合命令行调试,但格式化可能影响含语义空格的文本节点。

XML格式化不是语法校验,也不改变数据内容,它只是把嵌套层级、缩进、换行这些视觉结构补全,让人类能快速看清父子关系和文档结构。
为什么浏览器或编辑器里看到的XML是“挤在一起”的
XML本身对空白符(空格、制表符、换行)不敏感,解析器会忽略大部分无关空白。所以原始XML可能被压缩成单行,或者缩进错乱——这不是错误,只是可读性差。
常见现象包括:xml.etree.ElementTree 读取后直接 tostring() 输出无缩进;HTTP接口返回的XML响应没做美化;多人协作时手动编辑破坏了原有缩进。
用 Python 的 xml.dom.minidom 快速美化
这是标准库中最轻量、无需安装依赖的方案,适合一次性脚本或 CI 中简单处理。
-
minidom.parse()或minidom.parseString()加载 XML 字符串或文件 - 调用
.toprettyxml(indent=" ", encoding=None),注意encoding设为None才返回 Unicode 字符串(Python 3 默认行为) - 默认会在开头插入 XML 声明(如
),若原文已有,会导致重复——需用.replace()清理
from xml.dom import minidomxml_str = '
' dom = minidom.parseString(xml_str) pretty = dom.toprettyxml(indent=" ") A 去掉首行声明(如果不需要)和多余空行
pretty = '\n'.join([line for line in pretty.split('\n') if line.strip()]) print(pretty)
用 lxml 实现更可控的格式化
当需要保留注释、处理命名空间、或避免 minidom 的换行冗余时,lxml 是更健壮的选择。它默认不加空行,缩进也更干净。
- 安装:
pip install lxml - 用
etree.parse()或etree.fromstring()加载 - 调用
etree.tostring(tree, pretty_print=True, encoding="unicode") - 注意:如果源 XML 有 DTD 或外部实体,
lxml默认禁用解析,避免 XXE——这是安全特性,不是 bug
from lxml import etreexml_str = '
' root = etree.fromstring(xml_str) formatted = etree.tostring(root, pretty_print=True, encoding="unicode") print(formatted) B
命令行快速格式化(Linux/macOS/WSL)
不用开编辑器,适合管道处理或调试 API 返回结果。
- 用
xmllint(libxml2 提供):xmllint --format -,输入来自 stdin,Ctrl+D 结束 - 如果没装:
brew install libxml2(macOS)、apt install libxml2-utils(Ubuntu) - 注意:
xmllint对格式错误敏感,遇到未闭合标签会报错退出,不是所有“看起来像 XML”的字符串都能过
示例:echo '
真正容易被忽略的是:格式化后的 XML 不一定“合法”——比如缩进添加的空白可能进入文本节点,影响后续 XPath 查询或业务逻辑判断。如果 XML 里有 这种带语义空格的内容,美化后空格会被保留,但某些解析器可能 trim 它。是否格式化,得先看下游怎么用。










