2013-03-14 7 views
8

非常に大きな(〜40GB)XMLファイルを解析し、そこから特定の要素を削除し、結果を新しいxmlファイルに書き出す必要があります。私はPythonのElementTreeからiterparseを使用しようとしてきましたが、私はツリーを変更し、結果のツリーを新しいXMLファイルに書き込む方法について混乱しています。私はitertreeのドキュメントを読んだことがあるが、それは解決されていない。これを行う簡単な方法はありますか?python ElementTreeのitertree関数を使用して、変更されたツリーを出力ファイルに書き込む

ありがとうございました!

EDIT:これまで私がこれまで持っていたことは次のとおりです。

import xml.etree.ElementTree as ET 
import re 

date_pages = [] 
f=open('dates_texts.xml', 'w+') 

tree = ET.iterparse("sample.xml") 

for i, element in tree: 
    if element.tag == 'page': 
     for page_element in element: 
      if page_element.tag == 'revision': 
       for revision_element in page_element: 
        if revision_element.tag == '{text': 
         if len(re.findall('20\d\d', revision_element.text.encode('utf8'))) == 0: 
          element.clear() 
+0

あなたの試行でコードが表示されますか(不完全であっても)?ゼロから何かを書くのではなく、修正すると時間を節約できます。 –

+0

上記の質問にコードを追加しました。 – LateCoder

+0

私は早くそれを見つけました。申し訳ありませんが、私は他のもので忙しいですが、私はすぐに見てお約束します。その間、私はあなたの質問をチャットに持ち込んで、もっと注意を促しました。 –

答えて

1

おそらくmy similar questionの回答が役に立ちます。

の.xmlファイルにこのバックの書き方については、私は私のスクリプトの下でこれをやってしまったが:

with open('File.xml', 'w') as t: # I'd suggest using a different file name here than your original 
    for line in ET.tostring(doc): 
     t.write(line) 
    t.close 
print('File.xml Complete') # Console message that file wrote successfully, can be omitted 

変数docがどこに匹敵する、私のスクリプト内で以前からあります私は、この持っているtree = ET.iterparse("sample.xml")ています

doc = ET.parse(filename) 

私が代わりにElementTreeののlxmlのを使用してきたのが、私は書き出す部分はまだ動作するはずだと思う(私はそれが主のElementTreeを扱うことができないだけでXPathのものだと思う。)Iこれでインポートされたlxmlを使用していますライン:

from lxml import etree as ET 

うまくいけば、これは(あなたがそれを必要とする場合、いくつかの追加コードのコンテキストのための私のリンクの質問と一緒に)あなたを助けることができます!

+1

'tree.write( 'File.xml')'を使用して、 'tree = ET.parse(source)'を変更した後にファイルに書き込むことができます。注:ET.tostring(doc)内の 'for c 'コードは、一度に* 1文字を書き込みます。 'ET.tostring()'を使いたいなら、一度に 't.write(ET.tostring(doc))'を書くことができます。 'with'文はファイルを自動的に閉じます。その内部に' t.close() 'は必要ありません。私の答えの[大小のxmlファイルの書き方について]の例を参照してください。(0120-336-501) – jfs

6

メモリに収まらない大きなxmlがある場合、一度に1つの要素を直列化しようとする可能性があります。例えば、<root><page/><page/><page/>...</root>文書構造を仮定し、可能な名前空間の問題を無視して:

import xml.etree.cElementTree as etree 

def getelements(filename_or_file, tag): 
    context = iter(etree.iterparse(filename_or_file, events=('start', 'end'))) 
    _, root = next(context) # get root element 
    for event, elem in context: 
     if event == 'end' and elem.tag == tag: 
      yield elem 
      root.clear() # free memory 

with open('output.xml', 'wb') as file: 
    # start root 
    file.write(b'<root>') 

    for page in getelements('sample.xml', 'page'): 
     if keep(page): 
      file.write(etree.tostring(page, encoding='utf-8')) 

    # close root 
    file.write(b'</root>') 

keep(page)戻っTruepageは例えば保持すべきか:小さな XMLを変更するために、比較のために

import re 

def keep(page): 
    # all <revision> elements must have 20xx in them 
    return all(re.search(r'20\d\d', rev.text) 
       for rev in page.iterfind('revision')) 

をファイル:

# parse small xml 
tree = etree.parse('sample.xml') 

# remove some root/page elements from xml 
root = tree.getroot() 
for page in root.findall('page'): 
    if not keep(page): 
     root.remove(page) # modify inplace 

# write to a file modified xml tree 
tree.write('output.xml', encoding='utf-8') 
+0

ライブラリに「」と「」を印刷する方法はありますか'あなたのために、開始タグの属性や名前空間の宣言を保存しながら、ルート要素をメモリに保持しないで保存しますか? – binki

+0

@binki: 'getelements()'に 'root'変数がありますか?それがどういう意味だと思いますか? – jfs

+0

なぜ 'file.write(b '')'をお持ちですか? – binki

関連する問題