標準情報(TR)    TR X 0083:2003


文書オブジェクトモデル(DOM)水準2 たどり及び範囲の規定

Document Object Model (DOM) Level 2 Traversal and Range Specification



序文

この標準情報(TR)は,2000年11月にWorld Wide Web Consortium(W3C)から公表された Document Object Model (DOM) Level 2 Traversal and Range Specification, version 1.0 勧告を翻訳し,技術的内容を変更することなく作成した標準情報(TR)である。


0. 適用範囲

この標準情報(TR)は,文書オブジェクトモデル水準2 たどり及び範囲を定義する。これは,プラットフォーム中立で言語中立なインタフェースであって,これを使用することによって,プログラム及びスクリプトは,動的なたどり,及び文書の内容の範囲識別が可能となる。文書オブジェクトモデル水準2 たどり及び範囲は,文書オブジェクトモデル水準2 コア規定[DOM Level 2 Core]の上に構築される。

DOM水準2 たどり及び範囲の規定は,二つのモジュールから構成されている。二つのモジュールには,文書構造のたどり,並びに文書の範囲の識別及び操作を特定の目的とした特殊化されたインタフェースが含まれる。

1. 文書オブジェクトモデル たどり

1.1 概要

1.1では,オプションのDOM水準2 たどり の機能を示す。TreeWalkerNodeIterator及びNodeFilterの各インタフェースは,文書の内容の使い易く,頑健であって,選択的なたどりを提供する。

1.に示されるインタフェースは,必須とはしない。DOMアプリケーションは,このモジュールが実装によってサポートされているかどかを決定するために,パラメタ値"Traversal"及び"2.0"をそれぞれ用いてDOMImplementationインタフェースのhasFeature(feature, version)メソッドを使用してもよい。このモジュールを完全にサポートするためには,実装は,DOM水準2 コア規定[DOM Level 2 Core]で定義されている"コア"機能もサポートしなければならない。DOM水準2 コア規定[DOM Level 2 Core]の適合性に関する追加情報を参照すること。

NodeIteratorsインタフェース及びTreeWalkersインタフェースは,文書部分木のノード及びそれらインタフェースが提示するノード内の位置を表現する異なる二つの方法とする。NodeIteratorは,部分木の平坦化されたビューをノードの順序付けされた列として提示する。この場合,ノードの列は,文書順に提示される。このビューは階層に関係なく提示されるので,繰返し子(iterator)には,前後に移動するメソッドは存在するが,上下に移動するメソッドは存在しない。逆に,TreeWalkerは,部分木の階層関係を維持し,この階層における誘導を可能にする。一般に,選択されたノードの周囲の文書構造を操作する作業には,TreeWalkersの方が優れており,各々の選択されたノードの内容に焦点を合わせた作業には,NodeIteratorsの方が優れている。

NodeIterators及びTreeWalkersは,各々,部分木で見出されるすべてのノードを含まなくてよい文書部分木のビューを提示する。この規定では,これを論理ビューとして参照し,文書部分木それ自体に対応する物理ビューとは区別する。繰返し子又はTreeWalkerが生成されるとき,各ノードを検査し,それが論理ビューに現れるのが望ましいかどうかを決定するNodeFilterと関連付けられてもよい。さらに,フラグを使用して,どのノード型が論理ビューに現れるのがよいかを指定してもよい。

NodeIterators及びTreeWalkersは,動的とする。すなわち,論理ビューは,基礎となる文書に行われた変更を反映するために変化する。しかし,それらのインタフェースは,その変更にどのように応答するかという点で異なる。ノードを順番に提示するNodeIteratorsは,列の内容が変わる場合,その列の中の位置に対して相対的な位置を維持しようとする。フィルタ処理された木としてノードを提示するTreeWalkersは,現ノードに対して相対的な位置を維持し,新しい文脈に移動する場合には,そのノードに添付された状態を保つ。これらの振る舞いについての詳細を,次に示す。

1.1.1 NodeIterators

NodeIteratorは,ノードのリストのメンバを順番に返すことを可能にする。現在のDOMインタフェースでは,このリストは,常に文書順で提示される部分木のノードから構成される。繰返し子(iterator)が最初に生成される場合,そのnextNode()メソッドを呼び出すことによって,部分木の論理ビューの中の最初のノードが返される。ほとんどの場合,これは,部分木のルートになる。連続して呼出しを実行すると,その各々の呼出しが,リストを通してNodeIteratorを進めていき,論理ビューの中の利用可能な次のノードを返す。それ以上ノードが見えない場合には,nextNode()nullを返す。

NodeIteratorsは,DocumentTraversalインタフェースの中で見出されるcreateNodeIteratorメソッドを使用して,生成される。NodeIteratorが生成される場合,木をたどる間,どのノード型が"可視的"か,及びどのノード型が"不可視的"かを決定するためにフラグを使用できる。これらのフラグは,OR演算子を使用して,結合できる。"不可視"ノードは,存在しなかったものとして,繰返し子によって飛ばされる。

繰返し子を生成し,各要素の名前を印刷するための関数を呼び出すコードを,次に示す。

    NodeIterator iter=
     ((DocumentTraversal)document).createNodeIterator(
          root, NodeFilter.SHOW_ELEMENT, null);

    while (Node n = iter.nextNode())
        printMe(n);
     

1.1.1.1 前後移動

NodeIteratorsは,順序付けされたリストとしてノードを提示し,このリスト内で前後に移動する。繰返し子の位置は,常に二つのノードの間,最初のノードの前,又は最後のノードの後のいずれかとする。繰返し子が最初に生成される場合,その位置は,最初の項目の前に設定される。次の表記は,繰返し子が,特定の部分木に対してアスタリスク'*'で示される位置にあることを示すリスト形式のビューとする。

 * A B C D E F G H I

nextNode()の各呼出しは,次のノードを返し,位置を先に進める。例えば,上記の位置から始めた場合,nextNode()の最初の呼出しは,"A"を返し,繰返し子を先に進める。

 [A] * B C D E F G H I

