連載
» 2018年04月06日 05時00分 公開

Dev Basics/Keyword:Document Object Model:HTML/XMLドキュメントとプログラミング言語をつなぐAPI

DOMはHTMLドキュメントなどをツリー状のデータ構造として取り扱い、これを参照/操作するためのデータ構造やインタフェースを定義したもの。

[かわさきしんじ,Insider.NET編集部]
「Dev Basics/Keyword」のインデックス

連載「Dev Basics/Keyword」

 Document Object Model(DOM)は、HTMLドキュメントおよびXMLドキュメントをツリー状のデータ構造として扱い、それをプログラムから参照したり操作したりするためのデータ構造やインタフェース(API)を定義したもの。W3CおよびWHATWGにより仕様が策定されている。

 DOMはこれまでにW3CによりLevel 1〜4が勧告されている。その一方、現在ではWHATWGDOM Living Standard(変更が継続的に行われる標準)として策定をしている(W3Cが2015年11月に勧告したDOM Level 4はWHATWGのDOM Living Standardをベースとしたもの)。

DOMの特徴

 DOMが定義しているのは、「ドキュメントの論理的な構造」と「ドキュメントにアクセスしたり、それを操作したりするための手法」である。DOMではHTMLドキュメントなどを「ツリー」状の構造として扱う。よくある例だが、以下のようなHTMLドキュメントがあったとしよう。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>Document</title>
</head>
<body>
  <h1>Title</h1>
  <ul>
    <li>item1</li>
    <li>item2</li>
  </ul>
</body>
</html>

サンプルのHTMLドキュメント

 DOMでは、これを以下のような「オブジェクトがツリー構造に形成されたもの」として扱う。これを「ドキュメントツリー」「DOMツリー」などと呼ぶ。また、「ドキュメントツリーの操作」(特定のノードを参照したり、それを変更したりすること)を短く「DOM操作」と呼ぶこともよくある。

上のHTMLドキュメントをDOMのドキュメントツリーとして表現したもの 上のHTMLドキュメントをDOMのドキュメントツリーとして表現したもの
実際には空白文字(改行などを含む)で形成されるノードが生成されるが、ここでは省略している。

 ツリーを構成する個々の要素のことを「ノード」と呼ぶ。ノードは「メソッドやプロパティ」といった属性を持った「オブジェクト指向言語におけるオブジェクト」と同様なものである。DOMが定めるのは、これらのオブジェクトが「どのような属性を持つか」の抽象的な定義(インタフェース)であり、その実装はドキュメントをパースして、ツリー状のデータ構造を作成するプログラムに委ねられている。そうしたプログラムの代表的なものがWebブラウザといえる。

 HTMLなどのドキュメントをパースした結果として作成されるツリーのルートとなるのは、皆さんおなじみの「document」オブジェクトだ。このオブジェクトが実装しているDocumentインタフェースはDOM Living Standardの定義を借りると、次のようになっている(実際には、Documentインタフェースを拡張した「HTMLDocument」インタフェース)。

interface Document : Node {
  // …… 省略 …・
  HTMLCollection getElementsByTagName(DOMString qualifiedName);

  // …… 省略 …・
  [CEReactions, NewObject] Element createElement(DOMString localName,
    optional (DOMString or ElementCreationOptions) options);

  // …… 省略 …・
};


