XML이 포함 된 데이터베이스에 많은 행이 있으며 특정 노드 속성의 인스턴스를 계산하기 위해 Python 스크립트를 작성하려고합니다.
내 나무는 다음과 같습니다
<foo>
<bar>
<type foobar="1"/>
<type foobar="2"/>
</bar>
</foo>
Python을 사용하여 속성 "1"
및 "2"
XML에 액세스하려면 어떻게 해야합니까?
답변
나는 제안한다 ElementTree
. 같은 API의 다른 호환 가능한 구현 (예 : lxml
, 및 cElementTree
Python 표준 라이브러리 자체)이 있습니다. 그러나 이러한 맥락에서 그들이 주로 추가하는 것은 훨씬 더 빠릅니다. 프로그래밍의 용이성은 ElementTree
정의 하는 API에 달려 있습니다.
먼저 root
XML에서, 예를 들어 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 에서 지적했듯이 cElementTree
Python과 함께 번들로 제공됩니다.
- 파이썬 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