2012-10-09 10 views
18

필자는 (최대 1GB) 충분히 큰 xml 문서를 처리하고 파이썬으로 파싱해야합니다. 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() 

그리고 출력이 내 관심이 (간단한) 예제를 내가 진정한 XML 예제와 함께 상상하는 태그에 내가 (on_members_tag)이었다 알 수있는 별도의 변수를 만들 수 있었다이다

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 

같이이 잘 작동합니다 내가 처리해야하는 것은 중첩 된 태그가 더 많다는 것입니다.

또한 매우 축소 된 예입니다. 따라서 더 많은 태그, 더 많은 내부 태그 및 다른 태그 이름, 속성 등을 얻기 위해 xml에 직면 할 수 있다고 가정 할 수 있습니다.

그럼 질문입니다. 나는 무섭게 여기 무언가를하고 있니? 나는 이보다 더 우아한 해결책이 있어야만한다고 느낀다.

+0

당신이 데이터로 무엇을 할 것인가? 모든 것을 보관할 파이썬 데이터 구조를 만들거나 반복하는 동안 db에 저장하거나 다른 것을 작성 하시겠습니까? –

+0

@JanneKarila : 데이터가 파이썬 구조에 저장 될 수도 있고, db에 저장되거나, 파일에 덤프 될 수도 있습니다.이 경우에는 db에 쓰여질 것이라고 가정 할 수 있습니다. –

답변

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입니다. 당신은 색소폰을 얻습니다. 스트림을 반복 할 수 있고 관심있는 노드를 찾으면 해당 노드를 DOM 조각에로드 할 수 있습니다.

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

좋은 답변입니다. 사용이 매우 간단합니다. 46GB xml 파일을 구문 분석 할 수 있음 –

관련 문제