NodeIteratorの位置は,返された最後のノードに関して最もよく示すことができる。このノードを,参照ノードと呼ぶ。繰返し子が生成される場合,最初のノードが参照ノードになり,繰返し子の位置は,参照ノードの前になる。これらの表記では,角括弧を使用して参照ノードを示す。

previousNode()への呼出しは,前のノードを返し,位置を前に戻す。例えば,"A"と"B"との間にあるNodeIteratorで始める場合は,"A"を返し,次に示す位置に移動する。

 * [A] B C D E F G H I

nextNode()がリストの最後で呼び出される場合,又はpreviousNode()がリストの最初で呼び出される場合,それは,nullを返し,繰返し子の位置を変えない。NodeIteratorが最初に生成される場合,参照ノードは,最初のノードとする。

 * [A] B C D E F G H I

1.1.1.2 頑健性

NodeIteratorは,それが誘導するデータ構造が編集されている間,活性的であってもよい。そのために,繰返し子は,変更に直面しても支障なく振る舞わなければならない。基礎になっているデータ構造における追加及び削除は,NodeIteratorを無効にしない。実際,NodeIteratorは,そのdetach()メソッドが起動される場合でなくとも,無効にされることはない。これを可能にするために,繰返し子は,その位置を維持するために参照ノードを使用する。繰返し子の状態は,繰返し子が参照ノードの前又は後に配置されるかにも依存する。

繰返しリストへの変更が参照ノードを削除しない場合,それらの変更は,NodeIteratorの状態に影響を与えない。例えば,繰返し子の状態は,繰返し子の近くに新しいノードを挿入する,又は参照ノード以外のノードを削除することによって,影響されない。次の位置から開始する場合を仮定する。

A B C [D] * E F G H I

ここで"E"を削除してみる。その結果として得られる状態は,次になる。

A B C [D] * F G H I

新しいノードを挿入した場合,NodeIteratorは,参照ノードの近くに留まる。そのために,ノードが"D"と"F"との間に挿入される場合,そのノードは,繰返し子と"F"との間に出現することになる。

A B C [D] * X F G H I

ノードの移動は,削除及びそれに続く挿入に等価とする。"I"を"X"の前の位置に移動する場合,その結果は,次になる。

A B C [D] * I X F G H

参照ノードをその上で繰返しが行われているリストから削除する場合,異なるノードが,参照ノードとして選択される。参照ノードの位置がNodeIteratorの位置より前にある場合,これは,通常,nextNode()が呼び出された後の場合だが,繰返し子より前にある最も近いノードが,新しい参照ノードとして選択される。次の状態から開始して,"D"ノードを削除する場合を考察する。

A B C [D] * F G H I

"C"ノードが新たに参照ノードとなる。これは,"C"ノードが,繰返し子より前にあるNodeIteratorに最も近いノードであることによる。

A B [C] * F G H I

参照ノードがNodeIteratorより後にある場合,これは,通常,previousNode()が呼び出された後の場合だが,繰返し子より後にある最も近いノードが,新しい参照ノードとして選択される。次の状態から開始して,"E"を削除する場合を考察する。

A B C D * [E] F G H I

"F"ノードが新しい参照ノードとなる。これは,"F"ノードが,繰返し子の後にあるNodeIteratorに最も近いノードであることによる。

A B C D * [F] G H I

先に示したとおり,ノードの移動は,削除及びそれに続く挿入に等価とする。次の状態から開始して,"D"ノードをリストの最後まで移動したい場合を考察する。

A B C [D] * F G H I C

結果の状態は,次のとおりになる。

A B [C] * F G H I D

参照ノードがリストの中の最後のノードであって,その参照ノードが取り除かれる場合は,特殊な場合になる。次の状態から開始して,"C"ノードを取り除く場合を考察する。

A B * [C]

既に与えた規則に従うと,新しい参照ノードは,NodeIteratorより後にある最も近いノードになることが望ましいが,"C"の後にはもはやノードが存在しない。previousNode()がリストの中の最初のノードを返し,それが取り除かれた場合にも同じ状況が生じる。そのために,参照ノードの元の(進む)方向にノードが存在しない場合には,反対方向の最も近いノードを参照ノードとして選択する。

A [B] *

NodeIteratorが,取り除かれるノードのブロック内に配置されている場合,これらの規則は,行うことが望ましい処理を明確に示している。例えば,"C"が,"D","E"及び"F"のノードであって,次の状態から開始して,"C"を取り除く場合を考察する。

A B C [D] * E F G H I D

結果の状態は,次のとおりになる。

A [B] * G H I D

最後に, NodeIteratorrootノードをそのから取り除くことは,その上で繰返しが行われるリストを変更せず,繰返し子の状態を変えないという点に注意すること。

1.1.1.3 ノードの可視性

繰返しが行われている基礎となるデータ構造は,論理ビューの一部ではなく,したがって,NodeIteratorによって返されることはないノードを含んでもよい。whatToShowフラグの値のために排除されるのが望ましいノードの場合には,nextNode()は,次の可視ノードを返し,排除される"不可視"ノードは飛ばす。NodeFilterが存在する場合は,ノードを返す前にそれが適用される。フィルタがそのノードを受諾しない場合は,ノードがフィルタによって受諾されて返されるまで処理が繰り返される。可視ノードに出会わない場合には,nullが返され,繰返し子はリストの最後に配置される。この場合,参照ノードは,それが可視かどうかにかかわらず,リストの最後のノードとなる。previousNode()については,反対方向で,同じ手法が行われる。

次の例では,小文字を使用して,データ構造の中にあるが論理ビューの中にはないノードを表現する。例えば,次のリストを考察する。

A [B] * c d E F G

nextNode()の呼出しは,Eを返し,次の位置まで進める。

A B c d [E] * F G

参照ノードが取り除かれる場合,可視でないノードであっても,参照ノードとして使用されることがある。この例の状態から開始して,"E"ノードが削除される場合を考察する。結果の状態は,次になる。

A B c [d] * F G

可視である新しい"X"ノードを"d"の前に挿入する場合を考察する。結果の状態は,次になる。

A B c X [d] * F G

