python libxml2读取器和XML_PARSE_RECOVER

python libxml2读取器和XML_PARSE_RECOVER,python,libxml2,Python,Libxml2,我正在尝试让一个阅读器从损坏的XML中恢复。将libxml2.XML_PARSE_RECOVER选项与DOM api(libxml2.readDoc)结合使用可以从实体问题中恢复 但是,将该选项与reader API一起使用(由于我们正在解析的文档的大小,这是必不可少的)不起作用。它只是陷入了一个永久循环(reader.Read()返回-1): 示例代码(带有小示例): 导入cStringIO 导入libxml2 DOC=“一些坏的&xml” reader=libxml2.readerForDo

我正在尝试让一个阅读器从损坏的XML中恢复。将libxml2.XML_PARSE_RECOVER选项与DOM api(libxml2.readDoc)结合使用可以从实体问题中恢复

但是,将该选项与reader API一起使用(由于我们正在解析的文档的大小,这是必不可少的)不起作用。它只是陷入了一个永久循环(reader.Read()返回-1):

示例代码(带有小示例):

导入cStringIO
导入libxml2
DOC=“一些坏的&xml”
reader=libxml2.readerForDoc(DOC,“urn:bogus”,无,libxml2.XML_PARSE_RECOVER | libxml2.XML_PARSE_NOERROR)
ret=reader.Read()
而ret:
打印“ret:%d”%ret
打印“节点名称:”,reader.name(),reader.NodeType()
ret=reader.Read()

有没有关于如何正确恢复的想法?

我不太确定libxml2绑定的当前状态。甚至libxml2站点也建议使用。解析此树并忽略
&
在lxml中是很好且干净的:

from cStringIO import StringIO
from lxml import etree

DOC = "<a>some broken & xml</a>"

reader = etree.XMLParser(recover=True)
tree = etree.parse(StringIO(DOC), reader)
print etree.tostring(tree.getroot())

xml不是以某种一致的方式被破坏了吗?在解析xml之前,您是否可以遵循某种模式来修复xml

例如,如果错误仅由未替换的符号引起,而您不使用CDATA或处理指令,则可以使用regexp修复该错误


编辑:然后看看python标准库中的sgmllib。BeautifulSoup使用它,因此它在您的案例中非常有用。(BeatifulSoup本身只提供树表示,而不提供事件)。

考虑使用
xml.sax
。当我看到格式非常不正确的XML时,可能会出现大量不同的问题,请尝试将问题分成小块

您提到您有一个非常大的XML文件,它可能有许多您连续处理的记录。每个记录(例如,
大概都有一个开始和结束标记-这些将是您的恢复点

。更糟糕的是,使用此技术将无法恢复单个记录。这需要更多的设置,但一次递增地解析一个格式错误的提要一个记录记录坏记录可能是您所能做的最好的方法

在日志中,确保为自己提供足够的信息来重建原始记录,以便您可以为所有无疑必须处理的情况添加额外的恢复代码(例如,创建一个badrecords_uuCode>今天的日期.xml,以便您可以手动重新处理)


祝你好运。

或者,你可以使用。它在恢复损坏的ML方面做得很好。

是:
,而ret==1:
。请参阅。谢谢,但这不会恢复,只是中止。因此,对于上面的内容,我只会得到标记。DOM api会生成一个文档树,恢复只会删除-,这是理想情况下我想要的(等效)从reader API。不幸的是,我也研究了lxml,但是您上面的建议使用了DOM API,因为文档的大小不是一个选项。lxml iterparse API不支持恢复。如果您只是尝试增量解析,请查看lxml的_FeedParser接口,我将编辑上面的示例及其用法。我没有我们甚至能够找到一种迭代的解析方法,在解析元素时生成元素。感谢您的所有努力。从技术上讲,我们需要的是增量解析和使用recover对元素进行事件驱动的提取。遗憾的是,lxml不符合这些要求。在我查看的示例中,每个源都破坏了xml,并且所有这些都不同出租方式!其他常见错误是打开和关闭标记的大小写不匹配。解决每一个标记都很困难,至少是可靠的。除此之外,修复源代码不是一个选项-我们必须像以前的提供商那样支持它们!BeautifulSoup基于DOM,因此将整个文档加载到内存中,而内存不会满足要求。除内存需求外,对于任何规模较大的东西,它都相当慢。
from cStringIO import StringIO
from lxml import etree

DOC = "<a>some broken & xml</a>"

reader = etree.XMLParser(recover=True)
tree = etree.parse(StringIO(DOC), reader)
print etree.tostring(tree.getroot())
DOC = "<a>some broken & xml</a>"
reader = etree.XMLParser(recover=True)

for data in StringIO(DOC).read():
    reader.feed(data)

tree = reader.close()
print etree.tostring(tree)