Python 为什么ElementTree会引发语法错误?
我一直试图用Python 为什么ElementTree会引发语法错误?,python,xml,parsing,Python,Xml,Parsing,我一直试图用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:
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
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
从yparse导入分析;分析('file.xml')
文件“C:\Python27\yparse.py”,第10行,在analyze中
对于其中的(电动汽车,电动汽车):
文件“C:\Python27\lib\xml\etree\ElementTree.py”,第1258行,下一行
self.\u parser.feed(数据)
文件“C:\Python27\lib\xml\etree\ElementTree.py”,第1624行,在提要中
自我提升错误(v)
文件“C:\Python27\lib\xml\etree\ElementTree.py”,第1488行,在_raiseerror中
提出错误
ParseError:对无效字符号的引用:第1行,第52459列
结果是确定的,但是,如果一个文件工作,它将始终工作。如果文件失败,它总是失败,并且总是在同一点失败
最奇怪的是,我正在使用跟踪来找出是否有任何格式错误的XML破坏了解析器。然后隔离导致故障的节点。但是,当我创建一个包含该节点及其几个邻居的XML文件时,解析工作正常
这似乎也不是尺寸问题。我成功地解析了更大的文件,没有任何问题
有什么想法吗?以下是一些想法:
(0)解释“一个文件”和“偶尔”:你真的是说它在相同的文件中有时工作,有时失败吗
对每个失败的文件执行以下操作:
(1) 找出文件中投诉的地方:
text = open("the_file.xml", "rb").read()
err_col = 52459
print repr(text[err_col-50:err_col+100]) # should include the error text
print repr(text[:50]) # show the XML declaration
(2) 将文件提交到基于web的XML验证服务,例如
并编辑您的问题以显示您的发现
更新:以下是说明问题的最小xml文件:
[badcharref.xml]
<a></a>
[Python 2.7.1 output]
>>> import xml.etree.ElementTree as ET
>>> it = ET.iterparse(file("badcharref.xml"))
>>> for ev, el in it:
... print el.tag
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
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
xml.etree.ElementTree.ParseError: reference to invalid character number: line 1, column 3
>>>
输出:
comments.xml
6615405 
10205764 �
10213901 �
10213936 �
10214123 �
13292514 
...
155656543 
155656564 
157344876 
157722583 
posts.xml
7607143 
12982273 
12982282 
12982292 
12982302 
12982310 
16085949 
16085955 
...
36303479 
36303494  <<=== whoops
38942863 
...
785292911 
801282472 
848911592 
comments.xml
6615405;
10205764和#x00;
10213901和#x00;
10213936;
10214123和#x00;
13292514和x03;
...
155656543和x1B;
1556564和x1B;
157344876;
157722583;
posts.xml
7607143;
12982273;
12982282;
12982292;
12982302;
12982310;
16085949;
16085955和x1C;
...
36303479;
36303494 正如@John Machin所建议的,所讨论的文件中确实有可疑的数字实体,尽管错误消息似乎指向了文本中的错误位置。可能是由于流式传输和缓冲的特性,很难报告准确的位置
事实上,所有这些实体都出现在文本中:
set(['', '', '', '', '', '', '
', '', '', '', '', '�', '', '', '
', '', '', '	', '', '', '', '', ''])
大多数是不允许的。看起来这个解析器非常严格,您需要找到另一个不那么严格的解析器,或者预处理XML。我不确定这是否回答了您的问题,但是如果您想使用元素树引发的ParseError异常,您可以这样做:
except ET.ParseError:
print("catastrophic failure")
print("last successful: {0}".format(last))
来源:我觉得在这里还需要注意的是,您可以很容易地捕捉到错误,避免完全停止程序,只需在函数中使用您稍后已经使用的内容,并放置以下语句:
it = ET.iterparse(file(xml))
在try&except括号内:
try:
it = ET.iterparse(file(xml))
except:
print('iterparse error')
当然,这不会修复XML文件或预处理技术,但有助于识别导致错误的文件(如果您正在分析批次) 您必须显示一些有问题的XML。您可能有不好的XML,然后当您编辑它以缩小范围时,它就变成了好的XML。编辑可以做一些鬼鬼祟祟的事情…@nedbatcheld这个文件真的很大,让我很难上传。不过,我确实考虑过这种可能性。因此,我直接使用Python的文件操作函数来提取XML的一部分并将其写入另一个文件。您是否可以显示导致这种情况的任何XML?@Pessimoppotamus:根据您的错误消息,错误只发生在文件中52KB处…@NedBatchelder我正在开发一个XML分块器,该分块器可以生成高达52KB的有效XML分块一定的块大小。我将尝试使用它来生成一个失败的XML并上传它。(0)偶尔意味着“使用某些文件”。但是结果是确定的,如果一个文件有效,它将始终有效。如果一个文件失败,它总是失败,并且总是在同一点失败。(1)我这样做了,我没有发现任何明显的错误。(2) 因为太大,所以无法执行此操作。我怀疑是这样,但在发生错误的文件部分附近没有类似的字符。涉及预处理的解决方案不是一个好主意,同样是因为文件有多大。理想情况下,应该有一种方法让XML解析器优雅地记录错误并继续解析,而不是灾难性地崩溃。我现在受够了。我一会儿回来。希望我能验证我的chunker是否正常工作,然后我会上传一些示例。事实上,这些文件被破坏了。我在解析之前做了一些预处理,结果正如预期的那样。这是一个非常老的问题,有一个公认的答案。如果您不确定是否可以在答案中添加任何内容,则应避免为了回答而回答。
try:
it = ET.iterparse(file(xml))
except:
print('iterparse error')