Python:xml.etree.ElementTree
RDF からデータを取り出したいと思い、はじめて xml.etree.ElementTree モジュールを利用しました。ハマったのは、パス指定の名前空間部分。
参考にしたコードサンプルでは「.//タグ名」で子孫の要素を参照できると書いてあった。そこで、title のテキストを取得しようと思い、次のように記述したのだが。
if __name__ == "__main__": import xml.etree.ElementTree as etree source = 'sample.rdf' rootTree = etree.parse(source) title = rootTree.findtext('.//title') print title.encode('utf-8','ignore')
何も出力されなかった。
rdf:RDF channel title link description iterms rdf:Seq rdf:li(rdf:resource) item item
そこで、イテレータで順番に各要素を参照してみた。
if __name__ == "__main__": import xml.etree.ElementTree as etree source='sample.rdf' rootTree=etree.parse(source) print rootTree # for i in rootTree.getiterator(): if i.tag:# print 'tag : '+ i.tag
なぜか 「print rootTree」のように1行文字列を出力しておかないと、それ以降のものが出力されない。
また、tag がないノードもあるので、「if i.tag:」のように条件を付与する必要がある。
なお、属性もみたいときは、次の文を加えればよい。
if i.attrib: print str(i.attrib)
上記のスクリプトを実行すると、次のような結果に。
<xml.etree.ElementTree.ElementTree instance at 0xe44490> tag : {http://www.w3.org/1999/02/22-rdf-syntax-ns#}RDF tag : {http://purl.org/rss/1.0/}channel tag : {http://purl.org/rss/1.0/}title tag : {http://purl.org/rss/1.0/}link tag : {http://purl.org/rss/1.0/}description tag : {http://purl.org/dc/elements/1.1/}publisher tag : {http://purl.org/dc/elements/1.1/}date tag : {http://purl.org/dc/elements/1.1/}language tag : {http://purl.org/rss/1.0/}items tag : {http://www.w3.org/1999/02/22-rdf-syntax-ns#}Seq tag : {http://www.w3.org/1999/02/22-rdf-syntax-ns#}li tag : {http://www.w3.org/1999/02/22-rdf-syntax-ns#}li (中略) tag : {http://purl.org/rss/1.0/}item tag : {http://purl.org/rss/1.0/}title tag : {http://purl.org/rss/1.0/}link tag : {http://purl.org/rss/1.0/}description tag : {http://purl.org/dc/elements/1.1/}creator tag : {http://purl.org/dc/elements/1.1/}publisher tag : {http://purl.org/dc/elements/1.1/}date tag : {http://purl.org/dc/elements/1.1/}rank tag : {http://purl.org/dc/elements/1.1/}point tag : {http://purl.org/dc/elements/1.1/}arrow tag : {http://purl.org/rss/1.0/}item (以下略)
上の結果、tag の値というのは、名前空間付であることがわかった。
一番最初のスクリプトを次のように書き換えた。
title = root.findtext('.//{http://purl.org/rss/1.0/}title')
ちゃんとタイトルが表示された。
名前空間を押さえなければいけないことがわかりました。