为了账号安全,请及时绑定邮箱和手机立即绑定

Python ElementTree 生成格式不正确的带有特殊字符 '\x0b' 的 XML 文件

Python ElementTree 生成格式不正确的带有特殊字符 '\x0b' 的 XML 文件

呼唤远方 2022-12-14 21:16:17
我曾经ElementTree生成带有'\x0b'特殊字符的xml,然后minidom用来解析它。它会抛出not well-formed错误。import xml.etree.ElementTree as ETfrom xml.dom import minidomroot = ET.Element('root')root.text='\x0b'xml = ET.tostring(root, 'UTF-8')print(xml)pretty_tree = minidom.parseString(xml)生成的 XML:<root>\x0b</root>错误:Traceback (most recent call last):  File "testXml.py", line 7, in <module>    pretty_tree = minidom.parseString(xml)  File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/xml/dom/minidom.py", line 1968, in parseString    return expatbuilder.parseString(string)  File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/xml/dom/expatbuilder.py", line 925, in parseString    return builder.parseString(string)  File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/xml/dom/expatbuilder.py", line 223, in parseString    parser.Parse(string, True)xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 6
查看完整描述

3 回答

?
德玛西亚99

TA贡献1770条经验 获得超3个赞

此行为在过去已作为错误提出,并已解决为“不会修复”。

ElementTree模块作者点评

对于 ET,[这种行为] 是故意的。验证每个应用程序提供的数据会降低所有应用程序的性能,即使只有一小部分人会尝试序列化无法用 XML 表示的数据。

结束评论(由lxml的维护者,同时也是 Python 核心开发人员撰写)包括以下观察:

这是一个棘手的决定。例如,lxml 验证用户输入,但那是因为它无论如何都必须处理它,并且直接在输入时进行处理(并且在 C 代码中非常有效)。另一方面,ET 对于允许用户执行的操作相当宽松,并且不会对用户输入进行太多处理。它甚至在处理过程中允许无效的树,并且只期望树在被请求序列化时是可序列化的。

我认为这是一种公平的行为,因为大多数用户输入都可以,并且不需要承受验证所有输入的性能损失。例如,空字符在文本中很少见,我认为让用户自己处理可能出现的少数情况是合理的。

...

最后,真正关心正确输出的用户应该在序列化对其运行某种模式验证,因为这不仅会检测数据问题,还会检测结构和逻辑问题(例如缺失或空属性),特别是针对他们的目标数据格式。在某些情况下,它甚至可能检测到由于服务器计算机中的旧非 ECC RAM 而导致的随机数据损坏。:)

...

所以总而言之,ET.tostring将生成格式不正确的 xml,这是设计使然。如有必要,可以使用ET.fromstring或其他解析器解析输出以检查其格式是否正确。或者,可以使用 lxml 代替 ElementTree。


查看完整回答
反对 回复 2022-12-14
?
陪伴而非守候

TA贡献1757条经验 获得超8个赞

\x0b是 XML 限制字符。这个问题的答案中对有效字符和受限字符有很好的描述。



查看完整回答
反对 回复 2022-12-14
?
qq_遁去的一_1

TA贡献1725条经验 获得超7个赞

作为我自己的解决方法,我编写了一个辅助方法来在保存到 XML 模型之前清除受限字符:

def clean(str):
  return re.sub(r'[^\u0009\u000A\u000D\u0020-\uD7FF\uE000-\uFFFD\u10000-\u10FFF]+', '', str)


查看完整回答
反对 回复 2022-12-14
  • 3 回答
  • 0 关注
  • 163 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信