Python - XML生成とファイルの保存

Pythonで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

Related Posts

codechachaCopyright ©2019 codechacha