ß 无法从 XML-UTF-16 编码的 Python 文件中读取

ß can not be read from XML-file with UTF-16 Encoding with Python

我有两个 XML 文件,其中包含“ß”(德语中的“scharfes S”),开头为:

    <?xml version="1.0" encoding="utf-16" standalone="yes"?>

我用下面的代码读取了utf-8文件:

    with open(file.xml, encoding='utf-8') as file:  
        f = file.read()
        xml = xmltodict.parse(f) 

以及 utf-16 文件的代码。

    with open(file.xml, encoding='utf-16') as file:  
        f = file.read()
        xml = xmltodict.parse(f) 

对于 UTF-16 文件,我收到此错误:UnicodeError: UTF-16 stream does not start with BOM。 将所有内容更改为:

    with open(file.xml, encoding='utf-16') as file:  
        file.seek(1, os.SEEK_SET) 
        f = file.read()
        xml = xmltodict.parse(f) 

我尝试了不同的点(例如 seek(1,..), seek(2,..), ...)没有帮助。

然后我用 (Source)

检查了编码
   alias vic="vim -c 'execute \"silent \!echo \" . &fileencoding | q'"
   vic file.xml
   > latin-1

(因此我将 encoding='utf-16' 替换为 encoding='latin-1')。

但现在我在代码中收到有关“ß”的错误(例如,在尝试“utf-16-le”时)

  "'utf-16-le' codec can't decode bytes in position 12734-12735: illegal encoding"

有人知道问题出在哪里吗?或者一般来说:如何使用 utf-8 或 utf-16 编码读取 Python 中的 XML 文件,而不会出现 BOM 错误或有关字符“ß”的错误。

提前致谢!

如果我创建一个 UTF-16LE 文件:

$ echo 'Character is: ß' | iconv -t utf-16le >f.txt

并用十六进制转储检查它:

$ xxd f.txt 
00000000: 4300 6800 6100 7200 6100 6300 7400 6500  C.h.a.r.a.c.t.e.
00000010: 7200 2000 6900 7300 3a00 2000 df00 0a00  r. .i.s.:. .....

然后在Python阅读:

>>> open('f.txt', encoding='utf-16LE').read()
'Character is: ß\n'

然后我得到了预期的结果。

您的文件未使用您声明的编码正确编码。

can't decode bytes in position 12734-12735: illegal encoding

创建一个 小得多 的示例文件,或按照上面的建议生成一个并寻找差异。

如果您发现自己在处理 XML 个文件时手动弄乱了文件编码,那您就做错了。

基本规则:切勿在文本模式下阅读 XML 个带有 open() 的文件。

使用 XML 解析器加载文件。解析器会自动为你整理编码。这就是在文件顶部有一个像 <?xml version="1.0" encoding="utf-16"?> 这样的 XML 声明的全部意义。

import xml.etree.ElementTree as ET

tree = ET.parse('file.xml')

如果要使用xmltodict,以二进制模式打开文件(rb):

with open('file.xml', 'rb') as f:  
    xml = xmltodict.parse(f)

在这里,xmltodict 会将文件交给内部的 XML 解析器,它会再次为您整理编码。


如果上面的字符乱码甚至抛出错误,则您的 XML 文件已损坏。修复文件的制作者。如果您手动编辑了该文件,请仔细检查您的文本编辑器的编码设置是否与 XML 声明相匹配。