2012-10-09 14 views
18

मुझे एक्सएमएल दस्तावेजों को संभालना है जो काफी बड़े हैं (1 जीबी तक) और उन्हें अजगर के साथ पार्स करें। मैं iterparse() फ़ंक्शन (SAX शैली पार्सिंग) का उपयोग कर रहा हूं।ElementTree iterparse strategy

मेरी चिंता का विषय निम्नलिखित है, कल्पना आप इस

<?xml version="1.0" encoding="UTF-8" ?> 
<families> 
    <family> 
    <name>Simpson</name> 
    <members> 
     <name>Homer</name> 
     <name>Marge</name> 
     <name>Bart</name> 
    </members> 
    </family> 
    <family> 
    <name>Griffin</name> 
    <members> 
     <name>Peter</name> 
     <name>Brian</name> 
     <name>Meg</name> 
    </members> 
    </family> 
</families> 

समस्या निश्चित रूप से, है की तरह एक xml है पता करने के लिए जब मैं एक परिवार के नाम हो रही है (द सिम्पसंस के रूप में) और जब मैं नाम हो रही है उस परिवार के सदस्य (उदाहरण के लिए होमर) में से एक

जो मैं अब तक कर रहा हूं वह "स्विच" का उपयोग करना है जो मुझे बताएगा कि मैं "सदस्यों" टैग के अंदर हूं या नहीं, कोड इस तरह दिखेगा

import xml.etree.cElementTree as ET 

__author__ = 'moriano' 

file_path = "test.xml" 
context = ET.iterparse(file_path, events=("start", "end")) 

# turn it into an iterator 
context = iter(context) 
on_members_tag = False 
for event, elem in context: 
    tag = elem.tag 
    value = elem.text 
    if value : 
     value = value.encode('utf-8').strip() 

    if event == 'start' : 
     if tag == "members" : 
      on_members_tag = True 

     elif tag == 'name' : 
      if on_members_tag : 
       print "The member of the family is %s" % value 
      else : 
       print "The family is %s " % value 

    if event == 'end' and tag =='members' : 
     on_members_tag = False 
    elem.clear() 

और यह ठीक काम करता है के रूप में उत्पादन

The family is Simpson 
The member of the family is Homer 
The member of the family is Marge 
The member of the family is Bart 
The family is Griffin 
The member of the family is Peter 
The member of the family is Brian 
The member of the family is Meg 

मेरी चिंता का विषय है कि इस (सरल) उदाहरण के साथ मैं एक अतिरिक्त चर पता करने के लिए जो टैग में मैं था (on_members_tag) सच एक्सएमएल उदाहरण के साथ कल्पना बनाने के लिए किया था है कि मुझे संभालना है, उनके पास अधिक घोंसला वाले टैग हैं।

यह भी ध्यान रखें कि यह एक बहुत ही कम उदाहरण है, इसलिए आप मान सकते हैं कि मुझे अधिक टैग, अधिक आंतरिक टैग और विभिन्न टैग नाम, विशेषताओं आदि के साथ एक एक्सएमएल का सामना करना पड़ सकता है।

तो सवाल है। क्या मैं यहाँ कुछ बेवकूफ बेवकूफ कर रहा हूँ? मुझे लगता है कि इसके लिए एक और अधिक सुरुचिपूर्ण समाधान होना चाहिए।

+0

आप डेटा के साथ क्या करेंगे? इसे सभी को पकड़ने के लिए पाइथन डेटा संरचना का निर्माण करें, या पुनरावृत्ति करते समय डीबी में स्टोर करें, या कुछ और? –

+0

@JanneKarila: डेटा को पायथन संरचना पर रखा जा सकता है, डीबी या डंप को फ़ाइल में सहेज सकता है, यह प्रोसेस पर निर्भर करेगा, इस मामले में आप मान सकते हैं कि यह डीबी –

उत्तर

24

यहां एक संभावित दृष्टिकोण है: हम पथ सूची बनाए रखते हैं और माता-पिता नोड को खोजने के लिए पीछे की ओर देखते हैं।

path = [] 
for event, elem in ET.iterparse(file_path, events=("start", "end")): 
    if event == 'start': 
     path.append(elem.tag) 
    elif event == 'end': 
     # process the tag 
     if elem.tag == 'name': 
      if 'members' in path: 
       print 'member' 
      else: 
       print 'nonmember' 
     path.pop() 
+0

पर लिखा जाएगा सरल, सुरुचिपूर्ण और नौकरी करता है । बहुत बहुत धन्यवाद :) –

+0

क्या इस दृष्टिकोण के लिए कोई मानक नाम है? मेरा मानना ​​है कि इस दृष्टिकोण का उपयोग ऐसी कई समस्याओं के लिए किया जाता है। यदि आप इसका नाम बता सकते हैं, तो मैं गहराई से खोद सकता हूं और इसे समझ सकता हूं। –

11

pulldom इसके लिए उत्कृष्ट है। आपको एक सैक्स स्ट्रीम मिलती है। आप स्ट्रीम के माध्यम से पुनरावृत्त कर सकते हैं, और जब आपको कोई नोड मिलता है जिसमें आपकी दिलचस्पी है, उस नोड को डोम खंड में लोड करें।

import xml.dom.pulldom as pulldom 
import xpath # from http://code.google.com/p/py-dom-xpath/ 

events = pulldom.parse('families.xml') 
for event, node in events: 
    if event == 'START_ELEMENT' and node.tagName=='family': 
     events.expandNode(node) # node now contains a dom fragment 
     family_name = xpath.findvalue('name', node) 
     members = xpath.findvalues('members/name', node) 
     print('family name: {0}, members: {1}'.format(family_name, members)) 

उत्पादन:

family name: Simpson, members: [u'Hommer', u'Marge', u'Bart'] 
family name: Griffin, members: [u'Peter', u'Brian', u'Meg'] 
+0

यह एक बहुत अच्छा समाधान है, हालांकि मैं आपको इसे एक स्वीकार्य उत्तर के रूप में नहीं दे सकता (मुझे nneonneo का जवाब बेहतर लगता है), हालांकि, यह निश्चित रूप से एक सुरुचिपूर्ण समाधान की तरह दिखता है। धन्यवाद! –

+0

ग्रेट उत्तर। उपयोग करने के लिए बहुत आसान है। 46 जीबी एक्सएमएल फाइल को पार्स करने की अनुमति है –

संबंधित मुद्दे