9

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

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

編集:これが私がこれまでに持っているものです。

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

2 に答える 2

8

メモリに収まらない大きな 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>')

whereは、保持する必要がある場合にkeep(page)返します。Truepage

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

比較のために、小さなxml ファイルを変更するには、次のことができます。

# 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')
于 2013-03-17T03:59:51.873 に答える
1

おそらく、私の同様の質問に対する答えがあなたを助けることができます.

これを .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 だけだと思います)。この行でインポートされた lxml を使用しています。

from lxml import etree as ET

うまくいけば、これが(必要に応じて追加のコードコンテキストに関する私のリンクされた質問とともに)あなたを助けることができます!

于 2013-03-17T02:08:38.237 に答える