DOM Living StandardにおけるDocumentインタフェースの定義

 「var elms = document.getElementsByTagName(……)」のようにして使ったことがあるであろうメソッドが定義されていることが分かる(最も有名であろうgetElementByIdメソッドはまた別のインタフェースで定義されているが、Documentインタフェースではそのインタフェースを「ミックスイン」することで、このメソッドが使えるようになっている)。

 このように、ツリーを構成するノードはオブジェクトであり、それぞれがその種類(型)に応じたプロパティや操作を公開している。ソースとなる(例えば)HTMLドキュメントをWebブラウザなどのプログラムが読み込んで、そこからドキュメントツリーを構築することで、それぞれのノード(オブジェクト)が公開している各種のプロパティやメソッドをプログラミング言語(多くの場合ECMAScriptのことだ)が扱えるようになる。

 ドキュメントツリーを形成するノードには次のような種類がある。冒頭に示した図ではこれらの種類ごとに色を分けてある。

  • Nodeインタフェース:ノードの種類を示すプロパティ、親ノード/子ノード/兄弟ノードを走査するためのプロパティなどを持ち、多くのノードの基底になっている
  • Documentインタフェース:ドキュメントツリーのルートとなるノード。上図では薄い灰色の四角形で示した
  • Elementインタフェース:ドキュメント内の要素(例:HTMLドキュメントであれば<div>「要素」など)。上図では薄い水色で示した
  • Attrインタフェース:要素などが持つ属性(例:HTMLドキュメントであれば「id属性」「class属性」など)。上図では登場していない(属性を指定していないため)
  • Textインタフェース:個々の要素が含むテキストを表すノード(このインタフェースはNodeインタフェースを継承しない)。上図では薄い黄色で示した
  • Commentインタフェース:ドキュメントに含まれているコメントを表すノード。上図には登場しない

 この他にも、ドキュメントの種類を表すDocumentTypeインタフェース、ドキュメントツリーの一部分を表すDocumentFragmentインタフェースなど、ノードを形成するオブジェクトにはいろいろなものがある。

 DOMが定めるのは、そうしたオブジェクトがどういう意味合いで使われ、どんなプロパティやメソッドを持つかや、それらのオブジェクトがどのような関係を持っているかといった事柄だ。

 そして、DOMが定めるさまざまなインタフェースを利用することで、プログラミング言語からはDOMの内容を参照したり、動的にその内容を変更したりできるようになる。例えば、以下のようなコードを考えてみよう。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title id="title">Document</title>
</head>
<body>
  <script>
    var pnode = document.createElement("p");
    var textnode = document.createTextNode("Hello world");
    pnode.appendChild(textnode);
    document.body.appendChild(pnode);
  </script>
</body>
</html>

JavaScriptでページの内容を作成しているページ

 ここでは<script>要素内で<body>要素内に<p>要素を追加している。コードを見ると分かるが、document.createElementメソッドで<p>要素を作成し(これは上で見たElement型のノード)、さらにdocument.createTextNodeメソッドでそこに表示するテキストを含んだノードを作成してから(こちらは上で見たText型のノード)、<p>要素の子ノードとしてテキストノードを追加している。ノードを作成しただけでは、それはブラウザに表示されない。それをドキュメントツリーへと挿入する(ここでは<body>要素の子ノードとして追加する)ことで、「Hello world」と表示されるようになる。

上記のHTMLファイルをChromeで開いたところ 上記のHTMLファイルをChromeで開いたところ

 Webコンテンツを動的に生成するには、このように生のDOMをそのまま操作してもよいが、実際にそうしようとすると、その処理は煩雑なものになる(上で見たように、要素とそこに表示するテキストを追加するだけでも面倒だ)。そこで登場したのが、jQueryをはじめとした、DOM操作を簡単にしてくれるライブラリだ。さらに最近では、ReactVue.jsなど、「Virtual DOM」と呼ばれる機構を採用したフレームワークも広く使われるようになってきている。DOMの操作は負荷が比較的高い操作であることから、DOMを操作するたびにそれをWebブラウザへと反映するのではなく、通常は仮想的なDOMを操作しておいて、必要なタイミングでのみWebブラウザに反映するようにすることで、より応答性の高いWebアプリを作成しようというのが、仮想DOMフレームワークを普及させる原動力となっている。

 なお、本稿冒頭でも述べたが、DOMそのものはHTMLドキュメントやXMLドキュメントをドキュメントツリーの形で扱うためのものであり、HTMLドキュメントに対応するDOMの仕様はコアとなる部分とは別に定義されている。例えば、古いDOM Level 1では「Chapter 1: Document Object Model (Core) Level 1」でコア部分が、「Chapter 2: Document Object Model (HTML) Level 1」でHTMLに関連する部分が定められている。WHATWGでは「DOM Living Standard」と「HTML Living Standard」が相互に参照し合う形でHTMLのDOMに関する仕様が定まっているといえる。Living Standardが提供している一次情報に当たって、詳しく調べようというときには、両者を参照することになるだろう。


 DOMはHTMLドキュメント/XMLドキュメントを、ツリー状のデータ構造として取り扱い、これを参照したり、操作したりするためのデータ構造やインタフェースを定義している。プラットフォーム(例:Webブラウザ)やプログラミング言語とは独立した仕様とすることで、多くのプログラム/プログラミング言語がHTMLドキュメントやXMLドキュメントを透過的に扱うことができるようになっている。

参考資料


「Dev Basics/Keyword」のインデックス

Dev Basics/Keyword

Copyright© 1999-2018 Digital Advantage Corp. All Rights Reserved.

RSSについて

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

メールマガジン登録

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