Python:Unicode和ElementTree.pars

2024-04-26 14:04:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我正试图转到Python2.7,因为Unicode在这里是一个很大的问题,所以我会尝试用XML文件和文本处理它们,并使用xml.etree.cElementTree库解析它们。但我遇到了这个错误:

>>> import xml.etree.cElementTree as ET
>>> from io import StringIO
>>> source = """\
... <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
... <root>
...   <Parent>
...     <Child>
...       <Element>Text</Element>
...     </Child>
...   </Parent>
... </root>
... """
>>> srcbuf = StringIO(source.decode('utf-8'))
>>> doc = ET.parse(srcbuf)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 56, in parse
  File "<string>", line 35, in parse
cElementTree.ParseError: no element found: line 1, column 0

使用io.open('filename.xml', encoding='utf-8')传递给ET.parse也会发生同样的事情:

>>> with io.open('test.xml', mode='w', encoding='utf-8') as fp:
...     fp.write(source.decode('utf-8'))
...
150L
>>> with io.open('test.xml', mode='r', encoding='utf-8') as fp:
...     fp.read()
...
u'<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\n<root>\n  <Parent>\n
    <Child>\n      <Element>Text</Element>\n    </Child>\n  </Parent>\n</root>\n
'
>>> with io.open('test.xml', mode='r', encoding='utf-8') as fp:
...     ET.parse(fp)
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<string>", line 56, in parse
  File "<string>", line 35, in parse
cElementTree.ParseError: no element found: line 1, column 0

这里是否缺少关于unicode和ET解析的内容?

编辑:显然,ET解析器不能很好地处理unicode输入流?以下工作:

>>> with io.open('test.xml', mode='rb') as fp:
...     ET.parse(fp)
...
<ElementTree object at 0x0180BC10>

但这也意味着如果我想解析内存中的文本,就不能使用io.StringIO,除非我先将其编码到内存缓冲区中?


Tags: inioparseaslinerootxmlopen
3条回答

您的问题是您正在输入ElementTreeunicode,但它倾向于使用字节。它将在任何情况下为您提供unicode。

在Python2.x中,它只能使用字节。你可以告诉它这些字节是什么编码的,但就是这样。所以,如果你真的要处理一个表示文本文件的对象,比如io.StringIO,首先你需要把它转换成其他的东西。

如果您是从UTF-8编码中的2.x-str(也称为bytes)开始的,在内存中,就像您的示例中一样,使用xml.etree.cElementTree.XML一下子将其解析为XML,并且不必担心这一点:-)。

如果您想要一个能够处理从文件中增量读取的数据的接口,请使用xml.etree.cElementTree.parseio.BytesIO将其转换为内存中字节流,而不是内存中字符字符串。如果要使用io.open,请将其与b标志一起使用,以便获得字节流。

在Python3.x中,可以将unicode直接传递到ElementTree,这更方便一些,而且可以说,ElementTree的新版本更适合这样做。但是,您可能仍然不想这样做,而Python3的版本仍然接受字节作为输入。无论如何,您总是从字节开始:通过将它们直接从输入源传递到ElementTree,您可以让它在XML解析引擎中智能地进行编码或解码,以及在输入流中动态地检测编码声明,这可以用XML来实现,但不能用任意的文本数据来实现。因此,让XML解析器完成解码工作是承担这一责任的正确地方。

你不能用吗

doc = ET.fromstring(source)

在你的第一个例子里?

我在Python2.6中遇到了与您相同的问题。

在Python2.x和3.x版本中,cElementTree.parse的“utf-8”编码似乎不同。在Python2.x中,我们可以使用XMLParser对unicode进行编码。例如:

import xml.etree.cElementTree as etree

parser = etree.XMLParser(encoding="utf-8")
targetTree = etree.parse( "./targetPageID.xml", parser=parser )
pageIds = targetTree.find("categorymembers")
print "pageIds:",etree.tostring(pageIds)

您可以参考本页了解XMLParser方法(部分“XMLParser”):http://effbot.org/zone/elementtree-13-intro.htm

以下方法适用于Python3.x版本:

import xml.etree.cElementTree as etree
import codecs

target_file = codecs.open("./targetPageID.xml",mode='r',encoding='utf-8')

targetTree = etree.parse( target_file )
pageIds = targetTree.find("categorymembers")
print "pageIds:",etree.tostring(pageIds)

希望这能帮助你。

相关问题 更多 >