この場合,previousNode()の呼出しがノードXを返すことに注意すること。参照ノードを取り除く場合に,不可視ノードを飛ばさないことを重要とする。これは,ちょうどこの例のように,誤った結果を返すことがあることによる。"E"が取り除かれる場合であって,新しい参照ノードが"d"ではなく"B"であった場合,previousNode()の呼出しは,"X"を返すことはない。

1.1.2 NodeFilters

NodeFiltersを使用することによって,利用者は,ノードを"ろ過する"オブジェクトを生成することができる。各フィルタは,ノードを見て,文書のたどりの論理ビューの一部として提示されるのがよいかどうかを決定する利用者記述の関数を含む。NodeFilterを使用するためには,フィルタを使用するNodeIterator又はTreeWalkerを生成する。たどりのエンジンは,フィルタを各ノードに適用し,フィルタがノードを受諾しない場合,たどりは,文書の中にそのノードが存在しなかったものとして,それを飛ばす。NodeFiltersは,それが処理するノードを含む構造を誘導する方法を知る必要はない。

たどり操作が実行される場合,又はNodeIteratorの参照ノードが繰返しを行っている部分木から取り除かれ,NodeIteratorが新しい参照ノードを選択しなければならない場合,フィルタを使用することになる。しかし,これらのフィルタを呼び出す正確なタイミングは,DOM実装ごとに異なっていてもよい。そのために,NodeFiltersは,過去の呼出しの履歴に基づいた状態を維持しようとしないのが望ましい。結果としての振る舞いは,可搬的でないこともある。

同様に,TreeWalkers及びNodeIteratorsは,過去のフィルタ処理の結果の記憶をもたず,将来の結果の予測もしないものとして振る舞うことが望ましい。NodeFilterが検査している条件が,たどり論理がノードを最後に検査した時から変更された場合,例えば,試験する属性が追加された又は削除された場合は,この可視性における変化は,次のたどり操作が実行される場合だけに,発見されることになる。例えば,現ノードのためのフィルタ処理がFILTER_SHOWからFILTER_SKIPへと変わる場合,TreeWalkerは,あらゆる方向でのそのノードの誘導を遮断できるが,フィルタ処理の条件が再度変わらない場合には,それに戻すことはできない。たどりの最中に変化するNodeFiltersを書くことは可能だが,その振る舞いは混乱することもあり,可能な場合には,回避することが望ましい。

1.1.2.1 NodeFiltersの使用

NodeFilterは,acceptNode()という名前の一つのメソッドを含む。このメソッドの使用によって,NodeIterator又はTreeWalkerは,Nodeをフィルタに渡し,それが論理ビューの中に存在するのがよいかどうかを尋ねることができる。acceptNode()関数は,三つの値のうちの一つを返し,Nodeをどのように扱うのがよいかを示す。acceptNode()FILTER_ACCEPTを返す場合, Nodeは,論理ビューの中に存在する。FILTER_SKIPを返す場合は, Nodeは,論理ビューの中に存在しないが,Nodeの子は論理ビューの中に存在してもよい。FILTER_REJECTを返す場合は, Nodeもその子孫も論理ビューの中には存在しない。繰返し子は階層なしの順序付きリストとしてノードを提示するので,FILTER_REJECT及びFILTER_SKIPは,NodeIteratorsの同義語となり,単一の現ノードだけを飛ばす。

HTML文書の中の名前付きアンカを受諾するフィルタを考察する。HTMLでは,HREFは,NAME属性をもつあらゆるA要素を参照できる。ノードを見て,それが名前付きアンカかどうかを決定するJavaのNodeFilterを,次に示す。

    class NamedAnchorFilter implements NodeFilter
    {
     short acceptNode(Node n) {
      if (n.getNodeType()==Node.ELEMENT_NODE) {
       Element e = (Element)n;
       if (! e.getNodeName().equals("A"))
        return FILTER_SKIP;
      if (e.getAttributeNode("NAME") != null)
        return FILTER_ACCEPT;
       }
        return FILTER_SKIP;
      }
    }

ここに示したNodeFilterNodeIteratorsを用いるときだけしか使用されていない場合には,FILTER_SKIPがどこで使用されていようとも,FILTER_REJECTを使用でき,その振る舞いは変わらない。しかし,TreeWalkerについては,FILTER_REJECTは,名前付きアンカではないあらゆる要素の子どもを拒否し,さらに,名前付きアンカが常に他の要素内に含まれるので,これは,名前付きアンカが見つからないことを意味する。FILTER_SKIPは,与えられたノードを拒否するが,子どもの検査は続行する。そのために,ここに示したフィルタは,NodeIterator又はTreeWalkerのいずれかを用いて動作することになる。

このフィルタを使用するためには,利用者は,NodeFilterのインスタンスを生成し,それを使用してNodeIteratorを生成する。

NamedAnchorFilter myFilter = new NamedAnchorFilter(); 
NodeIterator iter=
     ((DocumentTraversal)document).createNodeIterator(
          node, NodeFilter.SHOW_ELEMENT, myFilter);
   

例示したNodeFilterは,nodeTypeを試験するので,この例では,SHOW_ELEMENTフラグの使用は厳密には必要ない点に注意すること。しかし,Traversalインタフェースの実装の中には,文書構造の知識を利用することによって,whatToShowの性能を改善することができ,SHOW_ELEMENTの利用を価値あるものにするものもある。逆に,フィルタからnodeType試験を取り除くことは可能だが,それは,ElementsAttr及びProcessingInstructionsの間の区別をwhatToShowに依存させることになる。

1.1.2.2 NodeFilters及び例外

NodeFilterを記述する場合,利用者は,例外を投げることのできるコードの記述を避けることが望ましい。しかし,DOM実装は例外が投げられることを禁止できないので,例外を投げるフィルタの振る舞いは,明確に定義されていることが重要になる。TreeWalker又はNodeIteratorは,フィルタが投げる例外を捕捉したり変更したりしないが,それを利用者のコードまで伝播させる。次の関数は,NodeFilterを呼び出し,そのために,例外がフィルタによって投げられる場合には,その例外を伝播する。

