lxml iterparse 缺失子节点
我正在使用lxml的iterparse来读取非常大的XML文件。对于一个特定的主元素,我会检查它的子元素并处理每一个子元素。但是我发现,在检查某个元素的子元素时,解析器有时会漏掉一些子节点。我甚至打印了每个元素的长度,对于一个特定的元素标签,这个长度应该是固定的,但有时却比预期的要小。令人惊讶的是,这种情况通常发生在第五个块(一个块就是主元素出现一次)。有没有什么原因导致解析器会漏掉子节点呢?有没有什么线索?
示例代码-
from lxml import etree
def parseXml(context,attribList,elemList,mainElement):
for event, element in context:
if element.tag == mainElement and event=='start':
for child in element:
if child.tag in elemList:
print len(child) #for a given child,the len should be constant
#do things
elif event=='end':
element.clear()
谢谢!
1 个回答
4
在定义上下文的时候,记得把参数 events
设置为 ('end',)
,而不是 ('start',)
。否则,你可能会遇到你所描述的那种情况。
context=etree.iterparse(filehandle, events=('end',), tag=mainElement)
我觉得问题出在 lxml 这个库,它在一个线程中处理 XML,而在另一个线程中运行 parseXml
。这样的话,你可能在 parseXml
中就能找到 start
元素,但 lxml 还没解析到对应的 end
元素。所以当你遍历这个元素的子元素时,你得到的结果就不完整。
顺便提一下,这篇文章提供了一种很好的组织方式,专门用来处理非常大的 XML 文件:
def fast_iter(context, func, *args, **kwargs):
# http://www.ibm.com/developerworks/xml/library/x-hiperfparse/
# Author: Liza Daly
for event, elem in context:
func(elem, *args, **kwargs)
elem.clear()
while elem.getprevious() is not None:
del elem.getparent()[0]
del context
def parseXml(element,attribList,elemList):
for child in element:
if child.tag in elemList:
print len(child) #for a given child,the len should be constant
#do things
context=etree.iterparse(filehandle, events=('end',), tag=mainElement)
fast_iter(context, parseXml, attribList, elemList)