連載
» 2002年09月10日 00時00分 公開

技術者のためのXML再入門(11):XMLデータを操作する〜DOMの詳細

前回「XMLプログラミングのためのAPI」ではDOMがツリー・ベースのオブジェクト指向APIであることを紹介した。今回は、オブジェクトの概念やオブジェクト指向のアクセス方法を解説する。DOMは、Internet Explorer 5以上やNetscape6以上をはじめ多くのツールでサポートされるAPIになってきており、XMLデータを操作するプログラムを書くときにも欠かせない技術だ。DOMの基本的な概念と機能を押さえよう。

[吉田稔, 青木秀起,日本ユニテック]

DOMツリーと「オブジェクト」

 第10回で考えたように、DOMはXMLデータ(注)のあらゆる要素をノードとしてとらえ、ノードのツリー(DOMツリー)としてメモリ上に展開する。そして展開されたDOMツリー上のノードをすべて「オブジェクト」としてとらえる。つまり、DOMは、DOM(Document Object Model)の名前にも表れているように、オブジェクトを使用してXMLデータをモデル化するのだ。

(注) W3CによるXMLの仕様書では、XMLで記述された情報を「XML文書(XML Document)」と呼んでいる。しかしXMLは、電子書籍などの文書以外に、電子商取引などのさまざまなデータの記述に用いられる。そこで、本連載ではXMLで記述された文書やデータを総称して「XMLデータ」と呼ぶことにする。


 オブジェクト指向技術においてオブジェクトはプロパティとメソッドで構成されるように、DOMのオブジェクトも「属性」と「メソッド」で構成される。

属性   オブジェクトが保持するデータや関連情報
メソッド オブジェクトの振る舞いを制御する関数

 これらDOMオブジェクトが提供する属性とメソッドを総称して「インターフェイス」と呼ぶ。

 例を使ってオブジェクトの概念を明確にしておこう。次のリストにあるXMLデータは、図1にあるようなDOMツリーに変換される。

<?xml version="1.0" encoding="shift_JIS">
<company>
  <name>日本ユニテック</name>
  <address>東京都虎ノ門X丁目Y-Z</address>
</company>
リスト1 XMLデータ
図1 DOMツリー 図1 DOMツリー

 図1にあるように、DOMツリーのルートはDocumentオブジェクトで、XMLデータ全体を表す。Elementオブジェクトは要素を表し、Textオブジェクトは要素の内容のテキストを表す。

 ElementオブジェクトやTextオブジェクトはそれぞれ属性を持っており、その中にオブジェクトについての情報が入っている。例えば、ElementオブジェクトのtagName(タグ名)属性には“name”や“address”などのタグ名が入っており、Textオブジェクトのdata(データ)属性には“日本ユニテック”や“東京都虎ノ門X丁目Y-Z”などの文字データが入っている。Elementオブジェクトにはほかにも、親子や兄弟関係を示す属性がある。このように、DOMオブジェクトの「属性」を参照することによって、DOMツリーをたどったり、データを取り出したりすることができる。

 図1においていくつかのオブジェクトを取上げたが、DOMツリー全体の構造モデルは図2のようになる(細かな部分は省略してあるので、詳細については仕様書をご覧いただきたい)。

図2 DOMツリー全体の構造モデル 図2 DOMツリー全体の構造モデル

 これらのオブジェクトは、「基本インターフェイス」と「拡張インターフェイス」に分類される。XMLデータへのアクセスは、「基本インターフェイス」と「拡張インターフェイス」を組み合わせて行う。次の一覧表をご覧いただきたい。

オブジェクト 説明
DOMException メソッドを使用する際に発生する例外を定義するオブジェクト
DOMImplementation 文書オブジェクト・モデルの特定のインスタンスに依存しない処理を実行するためのオブジェクト
DocumentFragment XMLデータの一部を表現するオブジェクト
Document XMLデータ全体を表すオブジェクト
Node XMLデータを構成するすべてのDOMオブジェクトの基礎となるオブジェクト
NodeList 順序付けされたノードのコレクション
NamedNodeMap 「名前」を用いてノードにアクセス可能なコレクションを表現するオブジェクト
CharacterData Text、Comment、CDATASectionオブジェクトによって継承される属性やメソッドを提供するオブジェクト
Attr 属性を表すオブジェクト(Elementノードの子ではない)
Element 要素を表すオブジェクト
Text テキストを表すオブジェクト
Comment XMLデータ中のコメントを表すオブジェクト
表1 基本インターフェイス

