では前回書いた通りPythonでDOMを使い、ツリー上のデータ構造でXMLファイルの内容をメモリ上に読みこんでみる。今回読み込んでみるのは以下のXMLファイル。
—–
sample.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- This is a sample xml document --> <country> <name>Japan</name> <population>120,000,000</population> <capital> <name>Tokyo</name> <population>12,645,525</population> <capital>Shinjuku</capital> </capital> </country>
で囲まれた部分はプロローグと呼ばれるらしく、このXMLに関する色々な情報を記述する欄らしいが、詳しくはまだ分からない。ここではXMLのバージョンと文字エンコードの指定をしている。二行目はコメント欄*1。
ではこのXMLを、以下のプログラムを使って読みこんでみる。
from xml.dom import minidom, Node def scanNode(node, level = 0): msg = node.__class__.__name__ if node.nodeType == Node.ELEMENT_NODE: msg += ", tag: " + node.tagName if node.nodeType == Node.TEXT_NODE: msg += " (" + node.wholeText + ")" print " " * level * 4, msg if node.hasChildNodes: for child in node.childNodes: scanNode(child, level + 1) if __name__ == '__main__': doc = minidom.parse('sample.xml') scanNode(doc)
xml.dom.minidomモジュールに関してはオンラインリファレンス等に詳しい説明があるが、dom用の軽量で単純なAPIを提供してくれるのでminiらしい。NodeモジュールはXML文書を
doc = minidom.parse('sample.xml')
でパースした際に返ってくるデータのノードの属性などが規定されているモジュールのようだ。こちらもオンラインマニュアルが参考になりそう。
上記の一文を実行するとXMLのデータ構造が全てメモリ上に読み込まれる。なので容量の大きいXMLファイルを読み込むと結構な時間がかかった。データが全て読み込まれるとminidom.parseはXMLドキュメントのトップノードを返してくれるので、scanNode関数によりトップノードから下位のノードに向かって再帰的にノードの情報を調べ、内容の表示を行っている。下位のノードにまた下位のノードがあれば、どんどん再帰的に処理が進む。
以下が実行結果となる。
Document Comment Element, tag: country Text ( ) Element, tag: name Text (Japan) Text ( ) Element, tag: population Text (120,000,000) Text ( ) Element, tag: capital Text ( ) Element, tag: name Text (Tokyo) Text ( ) Element, tag: population Text (12,645,525) Text ( ) Element, tag: capital Text (Shinjuku) Text ( ) Text ( )
Textという属性が表しているのは
Documentという属性はこのXMLファイル全体を表す属性。Commentは見てのとおりコメントを表しており、Elementという属性はタグで囲まれたひとつのセットを表現しているようだ。
<tag>data</tag>
は一つのElementだし、
<tag> <foo>data</foo> </tag>
だとひとつのElementの中にもうひとつElementがあるという再起構造となる。TextもDocumentもCommentもElementも全てがDOMが規定するXMLファイルを表現する構成要素であり、全てNodeクラスのサブクラスとなっている。
次回はさらに、DOMの使い方に関して踏み込んでみよう。
*1:ちなみにこのコメントの書き方は、はてな記法の下書きとかぶっている