Python - XML 생성 및 파일 저장

파이썬에서 xml 객체를 생성하고 파일로 저장하는 방법을 소개합니다.

1. xml 객체 생성 및 파일 저장

아래 예제는 국가별 도시 데이터를 갖고 있는 xml 객체를 생성하며 파일로 저장합니다. 코드를 보시면 Root Element를 만들고, 그 아래에 Sub Element를 추가합니다. 최종적으로 ElementTree 객체로 만들고 이 tree 객체의 내용을 파일로 저장합니다.

from xml.etree.ElementTree import Element, SubElement, ElementTree


root = Element("Countries")
element1 = Element("Korea")
root.append(element1)

sub_element1 = SubElement(element1, "City")
sub_element1.text = "Seoul"

element2 = Element("Japanese")
root.append(element2)

sub_element2 = SubElement(element2, "City")
sub_element2.text = "Tokyo"

tree = ElementTree(root)

fileName = "example.xml"
with open(fileName, "wb") as file:
    tree.write(file, encoding='utf-8', xml_declaration=True)

위의 코드에서 example.xml으로 xml 파일을 저장하며, 파일을 확인해보면 아래와 같이 저장되어있습니다.

<?xml version='1.0' encoding='utf-8'?>
<Countries><Korea><City>Seoul</City></Korea><Japanese><City>Tokyo</City></Japanese></Countries>

보기 좋게 바꾸면 이렇습니다.

<?xml version='1.0' encoding='utf-8'?>
<Countries>
	<Korea>
		<City>Seoul</City>
	</Korea>
	<Japanese>
		<City>Tokyo</City>
	</Japanese>
</Countries>

2. xml 객체 생성 및 파일 저장 (Attribute 추가)

1의 예제는 Element만 추가한 xml 형식이었습니다. 아래 예제는 Attribute까지 추가하는 예제입니다. SubElement에서 set(attribute, value) 형식으로 Attribute를 추가할 수 있습니다.

from xml.etree.ElementTree import Element, SubElement, ElementTree


root = Element("Countries")
element1 = Element("Korea")
root.append(element1)

sub_element1 = SubElement(element1, "City")
sub_element1.text = "Seoul"
sub_element1.set("attr1", "value1")
sub_element1.set("attr2", "value2")

element2 = Element("Japanese")
root.append(element2)

sub_element2 = SubElement(element2, "City")
sub_element2.text = "Tokyo"
sub_element2.set("attr1", "value1")
sub_element2.set("attr2", "value2")

tree = ElementTree(root)

fileName = "example.xml"
with open(fileName, "wb") as file:
    tree.write(file, encoding='utf-8', xml_declaration=True)

example.xml 파일을 열어보면 아래와 같이 저장됩니다.

<?xml version='1.0' encoding='utf-8'?>
<Countries><Korea><City attr1="value1" attr2="value2">Seoul</City></Korea><Japanese><City attr1="value1" attr2="value2">Tokyo</City></Japanese></Countries>

보기 좋게 바꾸면 아래와 같습니다.

<?xml version='1.0' encoding='utf-8'?>
<Countries>
	<Korea>
		<City attr1="value1" attr2="value2">Seoul</City>
	</Korea>
	<Japanese>
		<City attr1="value1" attr2="value2">Tokyo</City>
	</Japanese>
</Countries>

3. xml 보기 좋게 저장 (Pretty)

1과 2의 예제에서 파일을 열어보면 xml의 text가 Tab과 개행 문자가 모두 제거되어 파일의 크기는 작아졌지만 보기에는 좋지 않았습니다.

xml의 text에 Tab과 개행 문자를 추가하면 보기 좋게 저장할 수 있습니다. 아래 예제는 2의 예제에서 _pretty_print(root)만 추가되었습니다. _pretty_print()는 xml 객체의 text에 Tab과 개행문자를 추가하여, 저장될 때 보기 좋게 저장되도록 합니다.

from xml.etree.ElementTree import Element, SubElement, ElementTree


def _pretty_print(current, parent=None, index=-1, depth=0):
    for i, node in enumerate(current):
        _pretty_print(node, current, i, depth + 1)
    if parent is not None:
        if index == 0:
            parent.text = '\n' + ('\t' * depth)
        else:
            parent[index - 1].tail = '\n' + ('\t' * depth)
        if index == len(parent) - 1:
            current.tail = '\n' + ('\t' * (depth - 1))


root = Element("Countries")
element1 = Element("Korea")
root.append(element1)

sub_element1 = SubElement(element1, "City")
sub_element1.text = "Seoul"
sub_element1.set("attr1", "value1")
sub_element1.set("attr2", "value2")

element2 = Element("Japanese")
root.append(element2)

sub_element2 = SubElement(element2, "City")
sub_element2.text = "Tokyo"
sub_element2.set("attr1", "value1")
sub_element2.set("attr2", "value2")

_pretty_print(root)

tree = ElementTree(root)

fileName = "example.xml"
with open(fileName, "wb") as file:
    tree.write(file, encoding='utf-8', xml_declaration=True)

example.xml 파일을 열어보면 아래와 같이 저장됩니다.

<?xml version='1.0' encoding='utf-8'?>
<Countries>
	<Korea>
		<City attr1="value1" attr2="value2">Seoul</City>
	</Korea>
	<Japanese>
		<City attr1="value1" attr2="value2">Tokyo</City>
	</Japanese>
</Countries>

4. xml 파일 읽고, 보기 좋게 출력 (1)

다음과 같이 xml.etree.ElementTree으로 xml 파일을 읽고 출력할 수 있습니다.

import xml.etree.ElementTree as ET


filePath = "./example.xml"
tree = ET.parse(filePath)
ET.dump(tree)

Output:

<Countries><Korea><City>Seoul</City></Korea><Japanese><City>Tokyo</City></Japanese></Countries>

4.1 Tab, 개행 문자 추가하여 보기 좋게 출력

위의 코드에서, _pretty_print()를 추가로 구현하여, xml 객체의 text에 Tab과 개행 문자를 추가하면 다음과 같이 보기 좋게 출력할 수 있습니다.

import xml.etree.ElementTree as ET


def _pretty_print(current, parent=None, index=-1, depth=0):
    for i, node in enumerate(current):
        _pretty_print(node, current, i, depth + 1)
    if parent is not None:
        if index == 0:
            parent.text = '\n' + ('\t' * depth)
        else:
            parent[index - 1].tail = '\n' + ('\t' * depth)
        if index == len(parent) - 1:
            current.tail = '\n' + ('\t' * (depth - 1))


filePath = "./example.xml"
tree = ET.parse(filePath)

_pretty_print(tree.getroot())

ET.dump(tree)

Output:

<Countries>
	<Korea>
		<City attr1="value1" attr2="value2">Seoul</City>
	</Korea>
	<Japanese>
		<City attr1="value1" attr2="value2">Tokyo</City>
	</Japanese>
</Countries>

5. xml 파일 읽고, 보기 좋게 출력 (2)

아래와 같이 xml.dom.minidom를 이용하여 xml을 읽고 보기 좋게 출력할 수 있습니다.

import xml.dom.minidom


dom = xml.dom.minidom.parse(fileName)
pretty_xml_as_string = dom.toprettyxml()
print(pretty_xml_as_string)

Output:

<?xml version="1.0" ?>
<Countries>
	<Korea>
		<City attr1="value1" attr2="value2">Seoul</City>
	</Korea>
	<Japanese>
		<City attr1="value1" attr2="value2">Tokyo</City>
	</Japanese>
</Countries>

References

Loading script...
codechachaCopyright ©2019 codechacha