1

我正在尝试使用 xml.etree 来读取和写入包含 € 符号的 xml 文件。

我的简化代码如下所示:

optionsdirectory = os.getcwd()
optionsfile = os.path.join(optionsdirectory, "conf")
optionstree = ET.parse(optionsfile)
options = optionstree.getroot()
for option in options:
    if option.tag == "currency":
        option.text = "€"
optionstree.write(optionsfile, encoding="UTF-8")

运行时出现以下错误:

File "C:\curr.py", line 8
    optionstree.write(optionsfile, encoding="UTF-8")
File "C:\Python27\lib\xml\etree\ElementTree.py", line 815, in write
    serialize(write, self._root, encoding, qnames, namespaces)
File "C:\Python27\lib\xml\etree\ElementTree.py", line 934, in _serialize_xml
    _serialize_xml(write, e, encoding, qnames, None)
File "C:\Python27\lib\xml\etree\ElementTree.py", line 932, in _serialize_xml
    write(_escape_cdata(text, encoding))
File "C:\Python27\lib\xml\etree\ElementTree.py", line 1068, in _escape_cdata
    return text.encode(encoding, "xmlcharrefreplace")
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 2114: ordinal not in range(128)

有没有办法使用 xml.etree 将 € 符号写入 xml 文件?

4

3 回答 3

6

您需要使用 unicode 文字。使用 unicode 转义而不是字符会更容易:

option.text = u"\u20AC"  # Euro sign

当您不使用 unicode 文字而是使用字节(字符串)文字时,会发生什么情况,即 Python 尝试使用默认编码(即 ASCII)将值解码为 un​​icode 文字。这会导致您看到的 UnicodeDecodeError。

如果您确实使用非转义字符,请确保在顶部指定源文件的编码:

# -*- coding: utf-8 -*-

并确保您的编辑器使用 UTF-8 来保存文件。不过,您仍然必须使用 unicode 文字:

option.text = u"€"
于 2012-09-29T19:39:10.583 回答
0

下面介绍如何使用非 ASCII 字符创建 XML 文件。请注意,您需要以通过声明的编码保存源文件# coding:并使用 Unicode 文字 ( u'string')。在下面的示例中,我将文件同时写入 UTF-8 和 ASCII 以证明 ElementTree 在任何一种情况下都能正确读取文件:

# coding: utf8
from xml.etree import ElementTree as et

# Create the root element.
root = et.Element('test')
root.text = u'123€456'

# Wrap the root in an ElementTree and write files.
tree = et.ElementTree(root)
tree.write('utf8.xml',encoding='UTF-8')
tree.write('ascii.xml',encoding='ascii')

# Verify that each file can be read correctly.
tree = et.parse('utf8.xml')
print tree.getroot().text
tree = et.parse('ascii.xml')
print tree.getroot().text

# display the raw contents of the files
with open('utf8.xml','rb') as f:
    print repr(f.read())
with open('ascii.xml','rb') as f:
    print repr(f.read())

注意输出。0xE2 0x82 0xAC 是欧元字符的 UTF-8 十六进制序列。 €是字符参考。

123€456
123€456
"<?xml version='1.0' encoding='UTF-8'?>\n<test>123\xe2\x82\xac456</test>"
"<?xml version='1.0' encoding='ascii'?>\n<test>123&#8364;456</test>"
于 2012-09-30T17:08:15.977 回答
0

我以为我擅长网页,但对于我的生活,我无法像其他人一样弄清楚如何“回应”这个网站上的帖子。所以我需要创建这个新的答案......

感谢您的回复马克 Tolonen。您的回复和 Martijn Pieters 的回复都涉及使用 Unicode 文字。但是,这对我不起作用。我正在使用的 XML 文件将通过写出包含 € 符号的文件名来创建。我通过以下代码获取文件名:

for file in os.listdir(r'C:\test'):
    filenamelist = filenamelist + " " + file

其中一些文件名将在文件名本身中包含 € 符号。然后我想将这些文件名写为 XML 属性,如下所示:

optionsdirectory = os.getcwd()
optionsfile = os.path.join(optionsdirectory, "conf.xml")
optionstree = ET.parse(optionsfile)
options = optionstree.getroot()
for option in options:
    if option.tag == "filenames":
        option.text = filenamelist
optionstree.write(optionsfile, encoding="UTF-8")

最初,我将有一个 xml 文件“conf.xml”,其中将包含一个空的“文件名”属性。我知道它很笨拙,但它适用于我的目的。

因此,€ 符号不能来自 Unicode 文字。当我运行上面的代码时,我得到了我在原始帖子中发布的错误,它基本上说当它遇到'filenamelist'中的€符号时它会举手。

于 2012-09-30T17:38:20.320 回答