a) NodeIterator .nextNode()
b) NodeIterator .previousNode()
c) TreeWalker .firstChild()
d) TreeWalker .lastChild()
e) TreeWalker .nextSibling()
f) TreeWalker .previousSibling()
g) TreeWalker .nextNode()
h) TreeWalker .previousNode()
i) TreeWalker .parentNode()

1.1.2.3 NodeFilters及び文書変異

明確に設計されたNodeFiltersは,文書の基礎となる構造を変更する必要がないことが望ましい。しかし,DOM実装は,利用者が文書構造を変えるフィルタコードを記述することを禁止できない。たどり(の規定)は,この場合を取り扱うための特殊な処理を提供しない。例えば,NodeFilterが文書からノードを取り除く場合,それはまだそのノードを受諾できる。このことは,もはや部分木でたどりが実行されない場合でも,NodeIterator又はTreeWalkerがノードを返してもよいことを意味する。一般的には,これは,矛盾し混乱した結果を導き出す可能性がある。そのために,利用者には文書構造を変えないNodeFiltersを書くことを推奨する。その代わりに,たどりオブジェクトによって制御されるループの中で編集を行うこと。

1.1.2.4 NodeFilters及びwhatToShowフラグ

NodeIterator及びTreeWalkerは,それらのwhatToShowフラグをフィルタを適用する前に適用する。活性状態のwhatToShowフラグによってノードが飛ばされる場合,NodeFilterは,そのノードを評価するためには呼び出されない。この振る舞いは,FILTER_SKIPの振る舞いに類似していることに注意すること。ノードの子どもを考慮し,それらを評価するためにフィルタを呼び出してもよい。NodeFilterが部分木全体を拒否するほうがよい場合でも,それは実際には"飛ばし"となることにも注意すること。これがアプリケーションで問題を引き起こす場合には,whatToShowSHOW_ALLに設定し,フィルタ内部でnodeType試験を実行することを考慮すること。

1.1.3 TreeWalker

TreeWalkerインタフェースは,NodeIteratorインタフェースと同じ利点を数多く提供する。これら二つのインタフェースの間の主たる相違は,TreeWalkerが,部分木の中のノードを,繰返し子のリスト指向のビューではなく,木指向のビューとして提示することである。言い換えれば,繰返し子は,前後への移動を可能にするが,TreeWalkerは,ノードの,その子どもの一つ,又は兄弟へと移動することを可能にする。

TreeWalkerの使用は,Nodeを直接に使用する誘導に極めて類似しており,二つのインタフェースの誘導メソッドは類似している。例えば,次に,文書順にノードの木を再帰的に散策し,最初にノードに入るとき及びすべての子どもを処理した後で別々の動作をする関数を示す。

processMe(Node n) {
   nodeStartActions(n);
   for (Node child=n.firstChild(); 
        child != null;
        child=child.nextSibling()) {
      processMe(child);
   }
   nodeEndActions(n);
}

TreeWalkerを使用して同様のことを実行することは,極めて類似している。ただし,一つの相違点がある。TreeWalker上の誘導は現在位置を変更するので,関数の最後で位置が変更される。currentNodeという名前の読み書き属性によって,TreeWalkerに対する現ノードの照会及び設定の両方が可能になる。これを使用して,この関数を完了するときに,TreeWalkerの位置の復元を確実に行える。

processMe(TreeWalker tw) {
   Node n = tw.getCurrentNode();
   nodeStartActions(tw);
   for (Node child=tw.firstChild(); 
        child!=null;
        child=tw.nextSibling()) {
      processMe(tw);
   }

   tw.setCurrentNode(n);
   nodeEndActions(tw);
}

直接的なNode誘導の代わりに,TreeWalkerを使用する利点は,TreeWalkerによって,利用者が木の適切なビューを選択できることにある。Comments又はProcessingInstructionsを見せる又は隠すために,フラグを使用してもよい。実体をEntityReferenceノードとして拡張したり見せたりしてもよい。さらに, 木のカスタムビューを提示するためにNodeFiltersを使用してもよい。あるプログラムが,各章にどの表が出現するかを章ごとに一覧にして示す文書のビューを必要としているものとする。このビューでは,章要素及びそれらが含む表だけが見える。適切なフィルタを書くことが,最初の段階となる。

class TablesInChapters implements NodeFilter {

   short acceptNode(Node n) {
      if (n.getNodeType()==Node.ELEMENT_NODE) {
    
          if (n.getNodeName().equals("CHAPTER"))
             return FILTER_ACCEPT;

          if (n.getNodeName().equals("TABLE"))
             return FILTER_ACCEPT;

          if (n.getNodeName().equals("SECT1")
              || n.getNodeName().equals("SECT2")
              || n.getNodeName().equals("SECT3")
              || n.getNodeName().equals("SECT4")
              || n.getNodeName().equals("SECT5")
              || n.getNodeName().equals("SECT6")
              || n.getNodeName().equals("SECT7"))
             return FILTER_SKIP;

      }

      return FILTER_REJECT;
    }
}

このフィルタは,TABLE要素がCHAPTER要素又はSECTn要素の中に直接に含まれることを仮定している。他の種類の要素に出会った場合,その要素及びその要素の子どもは,拒否される。SECTn要素に出会った場合には,飛ばされるが,その子どもを探索し,TABLE要素を含んでいるかどうかを確かめる。

これで,プログラムがこのNodeFilterのインスタンスを生成し,さらにそれを使用するTreeWalker生成し,このTreeWalkerをProcessMe()関数に渡すことが可能となる。

TablesInChapters tablesInChapters  = new TablesInChapters();
TreeWalker tw  = 
     ((DocumentTraversal)document).createTreeWalker(
          root, NodeFilter.SHOW_ELEMENT, tablesInChapters);
processMe(tw);

ここでは,再び,フィルタ論理でのnodeTypeの試験及びSHOW_ELEMENTの使用の両方を行うことを選択した。これは,先のNodeIteratorの例で議論された理由による。

前述のProcessMe()関数に何も変更を行わず,CHAPTER要素及びTABLE要素だけを処理することを考える。プログラマは,他のフィルタを書くか,又は他のフラグを設定して,ノードの異なる集合を選択することができる。すなわち,関数は,誘導のためにTreeWalkerを使用する場合,TreeWalkerを用いて定義された文書のあらゆるビューをサポートすることになる。

