Python による XML の操作

2016年2月9日

はじめに

Python で XML を扱う方法について。

環境

  • Windows 7 64 bit
  • MSYS2 64 bit (MinGW w64)
  • Anaconda for Windows (Python 2.7)

XML ファイルの作成

Python で XML ファイルを作成するには、次のようにする。

create_xml.py

import xml.etree.ElementTree as ET

root = ET.Element('root')

sub = ET.SubElement(root, 'sub')

subsub = ET.SubElement(sub, 'subsub')
subsub.set('key', 'value')
subsub.text = 'text'

subsub2 = ET.SubElement(sub, 'subsub2')
subsub2.set('key2', 'value2')
subsub2.text = 'text2'

tree = ET.ElementTree(element=root)
tree.write('test.xml', encoding='utf-8', xml_declaration=True)

Element() で要素を作成し、SubElement() で要素に子要素を追加している。set() で属性を、text でテキストを設定している。ElementTree でツリーを作成し、write() でファイルに書き出している。

これを実行すると、次のファイルを得る。

test.xml

<?xml version='1.0' encoding='utf-8'?>
<root><sub><subsub key="value">text</subsub><subsub2 key2="value2">text2</subsub2></sub></root>

これでもよいのだが、出力がきれいでない。きれいに出力するには次のようにする。

create_xml2.py

import xml.etree.ElementTree as ET
import xml.dom.minidom as minidom

root = ET.Element('root')

sub = ET.SubElement(root, 'sub')

subsub = ET.SubElement(sub, 'subsub')
subsub.set('key', 'value')
subsub.text = 'text'

subsub2 = ET.SubElement(sub, 'subsub2')
subsub2.set('key2', 'value2')
subsub2.text = 'text2'

string = ET.tostring(root, 'utf-8')
pretty_string = minidom.parseString(string).toprettyxml(indent='  ')

with open('test.xml', 'w') as f:
    f.write(pretty_string)
<?xml version="1.0" ?>
<root>
  <sub>
    <subsub key="value">text</subsub>
    <subsub2 key2="value2">text2</subsub2>
  </sub>
</root>

XML ファイルの解析

XML ファイルを読むには次のようにする。

read_xml.py

import xml.etree.ElementTree as ET

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

for child in root.find('sub'):
    print child.tag
    print child.attrib
    print child.text

parse() でファイルを指定してツリーを作る。getroot() で最上位要素を得ている。find() で要素を探し、その子要素を巡回している。ここで child.tag は XML 作成の際に SubElement() の第 2 引数で指定した名前、child.attrib は set() で設定した key-value 型の辞書である。

実行結果は以下の通り。

$ python read_xml.py
subsub
{'key': 'value'}
text
subsub2
{'key2': 'value2'}
text2
subsub
{'key': 'value'}
text
subsub2
{'key2': 'value2'}
text2

find() は最初に見つけたものを返す。findall() だと当てはまるものすべてを返す。

for elem in root.findall('sub'):
    for child in elem:
        print child.tag
        print child.attrib
        print child.text

findall() は見つけた要素のリストを返してくるので、その子要素を見るにはリストの要素それぞれでループを回す必要がある。

参考