如何使用 Python 元素树生成带有 BOM 的 XML、UTF-8?

How to generate XML, UTF-8 with BOM using Python Element Tree?

提问人:pepr 提问时间:1/31/2022 最后编辑:pepr 更新时间:2/1/2022 访问量:982

问:

要为 ASP.NET 生成资源 XML 文件,第三方工具需要 BOM(迁移到工具的新版本时)。同时,它需要像 .<?xml version='1.0' encoding='utf-8'?>

问题是,当使用 ElementTree 命令时...

tree.write(lang_resx_fpath, encoding='utf-8')

生成的文件不包含 BOM。使用命令时...

tree.write(lang_resx_fpath, encoding='utf-8-sig')

结果确实包含物料清单;但是,XML prolog 包含 .encoding='utf-8-sig'

我应该如何生成同时包含 BOM 和 ?encoding='utf-8'

更新:

我通过再次读取、替换和写入文件来解决它,就像这样......

with open(lang_resx_fpath, 'r', encoding='utf-8-sig') as f:
    content = f.read()

content = content.replace("encoding='utf-8-sig'", "encoding='utf-8'")

with open(lang_resx_fpath, 'w', encoding='utf-8-sig') as f:
    f.write(content)

无论如何,有没有更清洁的解决方案?

更新:我已经创建了 https://bugs.python.org/issue46598,并且还编写了修复程序(https://github.com/python/cpython/pull/31043)。

python xml utf-8 元素树 字节顺序标记

评论

0赞 Maciej Wrobel 1/31/2022
是否可以选择禁用带有 as .write() 参数的 XML Prolog?xml_declaration=False
0赞 pepr 1/31/2022
@MaciejWrobel:没有。XML prolog 必须存在。

答:

1赞 Maciej Wrobel 2/1/2022 #1

查看 ElementTree.write 的源代码显示 prolog 在那里是硬编码的(https://github.com/python/cpython/blob/main/Lib/xml/etree/ElementTree.py 或永久链接 https://github.com/python/cpython/blob/ee0ac328d38a86f7907598c94cb88a97635b32f8/Lib/xml/etree/ElementTree.py)。因此,可能使用 ET 的内部结构是唯一的选择(除了 monkey-pathing 模块),以编写所需的前导码并将 BOM 保存在文件中:

import xml.etree.ElementTree as ET
qnames, namespaces = ET._namespaces(tree._root, None)
with open(lang_resx_fpath,'w',encoding='utf-8-sig') as f:
    f.write("<?xml version='1.0' encoding='utf-8'?>\n"     )
    ET._serialize_xml(f.write,
                        tree._root, qnames, namespaces,
                       short_empty_elements=False)

可能它并不比您的解决方案更优雅(也许它甚至不那么优雅)。唯一的优点是它不需要两次写入文件,除了一些巨大的XML文件之外,这将是一个小的好处。

评论

0赞 pepr 2/1/2022
谢谢,Maciej。在我看来,方法中的第 741 行(在编写序言时)应该替换为 .declared_encodingwriteutf-8-sigutf-8