TreeWalkerのフィルタ処理された文書のビューの構造は,文書それ自体の構造とは著しく異なってもよいことに注意すること。例えば,whatToShowパラメタでSHOW_TEXTだけが指定されたTreeWalkerは,すべてのTextノードを,をもたないのだがそれらが互いの兄弟であるものとして提示する。

1.1.3.1 頑健性

NodeIteratorsと同様に, TreeWalkerは,それが誘導するデータ構造が編集されている間,活性状態であってもよく,変更に直面しても支障なく振る舞わなければならない。基礎となるデータ構造の追加及び削除は,TreeWalkerを無効にしない。実際,TreeWalkerは,決して無効にされることはない。

しかし,これらの変更に対するTreeWalkerの応答は,NodeIteratorの応答とは全く異なる。NodeIteratorsは,その上で繰返しを実行するリスト内での位置を維持することによって,編集に応答するが,TreeWalkersは,その代わりに,そのcurrentNodeに添付された状態を維持する。TreeWalkerのすべての誘導メソッドは,TreeWalkerが最後にアクセスされてから,そのノード又はそのノードの周囲に何が起ころうと,それら誘導メソッドが呼び出された時のcurrentNodeの文脈に基づいて動作する。currentNodeが元の部分木の外部に移動されたとしても,これは,正しい。

例として,次の文書素片を考察する。

    ...
    <subtree>
        <twRoot>
            <currentNode/>
            <anotherNode/>
        </twRoot>
    </subtree>
    ...
 

ここで,rootノードが<twRoot/>要素であって,currentNodeが<currentNode/>要素であるTreeWalkerを生成したとする。この例では,示されたすべてのノードが,TreeWalkerwhatToShow及びフィルタ設定によって受諾されると仮定する。

removeChild()を使用してそのから<currentNode/>要素を取り除く場合,その要素は, たとえrootノードの部分木内に既に存在しなくても,TreeWalkercurrentNodeを維持する。TreeWalkerを使用して,その親をもたないcurrentNodeがもつかもしれないあらゆる子どもに沿っての誘導は可能だが,利用可能なが存在しないので,そのcurrentNodeから外部へ向かっての誘導はできない。

insertBefore()又はappendChild()を使用して,<currentNode/>に新しいを提供する場合,TreeWalkerの誘導は,currentNodeの新しい位置から操作されることになる。例えば,<currentNode/>を<anotherNode/>要素の直後に挿入する場合,TreeWalkerpreviousSibling()操作は,それ(<currentNode/>)を<anotherNode/>まで戻し,parentNode()の呼出しは,それを<twRoot/>まで移動する。

代わりに,currentNodeを<subtree/>要素に次のように挿入する場合を考察する。

    ...
    <subtree>
        <currentNode/>
        <twRoot>
            <anotherNode/>
        </twRoot>
    </subtree>
    ...

この場合は,currentNodeTreeWalkerrootノードの下から移動した。これは,TreeWalkerを無効化しない。すなわち,この場合でも,これを使用して,currentNodeに相対的な誘導を行ってもよい。例えば,parentNode()操作の呼出しは,currentNodeも元のrootノードの外部にあったとしても,それを<subtree/>要素まで移動する。しかし,TreeWalkerの誘導が元のrootノードの部分木までcurrentNodeを戻すのが望ましい場合,例えば,parentNode()を呼び出すのではなく,nextNode()を呼び出したときに,TreeWalkerを<twRoot/>要素まで移動する場合は,rootノードは,TreeWalkerを"再捕獲"し,たどりが後退しないようにする。

これは,フィルタを使用する場合は,若干複雑になる。currentNodeの再配置,すなわち,新しいcurrentNodeの明示的な選択,又はNodeFilterがその決定の基としている条件の変更が,そうでない場合には,文書のフィルタ処理された(論理)ビューの中で可視ではないcurrentNodeをもつTreeWalkerを結果として生じる。このノードをそのビューの"一時的なメンバ"として考えることができる。TreeWalkerにこのノードを誘導から外すことを要求する場合,単に,このノードが可視であったかのような結果となるが,再度可視とするように条件を変更しない場合は,誘導をこれに戻すことはできない可能性がある。

特に,currentNodeがフィルタによって拒否された部分木の一部となる場合は,その部分木全体を論理ビューの一時的なメンバとして追加してもよい。過去に拒否された先祖へと上向きに移動するまで,その部分木内を(すべての通常のフィルタ処理には従って)進むことが可能となる。その振る舞いは,(その部分木の内部を幾分曲がりくねりながら進むので,)そこを離れるまでは,拒否されたノードが単に飛ばされたかのようになる。その後,標準的なフィルタ処理が適用される。

1.2 形式的なインタフェース定義

インタフェース NodeIterator (DOM水準2で導入)

Iteratorsは,ノードの集合を通って一つずつ進むために使用される。ここで,ノードの集合とは,例えば,NodeListの中のノードの集合,特別なノードが支配する文書部分木,問合せの結果,又はノードのその他の集合をいう。NodeIteratorの実装によって,繰り返えされるノードの集合が決定される。DOM水準2は,文書部分木の文書順たどりのために,一つのNodeIteratorを規定する。これらの繰返し子のインスタンスは,DocumentTraversal.createNodeIterator()を呼び出すことによって生成される。


IDL定義
// Introduced in DOM Level 2:
interface NodeIterator {
  readonly attribute Node             root;
  readonly attribute unsigned long    whatToShow;
  readonly attribute NodeFilter       filter;
  readonly attribute boolean          expandEntityReferences;
  Node               nextNode()
                                        raises(DOMException);
  Node               previousNode()
                                        raises(DOMException);
  void               detach();
};

属性
booleanexpandEntityReferences,読取り専用
このフラグの値は,実体参照ノードの子どもが繰返し子に対して可視かどうかを決定する。falseの場合は,それら及びそれらの子孫は,拒否される。この拒否は,whatToShow及びフィルタに優先することに注意すること。これは,現時点では,NodeIteratorsが,個々のノードを飛ばすのではなくて,完全な部分木を拒否してもよい状況だけとすることにも注意すること。