オブジェクト 説明
CDATASection XMLデータ中のCDATAセクションを表すオブジェクト
DocumentType XMLデータのDOCTYPE宣言を表すオブジェクト
Notation DTD内で宣言されるNOTATIONを表すオブジェクト
Entity XMLデータ中のエンティティを表現するオブジェクト(エンティティそのものをモデル化する)
EntityReference XMLデータ中のエンティティ参照を表すオブジェクト
ProcessingInstruction 処理命令を表すオブジェクト
表2 拡張インターフェイス

 表1の中で、DocumentやElementなどのオブジェクトは「XMLの構成要素という観点」から見たインターフェイスで、Nodeオブジェクトは「ツリー構造上の観点」から見たインターフェイスだ。従って、XMLの要素を表すオブジェクトは、ElementであるとともにNodeでもあるということになる。

 DOMでは、DOMオブジェクトが持つこの二面性を解決するために「継承」という概念を採用している。継承とは、ほかのインターフェイスの性質を受け継ぐというオブジェクト指向の概念だ。DOM Level2 Coreでは、Attr、CharacterData、DocumentType、DocumentFragment、Document、Element、Entity、EntityReference、Notation、ProcessingInstruction、Comment、Text、CDATASectionがNodeのインターフェイスを継承することになっている。

DOMツリーにアクセスする

 では次に、DOMツリーにアクセスしてみよう。Nodeオブジェクトだけを使って、ある程度のツリー操作を行えるようになっている。Nodeオブジェクトが持っているツリー構造に関する属性は次のとおりである(ほかの属性については仕様書を参照)。

図3 Nodeオブジェクトが持つ、ツリー構造に関する属性 図3 Nodeオブジェクトが持つ、ツリー構造に関する属性

 これらの属性はNodeインターフェイスを継承したほかのオブジェクトにも継承されるので、DocumentやElementなどのオブジェクトでも使用することができる。では、図1のDOMツリーで、Documentオブジェクトから文字列“東京都虎ノ門X丁目Y-Z”までをたどってみると次のようになる。

document.firstChild.lastChild.firstChild
リスト2 DOMツリーのアクセス方法
図4 DOMツリーのたどり方 図4 DOMツリーのたどり方

 図4にあるとおり、「Documentノード」からスタートし、その「最初の子(firstChild)」の「最後の子(lastChild)」の「最初の子(firstChild)」、すなわち2つ目のTextオブジェクトにたどり着く。

 このように、階層関係を表す属性を使ってDOMツリーにアクセスすることができる。しかし、1つか2つ前後のノードをたどるのであればこの方法で行うことができるが、もっと長い経路をたどる場合、このやり方ではDOMツリー全体の構造を把握していなければならず、かなり複雑だ。そのうえDOMツリーを最初から順番に最後までたどらなければならないので、大きなデータを扱う際には速度の問題が生じる。

 そのため、ダイレクトに特定のノードを取得したり変更・追加・削除したりするメソッドが用意されている。例えば、DocumentオブジェクトのgetElementsByTagNameメソッドは、引数としてタグ名を指定し、そのタグ名にマッチするノードを取得することができる。

getElementsByTagName("address")
リスト3 getElementsByTagNameメソッドの書き方

 getElementsByTagNameの戻り値はNodeListオブジェクトであり、“address”という名前を持つElementオブジェクトが取得される。

 この記事では、DOMツリーにアクセスするための属性と、タグ名でDOMツリーにアクセスするためのメソッド(getElementsByTagName)を紹介したが、このほかにも、便利なメソッドが用意されており、DOMツリーを自在に操作することができる。その一部を紹介しよう。

メソッド オブジェクト 機能
新規作成
createElement Document 要素を新規作成
createTextNode Document テキストを新規作成
createAttribute Document 属性を新規作成
追加
appendChild Node 子ノードのリストの最後にノードを新規追加
insertBefore Node 指定された子ノードの前にノードを挿入
setAttribute Element 要素に属性を追加
削除
removeChild Node ノードの子を削除
removeNameditem NamedNodeMap 名前で指定されたノードを削除
取得
getElementsByTagName Document 指定された名前の要素のリストを取得
getParentNode Node ノードの親を取得
getAttributes Node ノードの属性リストを取得
getNamedItem NamedNodeMap 名前で指定されたノードを取得
表3 DOMツリーを操作するためのメソッド

 DOMのほかの機能については仕様書「Document Object Model (DOM) Level 2 Core Specification」をご覧いただきたい。

最後に

 約1年にわたり、本連載では、スキーマ(DTD、XML Schema、Relax)、名前空間(Namespaces in XML)、表示(CSS、XSLT、XSL)、構造変換(XSLT、XPath)、リンク(XLink、XPointer、XML Base)、API(DOM、SAX)など、XMLの基本規格を中心に解説してきた。“いまさら聞けない”ほどにXMLの知名度は高まり、その応用分野も驚くほど広がりを見せている。こんな業種でも? と思えるような分野にもXMLが採用されるようになり、基本規格の実装やXMLベースの応用規格の開発が進んでいる。

 しかし、XMLは万能薬ではなく、ビジネスにおける課題を克服し効率化を図るための、ビジネス・メソッドである。XMLの急速な進展にも焦らず、XMLの本質を踏まえたうえで適材適所に採用し、ビジネスに役立てていただきたい。


Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。