[python] 파이썬에서 XML을 어떻게 파싱합니까?

XML이 포함 된 데이터베이스에 많은 행이 있으며 특정 노드 속성의 인스턴스를 계산하기 위해 Python 스크립트를 작성하려고합니다.

내 나무는 다음과 같습니다

<foo>
   <bar>
      <type foobar="1"/>
      <type foobar="2"/>
   </bar>
</foo>

Python을 사용하여 속성 "1""2"XML에 액세스하려면 어떻게 해야합니까?



답변

나는 제안한다 ElementTree. 같은 API의 다른 호환 가능한 구현 (예 : lxml, 및 cElementTreePython 표준 라이브러리 자체)이 있습니다. 그러나 이러한 맥락에서 그들이 주로 추가하는 것은 훨씬 더 빠릅니다. 프로그래밍의 용이성은 ElementTree정의 하는 API에 달려 있습니다.

먼저 rootXML에서, 예를 들어 XML 함수를 사용하거나 다음과 같은 파일을 구문 분석 하여 Element 인스턴스 를 빌드 하십시오.

import xml.etree.ElementTree as ET
root = ET.parse('thefile.xml').getroot()

또는에 표시된 다른 많은 방법 중 하나 ElementTree입니다. 그런 다음 다음과 같이하십시오.

for type_tag in root.findall('bar/type'):
    value = type_tag.get('foobar')
    print(value)

그리고 비슷한, 일반적으로 매우 간단한 코드 패턴.


답변

minidom 가장 빠르고 매우 간단합니다.

XML :

<data>
    <items>
        <item name="item1"></item>
        <item name="item2"></item>
        <item name="item3"></item>
        <item name="item4"></item>
    </items>
</data>

파이썬 :

from xml.dom import minidom
xmldoc = minidom.parse('items.xml')
itemlist = xmldoc.getElementsByTagName('item')
print(len(itemlist))
print(itemlist[0].attributes['name'].value)
for s in itemlist:
    print(s.attributes['name'].value)

산출:

4
item1
item1
item2
item3
item4


답변

BeautifulSoup 을 사용할 수 있습니다 :

from bs4 import BeautifulSoup

x="""<foo>
   <bar>
      <type foobar="1"/>
      <type foobar="2"/>
   </bar>
</foo>"""

y=BeautifulSoup(x)
>>> y.foo.bar.type["foobar"]
u'1'

>>> y.foo.bar.findAll("type")
[<type foobar="1"></type>, <type foobar="2"></type>]

>>> y.foo.bar.findAll("type")[0]["foobar"]
u'1'
>>> y.foo.bar.findAll("type")[1]["foobar"]
u'2'


답변

많은 옵션이 있습니다. cElementTree 는 속도와 메모리 사용에 문제가있는 경우 우수 해 보입니다. 단순히 파일을 사용하여 읽는 것보다 오버 헤드가 거의 없습니다 readlines.

관련 요소는 cElementTree 웹 사이트 에서 복사 한 아래 표에서 확인할 수 있습니다 .

library                         time    space
xml.dom.minidom (Python 2.1)    6.3 s   80000K
gnosis.objectify                2.0 s   22000k
xml.dom.minidom (Python 2.4)    1.4 s   53000k
ElementTree 1.2                 1.6 s   14500k  
ElementTree 1.2.4/1.3           1.1 s   14500k  
cDomlette (C extension)         0.540 s 20500k
PyRXPU (C extension)            0.175 s 10850k
libxml2 (C extension)           0.098 s 16000k
readlines (read as utf-8)       0.093 s 8850k
cElementTree (C extension)  --> 0.047 s 4900K <--
readlines (read as ascii)       0.032 s 5050k   

@jfs 에서 지적했듯이 cElementTreePython과 함께 번들로 제공됩니다.

  • 파이썬 2 : from xml.etree import cElementTree as ElementTree.
  • Python 3 : from xml.etree import ElementTree(가속 C 버전이 자동으로 사용됨)

답변

단순화를 위해 xmltodict 를 제안 합니다.

XML을 OrderedDict로 구문 분석합니다.

>>> e = '<foo>
             <bar>
                 <type foobar="1"/>
                 <type foobar="2"/>
             </bar>
        </foo> '

>>> import xmltodict
>>> result = xmltodict.parse(e)
>>> result

OrderedDict([(u'foo', OrderedDict([(u'bar', OrderedDict([(u'type', [OrderedDict([(u'@foobar', u'1')]), OrderedDict([(u'@foobar', u'2')])])]))]))])

>>> result['foo']

OrderedDict([(u'bar', OrderedDict([(u'type', [OrderedDict([(u'@foobar', u'1')]), OrderedDict([(u'@foobar', u'2')])])]))])

>>> result['foo']['bar']

OrderedDict([(u'type', [OrderedDict([(u'@foobar', u'1')]), OrderedDict([(u'@foobar', u'2')])])])


답변

lxml.objectify 는 정말 간단합니다.

샘플 텍스트 가져 오기 :

from lxml import objectify
from collections import defaultdict

count = defaultdict(int)

root = objectify.fromstring(text)

for item in root.bar.type:
    count[item.attrib.get("foobar")] += 1

print dict(count)

산출:

{'1': 1, '2': 1}


답변

파이썬에는 국외 XML 파서에 대한 인터페이스가 있습니다.

xml.parsers.expat

유효성을 검사하지 않는 파서이므로 잘못된 XML이 발견되지 않습니다. 그러나 파일이 정확하다는 것을 알고 있다면, 이것은 꽤 좋으며 원하는 정확한 정보를 얻을 수 있으며 나머지는 즉시 버릴 수 있습니다.

stringofxml = """<foo>
    <bar>
        <type arg="value" />
        <type arg="value" />
        <type arg="value" />
    </bar>
    <bar>
        <type arg="value" />
    </bar>
</foo>"""
count = 0
def start(name, attr):
    global count
    if name == 'type':
        count += 1

p = expat.ParserCreate()
p.StartElementHandler = start
p.Parse(stringofxml)

print count # prints 4