実体参照を展開して,実体参照ノードそれ自体を開示しない文書のビューを生成するためには,実体参照ノードを隠蔽するようにwhatToShowフラグを使用し,繰返し子を生成するときにexpandEntityReferencesをtrueに設定すること。実体参照ノードをもつが,実体(参照)の展開をもたない文書のビューを生成するためには,実体参照ノードを見せるようにwhatToShowフラグを使用し,expandEntityReferencesをfalseに設定すること。
NodeFilterfilter,読取り専用
ノードの選別に使用するNodeFilter
Noderoot,読取り専用
NodeIteratorが生成された時に指定されたとおりの,NodeIteratorのルートノード。
unsigned longwhatToShow,読取り専用
この属性は,繰返し子を介して,どのノード型が提示されるかを決定する。利用可能な定数の集合は,NodeFilterインタフェースにおいて定義される。whatToShowが受諾しないノードは飛ばされるが,その場合でも,それらの子どもは検討されてよい。この飛ばしは,存在する場合には,フィルタに優先する点に注意すること。
メソッド
detach
NodeIteratorをその上で繰り返す集合から切り離し,あらゆる計算中の資源を解放し,繰返し子をINVALID状態にする。detachが呼び出された後,nextNode又はpreviousNodeを呼び出した場合には,例外INVALID_STATE_ERRが挙げられる。
パラメタなし
返却値なし
例外なし
nextNode
集合の中の次のノードを返し,その集合の中の繰返し子の位置を先に進める。NodeIteratorが生成された後,nextNode()の最初の呼出しは,その集合の中の最初のノードを返す。
返却値

Node

その上で繰り返される集合の中の次のNode,又はその集合の中にそれ以上のメンバが存在しない場合は,null

例外

DOMException

INVALID_STATE_ERR: detachメソッドの呼出し後にこのメソッドが呼び出された場合に,挙げられる。

パラメタなし
previousNode
集合の中の前のノードを返し,その集合の中のNodeIteratorの位置を後退させる。
返却値

Node

その上で繰り返される集合の中の前のNode,又はその集合の中にそれ以上のメンバが存在しない場合には,null

例外

DOMException

INVALID_STATE_ERR: detachメソッドの呼出し後に,このメソッドが呼び出された場合に,挙げられる。

パラメタなし

インタフェース NodeFilter (DOM水準2で導入)

フィルタは,ノードを"ろ過"する方法を知っているオブジェクトとする。NodeIterator又はTreeWalkerNodeFilterを提供される場合,次のノードを返す前にフィルタが適用される。フィルタがノードを受諾する場合,たどり論理は,そのノードを返す。そうでない場合は,たどりは次のノードを探し,拒否されたノードがそこに存在しなかったものとして振る舞う。

DOMはフィルタを提供しない。NodeFilterは,単に,利用者が彼ら自身のフィルタを提供するために実装できるインタフェースとする。

NodeFilterは,ノードからノードへのたどり方を知る必要はないし,たどられているデータ構造について何も知る必要もない。これによって,NodeFilterが知る必要があるのは,単一のノードの評価方法だけとなるので,フィルタを書くことが非常に容易になる。一つのフィルタを多くの異なる種類のたどりで使用してもよく,コードの再利用を推奨する。


IDL定義
// Introduced in DOM Level 2:
interface NodeFilter {

  // Constants returned by acceptNode
  const short               FILTER_ACCEPT                  = 1;
  const short               FILTER_REJECT                  = 2;
  const short               FILTER_SKIP                    = 3;


  // Constants for whatToShow
  const unsigned long       SHOW_ALL                       = 0xFFFFFFFF;
  const unsigned long       SHOW_ELEMENT                   = 0x00000001;
  const unsigned long       SHOW_ATTRIBUTE                 = 0x00000002;
  const unsigned long       SHOW_TEXT                      = 0x00000004;
  const unsigned long       SHOW_CDATA_SECTION             = 0x00000008;
  const unsigned long       SHOW_ENTITY_REFERENCE          = 0x00000010;
  const unsigned long       SHOW_ENTITY                    = 0x00000020;
  const unsigned long       SHOW_PROCESSING_INSTRUCTION    = 0x00000040;
  const unsigned long       SHOW_COMMENT                   = 0x00000080;
  const unsigned long       SHOW_DOCUMENT                  = 0x00000100;
  const unsigned long       SHOW_DOCUMENT_TYPE             = 0x00000200;
  const unsigned long       SHOW_DOCUMENT_FRAGMENT         = 0x00000400;
  const unsigned long       SHOW_NOTATION                  = 0x00000800;

  short              acceptNode(in Node n);
};

定義グループ acceptNodeが返す定数

次の定数が,acceptNode()メソッドによって返される。

定義済み定数
FILTER_ACCEPT
ノードを受諾する。NodeIterator又はTreeWalkerのために定義された誘導メソッドは,このノードを返す。
FILTER_REJECT
ノードを拒否する。NodeIterator又はTreeWalkerのために定義された誘導メソッドは,このノードを返さない。TreeWalkerの場合は,このノードの子どもも拒否される。NodeIteratorsは,これをFILTER_SKIPの同義語として扱う。
FILTER_SKIP
この一つのノードを飛ばす。NodeIterator又はTreeWalkerのために定義された誘導メソッドは,このノードを返さない。ただし,NodeIterator及びTreeWalkerの両方について,このノードの子どもは,検討される。
定義グループwhatToShowのための定数

これらは,TreeWalkers及びNodeIteratorsにおいて使用されるwhatToShowパラメタのための利用可能な値とする。それらは,Nodeのために可能な型の集合と同じであって,その値は,等価なノード型についてのnodeTypeの値に対応するビット位置を使用することによって,導出される。whatToShowの中のビットがfalseに設定されている場合,それは,ノードのこの型を飛ばす要求として受け取られる。その場合の振る舞いは,FILTER_SKIPの振る舞いと類似する。

