【问题标题】:python libxml2 reader and XML_PARSE_RECOVERpython libxml2阅读器和XML_PARSE_RECOVER
【发布时间】:2010-10-06 10:43:07
【问题描述】:

我正试图让阅读器从损坏的 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()

任何想法如何正确恢复?

【问题讨论】:

标签: python libxml2


【解决方案1】:

我不太确定 libxml2 绑定的当前状态。甚至 libxml2 站点也建议改用 lxml。解析这棵树并忽略 &amp; 在 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)

【讨论】:

  • 不幸的是,我也研究了 lxml,但您上面的建议使用 DOM api,因为文档的大小不是一个选项。 lxml iterparse API 不支持恢复。
  • 如果您只是尝试增量解析,请查看 lxml 的 _FeedParser 接口,我将编辑上面的示例及其用法。我一直无法找到一种迭代的解析方法,它在解析时会产生元素。 codespeak.net/lxml/api/lxml.etree._FeedParser-class.html
  • 感谢您的所有努力。从技术上讲,我们需要的是增量解析和事件驱动的带有恢复的元素拉取。可惜 lxml 不符合这些要求。
【解决方案2】:

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

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

编辑:然后看看 python 标准库中的 sgmllib。 BeautifulSoup 使用它,因此它对您的情况很有用。 (BeatifulSoup 本身只提供树表示,不提供事件)。

【讨论】:

  • 在我查看的示例中,每个单独的源都以不同的方式破坏了 xml!其他常见错误是打开和关闭标签的大小写不匹配。至少要可靠地解决每一个问题是很困难的。最重要的是,他们无法修复源代码 - 我们必须像以前的提供商一样支持他们!
【解决方案3】:

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

您提到您有一个非常大的 XML 文件,它可能有许多您需要串行处理的记录。并且每条记录(例如&lt;item&gt;...&lt;/item&gt; 都有一个开始和结束标签,大概 - 这些将是您的恢复点。

In xml.sax you provide the reader, the handler, and the input sources。更糟糕的是,使用这种技术将无法恢复单个记录。它的设置要多一些,但每次记录不良记录时增量解析格式错误的提要可能是您能做的最好的事情。

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

祝你好运。

【讨论】:

    【解决方案4】:

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

    【讨论】:

    • BeautifulSoup 是基于 DOM 的,因此将整个文档加载到内存中,这不符合要求。除了内存需求之外,对于任何相当大的东西,它也相当慢。
    猜你喜欢
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-02
    • 1970-01-01
    相关资源
    最近更新 更多