python libxml2 reader和XML_PARSE_RECOVER

时间:2010-10-06 10:43:08

标签: python libxml2

我正在努力让读者从破碎的XML中恢复过来。将libxml2.XML_PARSE_RECOVER选项与DOM api(libxml2.readDoc)配合使用可以从实体问题中恢复。

然而,使用带有阅读器API的选项(由于我们正在解析的文档的大小,这是必不可少的)不起作用。它只是陷入永久循环(使用reader.Read()返回-1):

示例代码(小例子):

import cStringIO
import libxml2

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

reader = libxml2.readerForDoc(DOC, "urn:bogus", None, libxml2.XML_PARSE_RECOVER | libxml2.XML_PARSE_NOERROR)

ret = reader.Read()
while ret:
    print 'ret: %d' % ret
    print "node name: ", reader.Name(), reader.NodeType()
    ret = reader.Read()

任何想法如何正确恢复?

4 个答案:

答案 0 :(得分:1)

我不太确定libxml2绑定的当前状态。即使是libxml2网站也建议使用lxml。要解析这棵树并忽略&在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())

lxml文档中的parsers page详细介绍了如何设置解析器和迭代内容。

编辑:

如果要逐步解析文档,也可以使用XMLparser类,因为它是_FeedParser的子类:

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)

答案 1 :(得分:0)

xml是否以某种一致的方式被破坏?在解析之前,是否有一些模式可以修复你的xml?

例如 - 如果错误仅由未转义的&符号引起,并且您不使用CDATA或处理指令,则可以使用正则表达式修复它。

编辑:然后看一下python标准库中的sgmllib。 BeautifulSoup使用它,所以它在你的情况下很有用。 (BeatifulSoup本身只提供树表示,而不是事件)。

答案 2 :(得分:0)

考虑使用xml.sax。当我提出格式错误的XML时,可能会遇到很多不同的问题,请尝试将问题分成小块。

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

In xml.sax you provide the reader, the handler, and the input sources。更糟糕的是,使用这种技术,单个记录将无法恢复。它稍微多一点设置,但是逐步解析格式错误的Feed,记录错误记录的记录可能是你能做的最好的。

在日志中,请确保为自己提供足够的信息来重建原始记录,以便为无疑必须处理的所有案例添加其他恢复代码(例如创建badrecords _ today's date。xml所以你可以手动重新处理。

祝你好运。

答案 3 :(得分:0)

或者,您可以使用BeautifulSoup。恢复破碎的ML确实很好。