当前位置: 首页 > 面试题库 >

为什么ElementTree引发ParseError?

微生毅
2023-03-14
问题内容

我一直在尝试使用解析文件xml.etree.ElementTree

import xml.etree.ElementTree as ET
from xml.etree.ElementTree import ParseError

def analyze(xml):
    it = ET.iterparse(file(xml))
    count = 0
    last = None

    try:        
        for (ev, el) in it:
            count += 1
            last = el

    except ParseError:
            print("catastrophic failure")
            print("last successful: {0}".format(last))

    print('count: {0}'.format(count))

当然,这是我的代码的简化版本,但这足以破坏我的程序。如果删除try-catch块,则会出现一些文件出现此错误的情况:

Traceback (most recent call last):
  File "<pyshell#22>", line 1, in <module>
    from yparse import analyze; analyze('file.xml')
  File "C:\Python27\yparse.py", line 10, in analyze
    for (ev, el) in it:
  File "C:\Python27\lib\xml\etree\ElementTree.py", line 1258, in next
    self._parser.feed(data)
  File "C:\Python27\lib\xml\etree\ElementTree.py", line 1624, in feed
    self._raiseerror(v)
  File "C:\Python27\lib\xml\etree\ElementTree.py", line 1488, in _raiseerror
    raise err
ParseError: reference to invalid character number: line 1, column 52459

但是,结果是确定性的,如果文件有效,它将始终有效。如果文件失败,则它总是失败并且总是在同一点失败。

最奇怪的是,我正在使用跟踪来确定是否有任何格式错误的XML破坏了解析器。然后,我隔离导致故障的节点。但是,当我创建一个包含该节点及其几个邻居的XML文件时,解析就可以了!

这似乎也不是一个大小问题。我设法解析出更大的文件,没有任何问题。

有任何想法吗?


问题答案:

正如@John
Machin所建议的,尽管错误消息似乎指向文本中的错误位置,但有问题的文件中确实包含可疑的数字实体。也许流的性质和缓冲使得难以报告准确的位置。

实际上,所有这些实体都出现在文本中:

set(['&#x08;', '&#x0E;', '&#x1E;', '&#x1C;', '&#x18;', '&#x04;', '&#x0A;', '&#x0C;', '&#x16;', '&#x14;', '&#x06;', '&#x00;', '&#x10;', '&#x02;', '&#x0D;', '&#x1D;', '&#x0F;', '&#x09;', '&#x1B;', '&#x05;', '&#x15;', '&#x01;', '&#x03;'])

大部分都不允许。看起来这个解析器非常严格,您需要找到另一个不是那么严格的解析器,或者对XML进行预处理。



 类似资料:
  • 问题内容: 有什么不同之处与使得迭代器不会引发异常而引发异常?最后,两者都在修改集合大小。 请在这里忽略多线程。我只是在谈论一个for-each循环和一个迭代器循环。据我所知,for-each循环仅在内部创建迭代器。 我很困惑。 问题答案: 不会抛出,因为这是在迭代时修改集合的 允许 方式。这是什么的Javadoc的说: 从基础集合中移除此迭代器返回的最后一个元素(可选操作)。每次调用next()

  • 问题内容: 需要对以下代码进行澄清: 这将打印出来,以便证明和对象引用相同的内存引用。 这将打印出来,也证明是相同的。 显然,这将引发,因为我试图调用空引用。 所以这是我的问题,为什么最后一个代码示例没有抛出,因为我从前两个示例中看到并理解的是,如果两个对象都引用同一个对象,那么如果我们更改任何值,那么它也会反映给另一个对象,因为两个对象都指向相同的内存引用。那么,为什么该规则在这里不适用?如果我

  • 问题内容: 为什么这段代码不抛出?它在不使用方法的情况下修改了一段时间,这是唯一安全的删除方法。 如果将替换为,则会得到相同的结果。但是,如果我将列表更改为或只是得到了预期的异常。到底是怎么回事?我正在使用是否相关。 编辑 我找到了以下链接 http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4902078 相关部分是 天真的解决方案是将协同修改

  • 这似乎与对象没有被实例化有关,尽管我不太明白为什么。有人知道出什么事了吗?

  • 问题内容: 为什么这段代码没有抛出?看一看: 我不知道! 问题答案: 您为什么不能自己检查一下并抛出异常(如果您要的话)。

  • 问题内容: 在Java中: 抛出。为什么?为什么在这里投降?我不知道原因。 问题答案: 让我重命名您的班级,以使事情更加清楚。 -> 。 -> 。 仅仅因为你是一个人并不意味着你是一个人。你可能是一个。这就是将A强制转换为A的原因。 另一方面,每个是吗?答案是“是”。这就是为什么您 可以 编写如下代码: 要么 另外值得注意的是,您 可以 执行以下操作: 这样做的原因是您的变量实际上是在引用实例。因