developer tip

파이썬에서 XML을 어떻게 구문 분석합니까?

optionbox 2020. 9. 28. 09:00
반응형

파이썬에서 XML을 어떻게 구문 분석합니까?


xml을 포함하는 데이터베이스에 많은 행이 있고 해당 행을 통과하는 Python 스크립트를 작성하고 특정 노드 속성의 인스턴스 수를 계산하려고합니다. 예를 들어, 내 트리는 다음과 같습니다.

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

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


나는 제안한다 ElementTree. 같은 동일한 API의 다른 호환 구현이 있습니다 lxml, 그리고 cElementTree파이썬 표준 라이브러리 자체는; 그러나 이러한 맥락에서 그들이 주로 추가하는 것은 훨씬 더 빠른 속도입니다. 프로그래밍 부분의 용이성은 API에 따라 달라집니다 ElementTree.

먼저 XML 함수를 사용하거나 다음과 같은 파일을 구문 분석 root하여 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가 훌륭해 보입니다. .NET을 사용하여 파일을 읽는 것에 비해 오버 헤드가 거의 없습니다 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파이썬 번들로 제공 :

  • 파이썬 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}

Python에는 expat 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

다른 가능성을 추가하기 위해 간단한 xml-to-python-object 라이브러리이므로 untangle 을 사용할 수 있습니다 . 여기에 예가 있습니다.

설치

pip install untangle

용법

xml 파일 (약간 변경됨) :

<foo>
   <bar name="bar_name">
      <type foobar="1"/>
   </bar>
</foo>

untangle로 속성에 액세스 :

import untangle

obj = untangle.parse('/path_to_xml_file/file.xml')

print obj.foo.bar['name']
print obj.foo.bar.type['foobar']

출력은 다음과 같습니다.

bar_name
1

풀기에 대한 자세한 정보는 여기 에서 찾을 수 있습니다 .
또한 (호기심이 있다면) 여기 에서 XML 및 Python 작업을위한 도구 목록을 찾을 수 있습니다 (이전 답변에서 가장 일반적인 도구가 언급 된 것도 볼 수 있습니다).


declxml을 제안 할 수 있습니다 .

전체 공개 : ElementTree를 사용하여 수십 줄의 명령 적 구문 분석 / 직렬화 코드를 작성할 필요없이 XML과 Python 데이터 구조간에 변환하는 방법을 찾고 있었기 때문에이 라이브러리를 작성했습니다.

declxml을 사용하면 프로세서사용 하여 XML 문서의 구조를 선언적으로 정의하고 XML과 Python 데이터 구조 간의 매핑 방법을 정의합니다. 프로세서는 직렬화 및 구문 분석뿐만 아니라 기본 수준의 유효성 검사에도 사용됩니다.

Python 데이터 구조로 파싱하는 것은 간단합니다.

import declxml as xml

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

processor = xml.dictionary('foo', [
    xml.dictionary('bar', [
        xml.array(xml.integer('type', attribute='foobar'))
    ])
])

xml.parse_from_string(processor, xml_string)

출력을 생성합니다.

{'bar': {'foobar': [1, 2]}}

동일한 프로세서를 사용하여 데이터를 XML로 직렬화 할 수도 있습니다.

data = {'bar': {
    'foobar': [7, 3, 21, 16, 11]
}}

xml.serialize_to_string(processor, data, indent='    ')

다음 출력을 생성합니다.

<?xml version="1.0" ?>
<foo>
    <bar>
        <type foobar="7"/>
        <type foobar="3"/>
        <type foobar="21"/>
        <type foobar="16"/>
        <type foobar="11"/>
    </bar>
</foo>

딕셔너리 대신 개체로 작업하려는 경우 프로세서를 정의하여 개체간에 데이터를 변환 할 수도 있습니다.

import declxml as xml

class Bar:

    def __init__(self):
        self.foobars = []

    def __repr__(self):
        return 'Bar(foobars={})'.format(self.foobars)


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

processor = xml.dictionary('foo', [
    xml.user_object('bar', Bar, [
        xml.array(xml.integer('type', attribute='foobar'), alias='foobars')
    ])
])

xml.parse_from_string(processor, xml_string)

다음 출력을 생성합니다.

{'bar': Bar(foobars=[1, 2])}

여기에 cElementTree.

try:
    import cElementTree as ET
except ImportError:
  try:
    # Python 2.5 need to import a different module
    import xml.etree.cElementTree as ET
  except ImportError:
    exit_err("Failed to import cElementTree from any known place")      

def find_in_tree(tree, node):
    found = tree.find(node)
    if found == None:
        print "No %s in file" % node
        found = []
    return found  

# Parse a xml file (specify the path)
def_file = "xml_file_name.xml"
try:
    dom = ET.parse(open(def_file, "r"))
    root = dom.getroot()
except:
    exit_err("Unable to open and parse input definition file: " + def_file)

# Parse to find the child nodes list of node 'myNode'
fwdefs = find_in_tree(root,"myNode")

출처:

http://www.snip2code.com/Snippet/991/python-xml-parse?fromPage=1


Python xml.domxml.dom.minidom은 매우 쉽습니다. DOM은 많은 양의 XML에는 좋지 않지만 입력이 상당히 적 으면 제대로 작동합니다.


import xml.etree.ElementTree as ET
data = '''<foo>
           <bar>
               <type foobar="1"/>
               <type foobar="2"/>
          </bar>
       </foo>'''
tree = ET.fromstring(data)
lst = tree.findall('bar/type')
for item in lst:
    print item.get('foobar')

이것은 foobar 속성의 값을 인쇄합니다.


XML

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

PYTHON_CODE

import xml.etree.cElementTree as ET

tree = ET.parse("foo.xml")
root = tree.getroot() 
root_tag = root.tag
print(root_tag) 

for form in root.findall("./bar/type"):
    x=(form.attrib)
    z=list(x)
    for i in z:
        print(x[i])

산출:

foo
1
2

xml.etree.ElementTree 대 lxml

These are some pros of the two most used libraries I would have benefit to know before choosing between them.

xml.etree.ElementTree:

  1. From the standard library: no needs of installing any module

lxml

  1. Easily write XML declaration: for instance do you need to add standalone="no"?
  2. Pretty printing: you can have a nice indented XML without extra code.
  3. Objectify functionality: It allows you to use XML as if you were dealing with a normal Python object hierarchy.node.

참고URL : https://stackoverflow.com/questions/1912434/how-do-i-parse-xml-in-python

반응형