使用 etree & LXML 在 python 的开头解析带有编码块的 XML 字符串

parsing XML string with encoding block at the beginning in python with etree & LXML

我必须解析 XML 个这样开头的文件:

xml_string = '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <annotationStandOffs xmlns="http://www.tei-c.org/ns/1.0">
        <standOff> 
    ...
</standOff> 
</annotationStandOffs>
    '''

以下代码只有在我删除上面显示的字符串的第一行时才会运行:

import xml.etree.ElementTree as ET
from lxml import etree
parser = etree.XMLParser(resolve_entities=False,strip_cdata=False,recover=True)
    
XML_tree = etree.XML(xml_string,parser=parser)

否则我得到错误:

ValueError:不支持带有编码声明的 Unicode 字符串。请使用不带声明的字节输入或 XML 片段。

如错误所示,XML 声明的 encoding 部分旨在提供有关如何转换 字节 的必要信息(例如从文件中读取)转换为字符串。当 XML 已经是 字符串时没有意义。

一些 XML 解析器在解析字符串时会默默地忽略此信息。有些会报错。

因此,由于您将 XML 粘贴到 Python 源代码中的字符串文字中,因此只有在您编辑 Python 时自己删除声明才有意义文件。

另一个不太聪明的选择是使用字节字符串文字 b'''...''',或者在 运行 时间 '''...'''.encode('windows-1252') 将字符串编码为单字节编码.但这打开了另一罐蠕虫。当您的 Python 文件编码(例如 UTF-8)与复制粘贴的 XML(例如 UTF-16)中所谓的 XML 编码发生冲突时,您会得到更多有趣的错误。

长话短说,不要那样做。不要在未使用 XML 的情况下将 XML 复制粘贴到 Python 源代码中声明出来。并且不要试图通过 运行-time string encode() tomfoolery.

来“修复”它

反之亦然。如果您有 bytes(例如,以二进制模式从文件读取,或从网络套接字读取),则将这些字节提供给 XML 解析器。不要先手动 decode() 将它们放入字符串中。