32種類より多いノード型が導入された場合は,whatToShowを介して,それらを個々に検査できないかもしれない点に注意すること。その必要が生じた場合には,適切なNodeFilterと一緒にSHOW_ALLを選択することによって,それを処理できる。

定義済み定数
SHOW_ALL
すべてのNodesを見せる。
SHOW_ATTRIBUTE
Attrノードを見せる。これは,属性ノードをそのrootとしてもつ繰返し子又は木散策を生成する場合だけに,意味がある。この場合,このことは,属性ノードが繰返し又はたどりの最初の位置に現れることを意味する。属性が他のノードの子どもであることはないので,文書木の上をたどるときには,それらが現れることはない。
SHOW_CDATA_SECTION
CDATASectionノードを見せる。
SHOW_COMMENT
Commentノードを見せる。
SHOW_DOCUMENT
Documentノードを見せる。
SHOW_DOCUMENT_FRAGMENT
DocumentFragmentノードを見せる。
SHOW_DOCUMENT_TYPE
DocumentTypeノードを見せる。
SHOW_ELEMENTを見せる。
Elementノードを見せる。
SHOW_ENTITY
Entityノードを見せる。これは,Entityノードをそのrootとしてもつ繰返し子又は木散策を生成する場合だけに,意味がある。この場合,このことは,Entityノードがたどりの最初の位置に現れることを意味する。実体は文書木の一部ではないので,文書木の上をたどるときに,それらが現れることはない。
SHOW_ENTITY_REFERENCE
EntityReferenceノードを見せる。
SHOW_NOTATION
Notationノードを見せる。これは,Notationノードをそのrootとしてもつ繰返し子又は木散策を生成する場合だけに,意味がある。この場合,このことは,Notationノードがたどりの最初の位置に現れることを意味する。記法は文書木の一部ではないので,文書木の上をたどるときに,それらが現れることはない。
SHOW_PROCESSING_INSTRUCTION
ProcessingInstructionノードを見せる。
SHOW_TEXT
Textノードを見せる。
メソッド
acceptNode
指定されたノードがTreeWalker又はNodeIteratorの論理ビューで可視かどうかを試験する。この関数は,TreeWalker及びNodeIteratorの実装によって呼び出される。これは,通常,利用者コードから直接に呼び出されることはない。ただし,同じフィルタを使用して,利用者自身のアプリケーション論理を導きたい場合には,利用者コードから直接に呼び出すことは可能とする。
パラメタ
Noden
フィルタを通過するかしないかを調べるために検査を行うノード。
返却値

short

"定義グループ acceptNodeが返す定数"で定義されるとおりに,ノードが受諾されるか,拒否されるか,又は飛ばされるかを決定する定数。

例外なし

インタフェース TreeWalker (DOM水準2で導入)

TreeWalkerオブジェクトは,そのwhatToShowフラグ及び(存在する場合には)フィルタが定義する文書のビューを使用して,文書木又は部分木を誘導するために使用する。TreeWalkerを使用して誘導を実行するあらゆる関数は,自動的に,TreeWalkerが定義するあらゆるビューをサポートする。

部分木の論理ビューからのノードを省略することは,結果として,フィルタにかけていない完全な文書の同じ部分木とは実質的に異なる構造になる。TreeWalkerビューの中で兄弟であるノードが,元のビューの中では,異なる,非常に離れたノードの子であってもよい。例えば,文書のテキストノード及びルートノードを除くすべてのノードを飛ばすNodeFilterを考えてみる。その結果として得られる論理ビューの中では,すべてのテキストノードは,兄弟となり,元の文書の構造がどんなに深く入れ子になっていても,ルートノードの直接の子どもとして現れることになる。


IDL定義
// Introduced in DOM Level 2:
interface TreeWalker {
  readonly attribute Node             root;
  readonly attribute unsigned long    whatToShow;
  readonly attribute NodeFilter       filter;
  readonly attribute boolean          expandEntityReferences;
           attribute Node             currentNode;
                                        // raises(DOMException) on setting

  Node               parentNode();
  Node               firstChild();
  Node               lastChild();
  Node               previousSibling();
  Node               nextSibling();
  Node               previousNode();
  Node               nextNode();
};

属性
NodecurrentNode
TreeWalkerが現在位置しているノード。
DOM木への変更によって,現ノードを,TreeWalkerの関連するフィルタがもはや受諾しなくなることがある。currentNodeは,それがrootノードが指定する部分木内に存在するかしないか,又はフィルタ及びwhatToShowフラグによって受諾されるかどうかに関わらず,すべてのノードに対して明示的に設定されてもよい。currentNodeが,要求された方向でフィルタが適用されることによって,現在ビューの一部ではない場合であっても,更なるたどりが,currentNodeに相対的に発生する。たどりが可能ではない場合,currentNodeは,変更されない。
設定に関する例外

DOMException

NOT_SUPPORTED_ERR: currentNodenullに設定しようと試みた場合に,挙げられる。

booleanexpandEntityReferences,読取り専用
このフラグの値は,実体参照ノードの子どもがTreeWalkerに対して可視かどうかを決定する。falseの場合は,それら及びそれらの子孫は,拒否される。この拒否は,whatToShow及び(存在する場合には)フィルタに優先する点に注意すること。
実体参照が展開され,実体参照ノードそれ自体を開示しない文書のビューを生成するためには,実体参照ノードを隠蔽するようにwhatToShowフラグを使用し,TreeWalkerの生成するときにexpandEntityReferencesをtrueに設定すること。実体参照ノードをもつが,実体展開をもたない文書のビューを生成するためには,実体参照ノードを見せるようにwhatToShowフラグを使用し,expandEntityReferencesをfalseに設定すること。
NodeFilterfilter,読取り専用
ノードの選別に使用されるフィルタ。
Noderoot,読取り専用
生成時に指定されるとおりの,TreeWalkerrootノード。
unsigned longwhatToShow,読取り専用
この属性は,どのノード型がTreeWalkerを介して提示されるかを決定する。利用可能な定数の集合は,NodeFilterインタフェースの中で定義される。whatToShowが受諾しないノードは飛ばされるが,その場合でも,それらの子どもは検討される。この飛ばしは,(存在する場合には)フィルタに優先する点に注意すること。
メソッド
firstChild
TreeWalkerを現ノードの最初の可視のまで移動し,その新しいノードを返す。現ノードに可視の子どもがない場合は,nullを返し,現ノードを保持する。
返却値

