파이썬의 XML 파서는 XML 파일을 읽고 그 안에서 유용한 정보를 추출할 수 있는 가장 쉬운 방법 중 하나를 제공합니다. 이 튜토리얼에서는 파이썬의 ElementTree XML API를 사용해 XML 파일을 파싱하고, 수정하고, 새로 생성하는 방법을 단계별로 살펴보겠습니다.
ElementTree는 XML 데이터를 추출·파싱·변환하는 데 가장 널리 쓰이는 표준 라이브러리로, 별도의 설치 과정 없이 바로 사용할 수 있다는 큰 장점이 있습니다.
그럼 지금부터 파이썬 XML 파서를 ElementTree와 함께 활용하는 방법을 알아보겠습니다.
예제 1: XML 파일 생성하기
새 XML 파일 만들기
먼저 하나의 요소(element)와 하위 요소(sub-element)를 포함하는 새로운 XML 파일을 만들어 보겠습니다.
# 필요한 라이브러리 임포트
import xml.etree.ElementTree as xml
def createXML(filename):
# 루트(root) 요소부터 시작합니다
root = xml.Element("users")
children1 = xml.Element("user")
root.append(children1)
tree = xml.ElementTree(root)
with open(filename, "wb") as fh:
tree.write(fh)
if __name__ == "__main__":
createXML("testXML.xml")위 프로그램을 실행하면 현재 작업 디렉터리에 testXML.xml이라는 새 파일이 생성됩니다.
생성된 파일의 내용은 다음과 같습니다:
<users><user /></users>
여기서 한 가지 주의할 점은, 파일을 저장할 때 'wb' 모드, 즉 바이너리(binary) 모드로 열었다는 것입니다. ElementTree의 write() 메서드는 바이너리 모드로 열린 파일 객체를 기대하기 때문입니다.
XML 요소에 값 추가하기
이번에는 위 프로그램의 XML 요소들에 실제 값을 넣어 보겠습니다. SubElement()를 사용하면 하위 요소를 추가할 수 있고, text 속성으로 값을 지정할 수 있습니다.
# 필요한 라이브러리 임포트
import xml.etree.ElementTree as xml
def createXML(filename):
# 루트(root) 요소부터 시작합니다
root = xml.Element("users")
children1 = xml.Element("user")
root.append(children1)
userId1 = xml.SubElement(children1, "Id")
userId1.text = "hello"
userName1 = xml.SubElement(children1, "Name")
userName1.text = "Rajesh"
tree = xml.ElementTree(root)
with open(filename, "wb") as fh:
tree.write(fh)
if __name__ == "__main__":
createXML("testXML.xml")프로그램을 실행하면 값이 담긴 새 요소들이 추가된 것을 확인할 수 있습니다:
<users>
<user>
<Id>hello</Id>
<Name>Rajesh</Name>
</user>
</users>출력 결과가 정상적으로 잘 나오는 것을 볼 수 있습니다.
이제 기존 XML 파일을 불러와 데이터를 수정하는 방법을 살펴보겠습니다.
XML 데이터 편집하기
다음과 같은 XML 파일이 있다고 가정해 보겠습니다.
newdata.xml
<users>
<user>
<id>1a</id>
<name>Rajesh</name>
<salary>NA</salary>
</user>
<user>
<id>2b</id>
<name>TutorialsPoint</name>
<salary>NA</salary>
</user>
<user>
<id>3c</id>
<name>Others</name>
<salary>NA</salary>
</user>
</users>위 XML 파일에서 각 사용자(user)의 salary(급여) 값을 일괄적으로 업데이트해 보겠습니다. iter() 메서드를 사용하면 특정 태그 이름을 가진 모든 요소를 한 번에 순회할 수 있습니다.
# 필요한 라이브러리 임포트
import xml.etree.ElementTree as ET
def updateET(filename):
# 루트(root) 요소부터 시작합니다
tree = ET.ElementTree(file=filename)
root = tree.getroot()
# 모든 salary 태그를 순회하며 값을 변경합니다
for salary in root.iter('salary'):
salary.text = '500000'
tree = ET.ElementTree(root)
with open("newdata.xml", "wb") as fh:
tree.write(fh)
if __name__ == "__main__":
updateET("newdata.xml")실행 결과
프로그램 실행 후 파일을 확인해 보면, 모든 salary 값이 'NA'에서 '500000'으로 변경된 것을 볼 수 있습니다.
예제: 파이썬 XML 파서로 데이터 읽기
이번에는 파일에 저장된 XML 데이터를 파싱(parse)해서 화면에 출력하는 또 다른 프로그램을 작성해 보겠습니다.
# 필요한 라이브러리 임포트
import xml.etree.cElementTree as ET
def parseXML(file_name):
# ElementTree로 XML을 파싱합니다
tree = ET.ElementTree(file=file_name)
print(tree.getroot())
root = tree.getroot()
print("tag=%s, attrib=%s" % (root.tag, root.attrib))
# 자식 요소를 통해 정보를 가져옵니다!
print("-" * 25)
print("getchildren()으로 순회합니다")
print("-" * 25)
users = root.getchildren()
for user in users:
user_children = user.getchildren()
for user_child in user_children:
print("%s=%s" % (user_child.tag, user_child.text))
if __name__ == "__main__":
parseXML("newdata.xml")실행 결과
<Element 'users' at 0x0551A5A0>
tag = users, attrib = {}
-------------------------
Iterating using getchildren()
-------------------------
id = 1a
name = Rajesh
salary = 500000
id = 2b
name = TutorialsPoint
salary = 500000
id = 3c
name = Others
salary = 500000루트 요소의 태그 이름(users)과 속성(attrib)이 먼저 출력되고, 이어서 각 user 요소의 자식 태그(id, name, salary)와 그 값들이 순서대로 화면에 표시됩니다.
참고: 최신 파이썬 버전에서의 주의사항
위 예제에서 사용된 getchildren() 메서드는 파이썬 3.2에서 폐기(deprecated)되었으며, 파이썬 3.9부터는 완전히 제거되었습니다. 최신 버전에서는 요소를 리스트처럼 직접 순회하는 방식이 권장됩니다:
for user in root: # users 아래의 모든 user 요소
for child in user: # 각 user의 자식 요소(id, name, salary)
print("%s=%s" % (child.tag, child.text))또한 xml.etree.cElementTree 모듈 역시 폐기된 상태이므로, 항상 xml.etree.ElementTree를 사용하는 것이 좋습니다.