Help us understand the problem. What is going on with this article?

Pythonで名前空間付きのXMLを操作する(ElementTree)

More than 5 years have passed since last update.

初めに

xml.etree.ElementTree
http://docs.python.jp/2/library/xml.etree.elementtree.html
を使って、名前空間付きのxmlを解析します。

本文ではkml(Google Earthなどに使われてるフォーマット)
http://ja.wikipedia.org/wiki/KML
をターゲットにしているが、実態はXMLなので同様に扱うとする。

対象データ

対象のKML
<?xml version='1.0' encoding='UTF-8'?>
<kml xmlns="http://earth.google.com/kml/2.0">
<Document>
<name>Hoge</name>
 <Style id="Mapit">
 <IconStyle>
 <color>FFFFFFFF</color>
 <scale>1.0</scale>
 </IconStyle>
 </Style>
 <Style id="kml">
 <LineStyle>
 <color>FF0080FF</color>
 <width>1</width>
 </LineStyle>
 <PolyStyle>
 <color>AADDDDDD</color>
 </PolyStyle>
 </Style>
・・・
 </Document>
</kml>

一部省略しているが、とりあえずこんな形をしているKMLを対象とする。
PolyStyle->color
の値がAADDDDDDになっていますが、これを変えたいとします。

プログラムコード

XML書き換えプログラム
# -*- coding: utf-8 -*-

from xml.etree import ElementTree

#KMLファイルを読み込み
tree = ElementTree.parse("in.kml")
#namespaceを付加する
#これをしないと再書き出しの際に、全てのタグにns0:PolyStyleみたいになる
ElementTree.register_namespace('', 'http://earth.google.com/kml/2.0')

# //PolyStyle/colorを探す
for node in tree.findall(".//{http://earth.google.com/kml/2.0}PolyStyle/{http://earth.google.com/kml/2.0}color"):
    # 内容書き換え
    node.text="AA001122"

#書き出し
#3つ目の引数はtrueなら<?xml ・・?>を付加する。
tree.write("out.kml","UTF-8",True)

PolyStyle->color
の値がAA001122となって書き出されます。

解説

xml.etree.ElementTree.findallは、頭に"."がいる。
(FutureWarningとか言われる)

XPathのサブセットが扱えるらしい。
http://docs.python.jp/3/library/xml.etree.elementtree.html
(Python2に関する記事は、見つけられてない)

ここで問題なのが名前空間である。

名前空間
<kml xmlns="http://earth.google.com/kml/2.0">

がルートにあるため、それ以下は全て名前空間がかかる。

なのでパスを指定するときは、{}内で名前空間を付加し、タグを指定しなけばならない。

しかもPolyStyle->colorなので2回書かないといけない。

xpath
//{http://earth.google.com/kml/2.0}PolyStyle/{http://earth.google.com/kml/2.0}color"

(なにかいい方法が有りましたら教えて下さい。。。)

次に、register_namespace をする意味は、
writeで書きだしたXMLが

register_namespaceをしない出力
<ns0:PolyStyle>
 <ns0:color>AADDDDDD</ns0:color>
</ns0:PolyStyle>

みたいになるのを回避します。

ゆるぼ

register_namespaceしてるのでXPath指定がもっとスマート
(名前空間URIを何度も書かなくていいとか)に記述できないかなぁ。。。

参考

XPathで指定したテキストがある次の要素を取得する方法
http://qiita.com/yuki2006/items/1f96450fc744769872c5

[Python]ElementTreeのnamespaceをゴニョゴニョする
http://d.hatena.ne.jp/nullpobug/20110420/1303293319

yuki2006
すいません。 基本的に記事は備忘録ですが、 ツッコミなどはすごくお待ちしております。
http://yukicoder.me
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした