xml 모듈

xml 모듈

  • xml 파일의 구조와 내용을 효율적으로 파싱하고 이용할 수 있는 여러 기능들을 제공한다.
  • 내장함수로 별도 라이브러리 설치가 필요 없다.

기본 사용법

Import

  • xml.etree.ElementTree 를 임포트해 사용할 수 있다.
1
from xml.etree import ElementTree as ET

xml 데이터 파싱

예시 데이터

  • example.xml 파일에 아래와 같은 내용을 가지고 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!--example.xml-->
<?xml version="1.0"?>
<gdpdata>
    <country name="Liechtenstein">
        <rank>1</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank>4</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank>68</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</gdpdata>

xml 파일 데이터 가져오기

(1) ET.parse() 이용하기

1
2
3
4
5
6
7
from xml.etree import ElementTree as ET

tree = ET.parse('example.xml')
root = tree.getroot()

print(root.tag)
>> 'gdpdata'

(2) fromstring() 을 통해 문자열을 직접 파싱하기

1
2
3
4
5
6
7
8
9
10
11
from xml.etree import ElementTree as ET

xml_data = ''
with open('example.xml', 'r') as f:
    lines = f.readlines()
    for line in lines:
        xml_data += line

root = ET.fromstring(xml_data)
print(root.tag)
>> 'gdpdata'

XML 구조 이용하기

tag

  • tag : XML 에서 데이터를 감싸는 구조적인 요소
  • 시작태그(<tag>)와 종료태그(</tag>)로 구성되거나, 빈 요소는 <tag/> 형태
  • 데이터의 이름이나 범위를 정하는 역할
1
2
3
4
5
6
7
from xml.etree import ElementTree as ET

tree = ET.parse('example.xml')
root = tree.getroot()

print(root.tag)
>> gdpdata

attrib

  • attrib : 태그 자체에 속성 값을 부여하는 형태
  • <tag key="value"> 형태로 사용됨
  • 주로 태그에 대한 메타데이터 역할
1
2
3
4
5
6
7
from xml.etree import ElementTree as ET

tree = ET.parse('example.xml')
root = tree.getroot()

print(root.attrib)
>> {}

이터레이션

  • XML 구조상 자식 노드가 있다면 이를 이터레이트 가능함
1
2
3
4
5
6
7
8
9
10
11
from xml.etree import ElementTree as ET

tree = ET.parse('example.xml')
root = tree.getroot()

for child in root:
    print(child.tag, child.attrib)

>> country {'name': 'Liechtenstein'}
>> country {'name': 'Singapore'}
>> country {'name': 'Panama'}
  • 또한 iter() 메서드를 이용해 서브트리를 이터레이트 할 수도 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
from xml.etree import ElementTree as ET

tree = ET.parse('example.xml')
root = tree.getroot()

for neighbor in root.iter('neighbor'):
    print(neighbor.attrib)

>> {'name': 'Austria', 'direction': 'E'}
>> {'name': 'Switzerland', 'direction': 'W'}
>> {'name': 'Malaysia', 'direction': 'N'}
>> {'name': 'Costa Rica', 'direction': 'W'}
>> {'name': 'Colombia', 'direction': 'E'}

text

  • 노드에 대한 값을 가져올 수 있다.
1
2
3
4
5
6
7
8
9
10
from xml.etree import ElementTree as ET

tree = ET.parse('example.xml')
root = tree.getroot()

print(root[0][1])
>> <Element 'year' at 0x120754cc0>

print(root[0][1].text)
>> 2008

findall

  • findall()은 현재 엘리먼트의 하위(자식 또는 그 이하 계층 포함) 중에서, 지정한 경로 또는 태그 이름과 일치하는 모든 엘리먼트를 리스트로 반환한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from xml.etree import ElementTree as ET

tree = ET.parse('example.xml')
root = tree.getroot()

for element in root.findall('country'):
    print(element.attrib)
    for child_ele in element.findall('neighbor'):
        print(child_ele.attrib)
    print('===================================')

>> {'name': 'Liechtenstein'}
>> {'name': 'Austria', 'direction': 'E'}
>> {'name': 'Switzerland', 'direction': 'W'}
>> ===================================
>> {'name': 'Singapore'}
>> {'name': 'Malaysia', 'direction': 'N'}
>> ===================================
>> {'name': 'Panama'}
>> {'name': 'Costa Rica', 'direction': 'W'}
>> {'name': 'Colombia', 'direction': 'E'}

find

  • find() 는 현재 엘리먼트 하위 중에서, 지정한 경로 또는 태그 이름과 일치하는 엘리먼트 중 처음 등장하는 엘리먼트를 반환한다.
1
2
3
4
5
6
7
8
9
10
11
12
from xml.etree import ElementTree as ET

tree = ET.parse('example.xml')
root = tree.getroot()

element = root.find('country')
child_ele = element.find('neighbor')

print(element.attrib)
print(child_ele.attrib)
>> {'name': 'Liechtenstein'}
>> {'name': 'Austria', 'direction': 'E'}

수정하고 파일로 저장하기

text 수정하기

  • text 를 수정하려면 <>.text = <값> 과 같이 수정할 수 있음
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from xml.etree import ElementTree as ET

tree = ET.parse('example.xml')
root = tree.getroot()

for rank in root.iter('rank'):
    print(rank.text)
    new_rank = str(int(rank.text) + 1)
    rank.text = new_rank

>> 1
>> 4
>> 68

for rank in root.iter('rank'):
    print(rank.text)

>> 2
>> 5
>> 69

set

  • 어트리뷰트를 추가하거나 수정하는 메서드
  • .set('<어트리뷰트이름>', '<어트리뷰트값>') 으로 사용한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from xml.etree import ElementTree as ET

tree = ET.parse('example.xml')
root = tree.getroot()

for rank in root.iter('rank'):
    new_rank = str(int(rank.text) + 1)
    rank.text = new_rank
    rank.set('updated', 'yes')

for rank in root.iter('rank'):
    print(rank.attrib)
    print(rank.text)

>> {'updated': 'yes'}
>> 2
>> {'updated': 'yes'}
>> 5
>> {'updated': 'yes'}
>> 69

append, remove

  • append : 새로운 자식을 추가하는 메서드
  • remove : 엘리먼트를 제거하는 메서드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from xml.etree import ElementTree as ET

tree = ET.parse('example.xml')
root = tree.getroot()

for element in root:
    if int(element.find('rank').text) > 50:
        root.remove(element)

for element in root.findall('country'):
    print(element.attrib)

>> {'name': 'Liechtenstein'}
>> {'name': 'Singapore'}

write

  • ET 를 파일에 쓰는 메서드
  • tree.write('파일경로') 와 같이 사용한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from xml.etree import ElementTree as ET

tree = ET.parse('example.xml')
root = tree.getroot()

for rank in root.iter('rank'):
    new_rank = str(int(rank.text) + 1)
    rank.text = new_rank
    rank.set('updated', 'yes')

for element in root:
    if int(element.find('rank').text) > 50:
        root.remove(element)

tree.write('example.xml')
  • 저장된 파일 결과
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--example.xml-->
<gdpdata>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E" />
        <neighbor name="Switzerland" direction="W" />
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N" />
    </country>
    </gdpdata>

Reference

https://docs.python.org/ko/3.13/library/xml.etree.elementtree.html

Comments