XMLデータを操作する〜DOMの詳細:技術者のためのXML再入門(11)
前回「XMLプログラミングのためのAPI」ではDOMがツリー・ベースのオブジェクト指向APIであることを紹介した。今回は、オブジェクトの概念やオブジェクト指向のアクセス方法を解説する。DOMは、Internet Explorer 5以上やNetscape6以上をはじめ多くのツールでサポートされるAPIになってきており、XMLデータを操作するプログラムを書くときにも欠かせない技術だ。DOMの基本的な概念と機能を押さえよう。
DOMツリーと「オブジェクト」
第10回で考えたように、DOMはXMLデータ(注)のあらゆる要素をノードとしてとらえ、ノードのツリー(DOMツリー)としてメモリ上に展開する。そして展開されたDOMツリー上のノードをすべて「オブジェクト」としてとらえる。つまり、DOMは、DOM(Document Object Model)の名前にも表れているように、オブジェクトを使用してXMLデータをモデル化するのだ。
オブジェクト指向技術においてオブジェクトはプロパティとメソッドで構成されるように、DOMのオブジェクトも「属性」と「メソッド」で構成される。
●属性 オブジェクトが保持するデータや関連情報
●メソッド オブジェクトの振る舞いを制御する関数
これらDOMオブジェクトが提供する属性とメソッドを総称して「インターフェイス」と呼ぶ。
例を使ってオブジェクトの概念を明確にしておこう。次のリストにあるXMLデータは、図1にあるようなDOMツリーに変換される。
<?xml version="1.0" encoding="shift_JIS"> <company> <name>日本ユニテック</name> <address>東京都虎ノ門X丁目Y-Z</address> </company>
図1にあるように、DOMツリーのルートはDocumentオブジェクトで、XMLデータ全体を表す。Elementオブジェクトは要素を表し、Textオブジェクトは要素の内容のテキストを表す。
ElementオブジェクトやTextオブジェクトはそれぞれ属性を持っており、その中にオブジェクトについての情報が入っている。例えば、ElementオブジェクトのtagName(タグ名)属性には“name”や“address”などのタグ名が入っており、Textオブジェクトのdata(データ)属性には“日本ユニテック”や“東京都虎ノ門X丁目Y-Z”などの文字データが入っている。Elementオブジェクトにはほかにも、親子や兄弟関係を示す属性がある。このように、DOMオブジェクトの「属性」を参照することによって、DOMツリーをたどったり、データを取り出したりすることができる。
図1においていくつかのオブジェクトを取上げたが、DOMツリー全体の構造モデルは図2のようになる(細かな部分は省略してあるので、詳細については仕様書をご覧いただきたい)。
これらのオブジェクトは、「基本インターフェイス」と「拡張インターフェイス」に分類される。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オブジェクトが持っているツリー構造に関する属性は次のとおりである(ほかの属性については仕様書を参照)。
これらの属性はNodeインターフェイスを継承したほかのオブジェクトにも継承されるので、DocumentやElementなどのオブジェクトでも使用することができる。では、図1のDOMツリーで、Documentオブジェクトから文字列“東京都虎ノ門X丁目Y-Z”までをたどってみると次のようになる。
document.firstChild.lastChild.firstChild
図4にあるとおり、「Documentノード」からスタートし、その「最初の子(firstChild)」の「最後の子(lastChild)」の「最初の子(firstChild)」、すなわち2つ目のTextオブジェクトにたどり着く。
このように、階層関係を表す属性を使ってDOMツリーにアクセスすることができる。しかし、1つか2つ前後のノードをたどるのであればこの方法で行うことができるが、もっと長い経路をたどる場合、このやり方ではDOMツリー全体の構造を把握していなければならず、かなり複雑だ。そのうえDOMツリーを最初から順番に最後までたどらなければならないので、大きなデータを扱う際には速度の問題が生じる。
そのため、ダイレクトに特定のノードを取得したり変更・追加・削除したりするメソッドが用意されている。例えば、DocumentオブジェクトのgetElementsByTagNameメソッドは、引数としてタグ名を指定し、そのタグ名にマッチするノードを取得することができる。
getElementsByTagName("address")
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.