正确压缩xml需基于解析器树操作:python用xml.etree.elementtree解析后strip属性值再tostring;node.js用xml2js禁用空白并关闭格式化;命令行推荐xmllint校验后处理;切忌字符串替换,否则破坏属性值、cdata等语义。

用 Python 的 xml.etree.ElementTree 重序列化 XML
直接字符串替换(比如 .replace('\n', '').replace(' ', ''))会破坏 XML 结构,比如把属性值里的空格也干掉,或把 CDATA 里的换行误删。正确做法是解析后再紧凑输出。
- 用
ET.parse()或ET.fromstring()加载 XML,确保语法合法 - 用
ET.tostring(root, encoding='unicode', method='xml')输出——默认不带缩进,但可能保留属性间空格 - 若需彻底无空格(包括属性之间),得先清理树:遍历所有
elem.attrib,对每个值调用.strip();再用method='xml'+encoding='unicode'输出
Node.js 里用 xml2js + builder 压缩
xml2js 默认解析后保留空白文本节点,直接重建会残留换行。必须显式禁用空白处理,并关闭格式化。
- 解析时加选项:
preserveWhitespace: false、ignoreAttrs: false - 构建时用
new xml2js.Builder({ headless: true, renderOpts: { pretty: false } }) - 注意:若原始 XML 有注释或处理指令,
xml2js默认不保留,需额外配ignorePi: false和ignoreComment: false
命令行快速压缩:用 xmllint 最稳
不用写代码,适合 CI 或临时处理。前提是系统装了 libxml2(macOS 用 brew install libxml2,Linux 用 apt install libxml2-utils)。
- 基础命令:
xmllint --format --noblanks input.xml | tr -d '\n' | sed 's/ */ /g'——但--noblanks有时不生效 - 更可靠写法:
xmllint --xpath '/*' input.xml 2>/dev/null | xmllint --format - | tr -d '\n\t\r' | sed 's/ \+/>/g; s/ \+/>/g' - 警告:
xmllint --compress不是压缩格式,而是启用 zlib 压缩传输,别被名字骗了
为什么不能简单 sed 或正则删除空白?
XML 里空格语义敏感:属性值内空格不能删(如 name="John Doe" → "JohnDoe" 就错了),CDATA 和文本节点中的换行也可能有意义。正则无法区分上下文。
- 典型翻车:
sed ':a;N;$!ba;s/\n//g;s/ //g'会把<tag attr="a b"></tag>变成<tag attr="ab"></tag> - 还有编码问题:UTF-8 BOM、实体引用(
)、命名空间前缀里的冒号,都可能被误伤 - 真正安全的压缩,永远基于解析器树结构操作,不是字符串层面的暴力清理
事情说清了就结束。最易忽略的是:压缩后没验证是否仍为良构 XML——建议加一步 xmllint --noout compressed.xml 校验。










