2017-12-20 17 views
2

から親の属性を取得し、私は XMLは:iterparse要素

<data num_entries="1000000000"> 
    <item value="3.1324213213"></item> 
    <item value="6.2432343213"></item> 
    <!-- ... --> 
</data> 

のようなエントリを持つ大規模なXMLファイルを持っている(実際には、複数の dataのエントリがあると、彼らは、XMLツリー内のより深いですが、のは、それをシンプルに保つみましょう。 )

私はこのファイルをPythonで読んで、すべてitemをnumpyの配列に入れたいと思います。ファイルは非常に大きいので、ET.parse()はオプションではありません。メモリをのどに詰まらないようにするには、私は、これは動作しますが、itemsが少しずつ割り当てられているので、かなり遅いですelem.clear()

import xml.etree.cElementTree as ET 

items = [] 
for event, elem in ET.iterparse(filename): 
    if elem.tag == 'item': 
     items.append(float(elem.attrib['value'])) 
    elem.clear() 
items = numpy.array(items) 

ように iterparse()を使用しています。私は、すなわち、最初の配列を割り当てるために、周囲の dataブロックの num_entries情報を使用したい

items = None 
k = 0 
for event, elem in ET.iterparse(filename): 
    if elem.tag == 'item': 
     if items is None: 
      num_entries = get_num_entries_somehow() 
      items = numpy.empty(num_entries) 
     items[k] = float(elem.attrib['value']) 
     k += 1 
    elem.clear() 

のようなものは残念ながら、iterparseitemすべて後のsが反復されている親要素になります以上。

親属性にアクセスする方法iterparse()

答えて

3

あなたはしてXMLのルートからnum_entriesを取得することができます:上記の方法は良くないこれ、一度にすべてのツリーを解析します^

tree = ET.ElementTree(file=filename) 
root = tree.getroot() 
print(root.attrib.get('num_entries')) 

startイベントを有効にする方法はありますか?

for event, elem in ET.iterparse(filename, events=('start', 'end')): 
    if elem.tag == 'data' and event == 'start': 
     print(elem.attrib['num_entries']) 
    if elem.tag == 'item' and event == 'start': 
     items.append(float(elem.attrib['value'])) 
    elem.clear() 
+0

オプションはありません。ファイルは単純に大きすぎて一度に解析することはできません。私はOPでそれを明らかにした。 –

+1

@NicoSchlömer:それを指摘してくれてありがとう、私の答えを変更してください。 –

+0

ああ、私は今それを得る。 'events =( 'start'、 'end')'なしでは、パーサは最後にのみ解析し、前後でエントリを参照します。ちょうど私が必要なもの。ありがとうございました! –