suzukiyou blog

建築設計とかpythonとかその辺をとりあえずする

xml.etree.ElementTree.ElementTree.write()に関して

xml.etree.ElementTree

pythonxmlを扱うにあたって、python標準ライブラリにxmlモジュールがあるのでそれを使う。xmlモジュールには大きくはxml.domとxml.saxとxml.etreeというのがありますが、etree.ElementTreeがいろいろ参考になるところが多いので、それを使う。W3C標準だとDOMを使うべきなのかな、って気もするけど、まあローカルで使うだけなのでElementTreeでいいでしょう。

参考としては、だいたいこの辺。
19.13. xml.etree.ElementTree — ElementTree XML API — Python 2.7ja1 documentation
PythonでElementTreeを使ってXMLを処理する方法 - hikm's blog

ElementTreeの使い方

だいたい以下のようになる。

#coding:utf-8

import xml.etree.ElementTree as ET

filename="sample.xml"

#読み込むとき
#tree=ET.parse(filename)
#root=tree.getroot()
#root.tag="hoge"

#新規で作るとき
root=ET.Element("hoge")

#タグを変える
root.tag="fuga"

#テキストを入れる
root.text=u"こんにちは"

#attribute要素を入れる
root.attrib["zokusei"]="foo"
#よくよく読むとあんまり良くない構文らしい
#root.set("zokusei","foo")とかのが良いという。

#子のElementを入れる
root.append(ET.Element("bar"))
#複数突っ込むときはroot.extend(<i>ElementsList</i>)

#子の中からタグ名で探す
root.find("bar")

#一回ElementTreeにして、書き出す。

tree=ET.ElementTree(root)
tree.write(filename,"utf-8")
実行結果

sample.xmlが出力されて、中身はこんなかんじになる。

<?xml version="1.0"?>
<fuga zokusei="foo">
test
<bar/>
</fuga>
メリットとデメリット

xml.etree.ElementTree超簡単やん!これ使えばええやん!読み出しはET.parse、書き出しはtree.write()したらええんや!というのがうれしい。だいたいそれぐらいの能力で満足できそう。ただし、write()にはしばしば怒られうる。と言うのは例えば上のコードにおいて

#tag,text,attribにintリテラルとかfloatリテラルを突っ込んでもエラーにならない。
root=ET.Element(1)
root.tag=1.1
root.text=1
root.set(1.1,5)
#しかしそういうElementを含むtreeをwriteするとerror
tree=ET.ElementTree(root)
tree.write(filename,"utf-8") #できない

微妙に腹立ちます。

文字コード形式をutf-8の設定にした場合の話ですけど、
tree.write()はstr型とunicode型はそのまま書けるし、parse()でそのまま読むらしい。
けど少なくともintとかfloatは書けない。numpy.int16とかそのへんも試してないけどきっと書けないだろうな。

付き合い方を考える

xmlは基本的にはDBの書式だと思うし、一回のスクリプトで一つのxmlファイルに何度もアクセスして何度も書き換えて、ってものではないだろう。一回ロードして、プログラム上でグリグリ変更して、最終的にセーブします、ってなもんでしょう。
で、その上で書き込み時になにかこう、それっぽいクラスからElementクラスへ渡すことになるのだから、そこでそのへんのチェックなり何なりすればよろしかろう、と思います。