Node

新しいノード,又は現ノードがTreeWalkerの論理ビューの中で可視の子どもをもたない場合は,null

パラメタなし
例外なし
lastChild
TreeWalkerを現ノードの最後の可視のまで移動し,その新しいノードを返す。現ノードに可視の子どもがない場合は,nullを返し,現ノードを保持する。
返却値

Node

新しいノード,又は現ノードがTreeWalkerの論理ビューの中で子どもをもたない場合は,null

パラメタなし
例外なし
nextNode
TreeWalkerを,現ノードに相対的な文書順で次の可視のノードまで移動し,その新しいノードを返す。現ノードに次のノードがない場合,又はnextNodeの検索がTreeWalkerrootノードから上に移動しようとした場合は,nullを返し,現ノードを保持する。
返却値

Node

新しいノード,又は現ノードがTreeWalkerの論理ビューの中で次のノードをもたない場合は,null

パラメタなし
例外なし
nextSibling
TreeWalkerを現ノードの次の兄弟まで移動し,その新しいノードを返す。現ノードに可視の次の兄弟がない場合は,nullを返し,現ノードを保持する。
返却値

Node

新しいノード,又は現ノードがTreeWalkerの論理ビューの中で次の兄弟をもたない場合は,null

パラメタなし
例外なし
parentNode
現ノードの最も近い可視の先祖ノードまで移動し,それを返す。parentNodeの検索がTreeWalkerrootノードから上に移動しようとした場合,又は可視の先祖ノードの発見に失敗した場合は,このメソッドは,現在の位置を保持し,nullを返す。
返却値

Node

新しいノード,又は現ノードがTreeWalkerの論理ビューの中で親をもたない場合は,null

パラメタなし
例外なし
previousNode
TreeWalkerを,現ノードに相対的な文書順で前の可視のノードに移動し,その新しいノードを返す。現ノードに前のノードがない場合,又はpreviousNodeの検索がTreeWalkerrootノードから上に移動しようとした場合は,nullを返し,現ノードを保持する。
返却値

Node

新しいノード,又は現ノードがTreeWalkerの論理ビューの中で前のノードをもたない場合は,null

パラメタなし
例外なし
previousSibling
TreeWalkerを現ノードの前の兄弟まで移動し,その新しいノードを返す。現ノードに可視の前の兄弟がいない場合は,nullを返し,現ノードを保持する。
返却値

Node

新しいノード,又は現ノードがTreeWalkerの論理ビューの中で前の兄弟をもたない場合は,null

パラメタなし
例外なし

インタフェース DocumentTraversal (DOM水準2で導入)

DocumentTraversalは,繰返し子,並びにノード及びその子どもを文書順でたどる木散策を生成するメソッドを含む。ここでいう文書順とは,深さの方向を最初にする前順たどりであって,文書のテキスト表現で開始タグが現れる順番と等価になっている。Traversal(たどり)機能をサポートするDOMでは,DocumentTraversalは,Documentインタフェースを実装する同じオブジェクトによって,実装される。


IDL定義
// Introduced in DOM Level 2:
interface DocumentTraversal {
  NodeIterator       createNodeIterator(in Node root, 
                                        in unsigned long whatToShow, 
                                        in NodeFilter filter, 
                                        in boolean entityReferenceExpansion)
                                        raises(DOMException);
  TreeWalker         createTreeWalker(in Node root, 
                                      in unsigned long whatToShow, 
                                      in NodeFilter filter, 
                                      in boolean entityReferenceExpansion)
                                        raises(DOMException);
};

メソッド
createNodeIterator
指定されたノードをルートとする部分木の上に,新しいNodeIteratorを生成する。
パラメタ
Noderoot
その子どもと一緒に繰り返されるノード。繰返し子は,最初に,このノードの直前に配置される。この位置設定のとき,whatToShowフラグ及び(存在する場合には)フィルタは考慮されない。ルートは,nullであってはならない。
unsigned longwhatToShow
このフラグは,繰返し子が提示する木の論理ビューの中にどのノード型が現れてよいかを指定する。可能なSHOW_値の集合については,NodeFilterの記述を参照すること。
ORを使用して,これらのフラグを組み合わせることができる。
NodeFilterfilter
このTreeWalkerと一緒に使用されるNodeFilter,又はフィルタが存在しないことを示すnull
booleanentityReferenceExpansion
このフラグの値は,実体参照ノードが展開されるかどうかを決定する。
返却値

NodeIterator

新しく生成されたNodeIterator

例外

DOMException

NOT_SUPPORTED_ERR: 指定されたrootnullの場合に,挙げられる。

createTreeWalker
指定されたノードをルートとする部分木の上に,新しいTreeWalkerを生成する。
パラメタ
Noderoot
TreeWalkerに対してrootとして振る舞うノード。whatToShowフラグ及びNodeFilterは,この値の設定時には考慮されない。すなわち,あらゆるノード型が,rootとして受諾される。TreeWalkercurrentNodeは,可視かどうかに関係なく,このノードに対して初期化される。rootは,parentNode及びnextNodeといった文書構造の中を上方向に検索するたどりメソッドのための停止位置として機能する。rootは,nullであってはならない。
unsigned longwhatToShow
このフラグは,木散策が提示する木の論理ビューの中にどのノード型が現れてよいかを指定する。可能なSHOW_値の集合については,NodeFilterの記述を参照すること。
ORを使用して,これらのフラグを組み合わせることができる。
NodeFilterfilter
このTreeWalkerと一緒に使用されるNodeFilter,又はフィルタが存在しないことを示すnull
booleanentityReferenceExpansion
このフラグがfalseの場合,EntityReferenceノードの内容は,論理ビューの中で提示されない。
返却値

TreeWalker

新しく生成されたTreeWalker

例外

DOMException

NOT_SUPPORTED_ERR: 指定されたrootnullの場合に,挙げられる。