我正在努力让读者从破碎的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()
任何想法如何正确恢复?
答案 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确实很好。