DOM (Document Object Model; どむ) は、 プログラムから XML 文書のような構造化された文書(document)を扱うための、文書のモデルです。 特定のプログラミング言語に依存しない仕様となっています。
Java のライブラリは DOM Level 3 の仕様に準拠しています。
DOM では、要素(element)やテキスト(text)といった文書の構成要素を、 木構造のノード(node)として扱います。
主なノード(Node)を以下に挙げます。
注: DOM4 では CDATA は特別扱いされなくなり Text ノードとなります。また、属性はノードではなくなります。
以下の XML 文書を考えます。
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<item>
<title>りんご</title>
<link>http://www.apple.com/jp/</link>
</item>
</channel>
</rss>
この XML文書を DOM tree で表現すると、以下のようになります。
rss
version
="2.0
"
channel
item
title
Text
: りんごlink
Text
: http://www.apple.com/jp/要素(Element)だけでなく、テキスト(Text)もノードになっていることに着目してください。 例えば title 要素の内容(文字列)は、title 要素の子ノードであるテキストの値となります。
なお、実際には字下げのための空白や改行もテキストとして扱われるため、それが DOM tree に反映されます。
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
■<channel>
■■<item>
■■■<title>りんご</title>
■■■<link>http://www.apple.com/jp/</link>
■■</item>
■</channel>
</rss>
rss
version
="2.0
"
Text
: ↵■channel
Text
: ↵■■item
Text
: ↵■■■title
Text
: りんごText
: ↵■■■link
Text
: http://www.apple.com/jp/Text
: ↵■■Text
: ↵■Text
: ↵ここまでに、Node, Document, Element, Text が登場しました。 DOM の仕様では、これらに対してどのような操作ができるのかが規定されています。 Java では、org.w3c.dom 以下のパッケージのインタフェースとして用意されています。
なお、これら DOM のインタフェースとは別に、 javax.xml 以下の各種パッケージに XML 全般のためのクラスが用意されています。
DOM を用いるプログラムでは、メモリ上に DOMツリーを構築し、それに対して操作を行います。
ここでは、XML文書を読み込んでツリーを探索する方法を学びます。 以下の XML文書を読み込んでみます。
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<item>
<title>りんご</title>
<link>http://www.apple.com/jp/</link>
</item>
<item>
<title>みかん</title>
<link>https://orangeamps.com/</link>
</item>
<item>
<title>バナナ</title>
<link>https://en.wikipedia.org/wiki/The_Velvet_Underground_%26_Nico</link>
</item>
</channel>
</rss>
eclipse を使っている場合には、プロジェクトのフォルダの直下に置いてください。
ここではまず、ファイルから読み込む場合を見てみましょう。
登場する主なクラス/インタフェースを以下に挙げます。
定型的な書き方ですが、 DOM ツリーを構築する際の入力として InputStream を与えることに着目しましょう。 ファイルを渡すことも、Webから取得したデータを渡すこともできます。
Document の getDocumentElement() を用いると、DOM ツリーの root要素を得ることができます。 このサンプルプログラムでは root要素の要素名を表示しているだけです。 ツリーをたどって情報を得る方法は次の節で学びます。
root要素からツリーをたどるには、ノード(Node)に対する操作を知る必要があります。
ノードに関する主な情報として、以下の3つがあります。
これらの情報は、それぞれ getNodeType(), getNodeName(), getNodeValue() というメソッドにより得ることができます。
NodeType を表す定数の主なものを以下に挙げます。
属性もノードとして扱われます(DOM3までは)。
root要素から子ノードをたどるには、Node に対する以下の操作を使います。
XMLでは、要素の出現順序に意味があったことを思い出しましょう。 子ノードは、同じ階層でも順序が決まっていますので、先頭から順に見ていくといった操作をすることができます。ノード node の子ノードをすべてたどる繰り返しは以下のように書けます。
for(Node current = node.getFirstChild(); current != null; current = current.getNextSibling())
子ノードを順にたどる際、着目しているノードが要素の場合にはその子ノードも考えられるため、 子ノードをたどるメソッドを再帰的に呼び出すことにより、ツリー全体を走査することができます。 深さ優先探索となります。