2011-11-14 4 views
2

私はlxml iterparseを使用して巨大なxmlファイルを読み込みます。与えられたmainElementに対して、私は子要素をチェックし、各子を処理します。しかし、要素内の子を調べると、実際にパーサはいくつかの子ノードを実際には見逃していることに気付きます。私は各要素の長さを印刷しました。要素の長さは、要素タグの定数でなければなりませんが、時にはそれより小さくなります。そして、驚くべきことに、これは通常5番目のブロック(1ブロック=> mainElement発生)で発生します。パーサーが子ノードを見逃すべき理由はありますか?すべての手がかりは?lxml iterparse mising子ノード

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() 

おかげコード -

サンプル!

答えて

2

コンテキストを定義するときは、('start',)ではなく、events('end',)に設定してください。それ以外の場合は、あなたが記述している動作を得ることができます。

context=etree.iterparse(filehandle, events=('end',), tag=mainElement) 

私はこの問題は、他でparseXmlを実行中にlxmlのは、1つのスレッドでXMLを処理しているということですので、lxmlのは、対応するend要素に解析する行われる前に、あなたがparseXmlstart要素に達することができると思います。したがって、要素の子をループすると、部分的な結果しか得られません。ところで


this articleは非常に大規模な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) 
+0

おかげ@unutbuを。私はevents =( 'start'、 'end')を使用していて、 'start'イベント(上記の私のコードを編集)の要素を処理しています。そして、あなたが言ったことはまさに起こっていることだと思います。開始イベントで処理するとき、子ノードはまだ読み取られません。代わりにエンドイベントで処理するようにコードをすばやく更新しましたが、うまくいくようです。私はまだテストしています。もう一度ありがとう、本当にありがとう! – Rinks

+0

これは、要素内のすべての子を取得していないようです。要素内の最後の子のみを返します。推理? –