ElementTree 和 Unicode

21

我有一个xml文件中的这个字符:

<data>
  <products>
      <color>fumè</color>
  </product>
</data>

我尝试使用以下代码生成ElementTree的一个实例:

string_data = open('file.xml')
x = ElementTree.fromstring(unicode(string_data.encode('utf-8')))

我得到了以下错误信息:
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe8' in position 185: ordinal not in range(128)

(注:这个位置不是准确的,我从较大的一个 XML 示例中抽样。)

如何解决?谢谢。


顺便提一下,你的样本数据是不正确的 - productsproduct - Jon Clements
6个回答

35

1
通常情况下,您应该直接将XML数据(以字节形式)传递给XML解析器,除非response.text考虑到response.content是XML并遵循相应的标准,例如读取任何XML声明以查找字符编码(似乎不太可能requests会这样做,也不应该这样)。 - jfs

15
你需要将 utf-8 字符串 解码 成 Unicode 对象。因此,
string_data.encode('utf-8')

应该是这样

string_data.decode('utf-8')

假设string_data实际上是一个utf-8字符串。

总之,为了从Unicode对象得到一个utf-8字符串,您需要编码该Unicode对象(使用utf-8编码),而将字符串转换为Unicode对象,则需要使用相应的编码解码该字符串。

有关这些概念的更多细节,建议阅读《软件开发人员必须了解的有关Unicode和字符集的绝对最低限度》(非Python特定)。


这很遗憾,但这并没有改变任何事情。 - pistacchio
2
OP的问题在于他/她试图处理解码,而不是将其留给ElementTree本身... - Martijn Pieters
1
@MartijnPieters:完全正确,我在路上写了我的答案,应该更仔细地看问题。虽然编码字节串以获取Unicode肯定是错误的,但这并不是(真正的)问题所在。 - Lukas Graf
你救了我的命:) - Thang Nguyen

12

你不需要解码XML才能使用ElementTree。 XML自带编码信息(默认为UTF-8),而ElementTree会为您处理,并输出Unicode:

>>> data = '''\
... <data>
...   <products>
...       <color>fumè</color>
...   </products>
... </data>
... '''
>>> x = ElementTree.fromstring(data)
>>> x[0][0].text
u'fum\xe8'
如果你的数据包含在一个文件(例如文件对象)中,只需将文件名或文件对象直接传递给ElementTree.parse()函数即可:
x = ElementTree.parse('file.xml')

2
不幸的是,有时我们会遇到没有嵌入编码信息的XML,而Elementree会出错,返回带有损坏字符的strs。 - Kylotan
3
@Kylotan:那么这些XML文档有问题。XML规范在这方面非常清楚;除非在XML头中明确说明,否则文档将以UTF8编码。 - Martijn Pieters
2
@Kylotan:你可以使用传递给ElementTree.parse()函数的ElementTree.XMLParser()对象来覆盖XML声明,用于处理损坏的XML输入。 - Martijn Pieters
@Kylotan:仅仅因为你的XML文件出了问题,并不能否定我的答案是正确的。 - Martijn Pieters
嗯,对于XML是否存在问题,我很难确定,因为它在其他地方似乎可以正常呈现,但我只知道输出存在问题。 (我会撤销投票,但SO不允许我这样做。) - Kylotan
显示剩余4条评论

2
你尝试过使用parse函数吗?它可以代替打开文件,这样就不需要在.fromstring()之前用.read()了。
import xml.etree.ElementTree as ET

tree = ET.parse('file.xml')
root = tree.getroot()
# etc...

1

open()函数不返回一个字符串。 相反,使用open('file.xml').read()


1
很可能您的文件不是UTF-8编码。字符è可能来自其他编码,例如latin-1

我确保使用UTF-8编码保存了该文件。 - pistacchio
尝试了编码 'cp-1250',但不起作用。'latin-1' 可以。谢谢! - EvertW

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接