この標準情報(TR)は,2000年11月にWorld Wide Web Consortium(W3C)から公表された Document Object Model (DOM) Level 2 Traversal and Range Specification, version 1.0 勧告を翻訳し,技術的内容を変更することなく作成した標準情報(TR)である。
この標準情報(TR)は,文書オブジェクトモデル水準2 たどり及び範囲を定義する。これは,プラットフォーム中立で言語中立なインタフェースであって,これを使用することによって,プログラム及びスクリプトは,動的なたどり,及び文書の内容の範囲識別が可能となる。文書オブジェクトモデル水準2 たどり及び範囲は,文書オブジェクトモデル水準2 コア規定[DOM Level 2 Core]の上に構築される。
DOM水準2 たどり及び範囲の規定は,二つのモジュールから構成されている。二つのモジュールには,文書構造のたどり,並びに文書の範囲の識別及び操作を特定の目的とした特殊化されたインタフェースが含まれる。
1.1では,オプションのDOM水準2 たどり の機能を示す。TreeWalker
,NodeIterator
及び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
は,現ノードに対して相対的な位置を維持し,新しい文脈に移動する場合には,そのノードに添付された状態を保つ。これらの振る舞いについての詳細を,次に示す。
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);
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
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
最後に, NodeIterator
のroot
ノードをその親から取り除くことは,その上で繰返しが行われるリストを変更せず,繰返し子の状態を変えないという点に注意すること。
繰返しが行われている基礎となるデータ構造は,論理ビューの一部ではなく,したがって,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"を返すことはない。
NodeFilters
NodeFilters
を使用することによって,利用者は,ノードを"ろ過する"オブジェクトを生成することができる。各フィルタは,ノードを見て,文書のたどりの論理ビューの一部として提示されるのがよいかどうかを決定する利用者記述の関数を含む。NodeFilter
を使用するためには,フィルタを使用するNodeIterator
又はTreeWalker
を生成する。たどりのエンジンは,フィルタを各ノードに適用し,フィルタがノードを受諾しない場合,たどりは,文書の中にそのノードが存在しなかったものとして,それを飛ばす。NodeFilters
は,それが処理するノードを含む構造を誘導する方法を知る必要はない。
たどり操作が実行される場合,又はNodeIterator
の参照ノードが繰返しを行っている部分木から取り除かれ,NodeIterator
が新しい参照ノードを選択しなければならない場合,フィルタを使用することになる。しかし,これらのフィルタを呼び出す正確なタイミングは,DOM実装ごとに異なっていてもよい。そのために,NodeFilters
は,過去の呼出しの履歴に基づいた状態を維持しようとしないのが望ましい。結果としての振る舞いは,可搬的でないこともある。
同様に,TreeWalkers
及びNodeIterators
は,過去のフィルタ処理の結果の記憶をもたず,将来の結果の予測もしないものとして振る舞うことが望ましい。NodeFilter
が検査している条件が,たどり論理がノードを最後に検査した時から変更された場合,例えば,試験する属性が追加された又は削除された場合は,この可視性における変化は,次のたどり操作が実行される場合だけに,発見されることになる。例えば,現ノードのためのフィルタ処理がFILTER_SHOW
からFILTER_SKIP
へと変わる場合,TreeWalker
は,あらゆる方向でのそのノードの誘導を遮断できるが,フィルタ処理の条件が再度変わらない場合には,それに戻すことはできない。たどりの最中に変化するNodeFilters
を書くことは可能だが,その振る舞いは混乱することもあり,可能な場合には,回避することが望ましい。
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; } }
ここに示したNodeFilter
がNodeIterators
を用いるときだけしか使用されていない場合には,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
試験を取り除くことは可能だが,それは,Elements
,Attr
及びProcessingInstructions
の間の区別をwhatToShow
に依存させることになる。
NodeFilters
及び例外NodeFilter
を記述する場合,利用者は,例外を投げることのできるコードの記述を避けることが望ましい。しかし,DOM実装は例外が投げられることを禁止できないので,例外を投げるフィルタの振る舞いは,明確に定義されていることが重要になる。TreeWalker
又はNodeIterator
は,フィルタが投げる例外を捕捉したり変更したりしないが,それを利用者のコードまで伝播させる。次の関数は,NodeFilter
を呼び出し,そのために,例外がフィルタによって投げられる場合には,その例外を伝播する。
NodeIterator
.nextNode()
NodeIterator
.previousNode()
TreeWalker
.firstChild()
TreeWalker
.lastChild()
TreeWalker
.nextSibling()
TreeWalker
.previousSibling()
TreeWalker
.nextNode()
TreeWalker
.previousNode()
TreeWalker
.parentNode()
NodeFilters
及び文書変異明確に設計されたNodeFilters
は,文書の基礎となる構造を変更する必要がないことが望ましい。しかし,DOM実装は,利用者が文書構造を変えるフィルタコードを記述することを禁止できない。たどり(の規定)は,この場合を取り扱うための特殊な処理を提供しない。例えば,NodeFilter
が文書からノードを取り除く場合,それはまだそのノードを受諾できる。このことは,もはや部分木でたどりが実行されない場合でも,NodeIterator
又はTreeWalker
がノードを返してもよいことを意味する。一般的には,これは,矛盾し混乱した結果を導き出す可能性がある。そのために,利用者には文書構造を変えないNodeFilters
を書くことを推奨する。その代わりに,たどりオブジェクトによって制御されるループの中で編集を行うこと。
NodeFilters
及びwhatToShow
フラグNodeIterator
及びTreeWalker
は,それらのwhatToShow
フラグをフィルタを適用する前に適用する。活性状態のwhatToShow
フラグによってノードが飛ばされる場合,NodeFilter
は,そのノードを評価するためには呼び出されない。この振る舞いは,FILTER_SKIP
の振る舞いに類似していることに注意すること。ノードの子どもを考慮し,それらを評価するためにフィルタを呼び出してもよい。NodeFilter
が部分木全体を拒否するほうがよい場合でも,それは実際には"飛ばし"となることにも注意すること。これがアプリケーションで問題を引き起こす場合には,whatToShow
をSHOW_ALL
に設定し,フィルタ内部でnodeType
試験を実行することを考慮すること。
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
ノードを,親をもたないのだがそれらが互いの兄弟であるものとして提示する。
NodeIterators
と同様に, TreeWalker
は,それが誘導するデータ構造が編集されている間,活性状態であってもよく,変更に直面しても支障なく振る舞わなければならない。基礎となるデータ構造の追加及び削除は,TreeWalker
を無効にしない。実際,TreeWalker
は,決して無効にされることはない。
しかし,これらの変更に対するTreeWalker
の応答は,NodeIterator
の応答とは全く異なる。NodeIterators
は,その上で繰返しを実行するリスト内での位置を維持することによって,編集に応答するが,TreeWalkers
は,その代わりに,そのcurrentNode
に添付された状態を維持する。TreeWalker
のすべての誘導メソッドは,TreeWalker
が最後にアクセスされてから,そのノード又はそのノードの周囲に何が起ころうと,それら誘導メソッドが呼び出された時のcurrentNode
の文脈に基づいて動作する。currentNode
が元の部分木の外部に移動されたとしても,これは,正しい。
例として,次の文書素片を考察する。
... <subtree> <twRoot> <currentNode/> <anotherNode/> </twRoot> </subtree> ...
ここで,root
ノードが<twRoot/>要素であって,currentNode
が<currentNode/>要素であるTreeWalker
を生成したとする。この例では,示されたすべてのノードが,TreeWalker
のwhatToShow
及びフィルタ設定によって受諾されると仮定する。
removeChild()
を使用してその親から<currentNode/>要素を取り除く場合,その要素は, たとえroot
ノードの部分木内に既に存在しなくても,TreeWalker
のcurrentNode
を維持する。TreeWalker
を使用して,その親をもたないcurrentNode
がもつかもしれないあらゆる子どもに沿っての誘導は可能だが,利用可能な親が存在しないので,そのcurrentNode
から外部へ向かっての誘導はできない。
insertBefore()
又はappendChild()
を使用して,<currentNode/>に新しい親を提供する場合,TreeWalker
の誘導は,currentNode
の新しい位置から操作されることになる。例えば,<currentNode/>を<anotherNode/>要素の直後に挿入する場合,TreeWalker
のpreviousSibling()
操作は,それ(<currentNode/>)を<anotherNode/>まで戻し,parentNode()
の呼出しは,それを<twRoot/>まで移動する。
代わりに,currentNode
を<subtree/>要素に次のように挿入する場合を考察する。
... <subtree> <currentNode/> <twRoot> <anotherNode/> </twRoot> </subtree> ...
この場合は,currentNode
をTreeWalker
のroot
ノードの下から移動した。これは,TreeWalker
を無効化しない。すなわち,この場合でも,これを使用して,currentNode
に相対的な誘導を行ってもよい。例えば,parentNode()
操作の呼出しは,currentNode
も元のroot
ノードの外部にあったとしても,それを<subtree/>要素まで移動する。しかし,TreeWalker
の誘導が元のroot
ノードの部分木までcurrentNode
を戻すのが望ましい場合,例えば,parentNode()
を呼び出すのではなく,nextNode()
を呼び出したときに,TreeWalker
を<twRoot/>要素まで移動する場合は,root
ノードは,TreeWalker
を"再捕獲"し,たどりが後退しないようにする。
これは,フィルタを使用する場合は,若干複雑になる。currentNode
の再配置,すなわち,新しいcurrentNode
の明示的な選択,又はNodeFilter
がその決定の基としている条件の変更が,そうでない場合には,文書のフィルタ処理された(論理)ビューの中で可視ではないcurrentNode
をもつTreeWalker
を結果として生じる。このノードをそのビューの"一時的なメンバ"として考えることができる。TreeWalker
にこのノードを誘導から外すことを要求する場合,単に,このノードが可視であったかのような結果となるが,再度可視とするように条件を変更しない場合は,誘導をこれに戻すことはできない可能性がある。
特に,currentNode
がフィルタによって拒否された部分木の一部となる場合は,その部分木全体を論理ビューの一時的なメンバとして追加してもよい。過去に拒否された先祖へと上向きに移動するまで,その部分木内を(すべての通常のフィルタ処理には従って)進むことが可能となる。その振る舞いは,(その部分木の内部を幾分曲がりくねりながら進むので,)そこを離れるまでは,拒否されたノードが単に飛ばされたかのようになる。その後,標準的なフィルタ処理が適用される。
Iterators
は,ノードの集合を通って一つずつ進むために使用される。ここで,ノードの集合とは,例えば,NodeList
の中のノードの集合,特別なノード
が支配する文書部分木,問合せの結果,又はノードのその他の集合をいう。NodeIterator
の実装によって,繰り返えされるノードの集合が決定される。DOM水準2は,文書部分木の文書順たどりのために,一つのNodeIterator
を規定する。これらの繰返し子のインスタンスは,DocumentTraversal
.createNodeIterator()
を呼び出すことによって生成される。
// 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(); };
boolean
のexpandEntityReferences
,読取り専用
whatToShow
及びフィルタに優先することに注意すること。これは,現時点では,NodeIterators
が,個々のノードを飛ばすのではなくて,完全な部分木を拒否してもよい状況だけとすることにも注意すること。
whatToShow
フラグを使用し,繰返し子を生成するときにexpandEntityReferences
をtrueに設定すること。実体参照ノードをもつが,実体(参照)の展開をもたない文書のビューを生成するためには,実体参照ノードを見せるようにwhatToShow
フラグを使用し,expandEntityReferences
をfalseに設定すること。NodeFilter
のfilter
,読取り専用
NodeFilter
。Node
のroot
,読取り専用
NodeIterator
が生成された時に指定されたとおりの,NodeIterator
のルートノード。unsigned long
のwhatToShow
,読取り専用
NodeFilter
インタフェースにおいて定義される。whatToShow
が受諾しないノードは飛ばされるが,その場合でも,それらの子どもは検討されてよい。この飛ばしは,存在する場合には,フィルタに優先する点に注意すること。 detach
NodeIterator
をその上で繰り返す集合から切り離し,あらゆる計算中の資源を解放し,繰返し子をINVALID状態にする。detach
が呼び出された後,nextNode
又はpreviousNode
を呼び出した場合には,例外INVALID_STATE_ERRが挙げられる。
nextNode
NodeIterator
が生成された後,nextNode()
の最初の呼出しは,その集合の中の最初のノードを返す。
|
その上で繰り返される集合の中の次の |
|
INVALID_STATE_ERR: |
previousNode
NodeIterator
の位置を後退させる。
|
その上で繰り返される集合の中の前の |
|
INVALID_STATE_ERR: |
フィルタは,ノードを"ろ過"する方法を知っているオブジェクトとする。NodeIterator
又はTreeWalker
がNodeFilter
を提供される場合,次のノードを返す前にフィルタが適用される。フィルタがノードを受諾する場合,たどり論理は,そのノードを返す。そうでない場合は,たどりは次のノードを探し,拒否されたノードがそこに存在しなかったものとして振る舞う。
DOMはフィルタを提供しない。NodeFilter
は,単に,利用者が彼ら自身のフィルタを提供するために実装できるインタフェースとする。
NodeFilter
は,ノードからノードへのたどり方を知る必要はないし,たどられているデータ構造について何も知る必要もない。これによって,NodeFilterが知る必要があるのは,単一のノードの評価方法だけとなるので,フィルタを書くことが非常に容易になる。一つのフィルタを多くの異なる種類のたどりで使用してもよく,コードの再利用を推奨する。
// 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()メソッドによって返される。
FILTER_ACCEPT
NodeIterator
又はTreeWalker
のために定義された誘導メソッドは,このノードを返す。
FILTER_REJECT
NodeIterator
又はTreeWalker
のために定義された誘導メソッドは,このノードを返さない。TreeWalker
の場合は,このノードの子どもも拒否される。NodeIterators
は,これをFILTER_SKIP
の同義語として扱う。
FILTER_SKIP
NodeIterator
又はTreeWalker
のために定義された誘導メソッドは,このノードを返さない。ただし,NodeIterator
及びTreeWalker
の両方について,このノードの子どもは,検討される。 これらは,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
の実装によって呼び出される。これは,通常,利用者コードから直接に呼び出されることはない。ただし,同じフィルタを使用して,利用者自身のアプリケーション論理を導きたい場合には,利用者コードから直接に呼び出すことは可能とする。
Node
のn
|
"定義グループ acceptNodeが返す定数"で定義されるとおりに,ノードが受諾されるか,拒否されるか,又は飛ばされるかを決定する定数。 |
TreeWalker
オブジェクトは,そのwhatToShow
フラグ及び(存在する場合には)フィルタが定義する文書のビューを使用して,文書木又は部分木を誘導するために使用する。TreeWalker
を使用して誘導を実行するあらゆる関数は,自動的に,TreeWalker
が定義するあらゆるビューをサポートする。
部分木の論理ビューからのノードを省略することは,結果として,フィルタにかけていない完全な文書の同じ部分木とは実質的に異なる構造になる。TreeWalker
ビューの中で兄弟であるノードが,元のビューの中では,異なる,非常に離れたノードの子であってもよい。例えば,文書のテキストノード及びルートノードを除くすべてのノードを飛ばすNodeFilter
を考えてみる。その結果として得られる論理ビューの中では,すべてのテキストノードは,兄弟となり,元の文書の構造がどんなに深く入れ子になっていても,ルートノードの直接の子どもとして現れることになる。
// 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(); };
Node
のcurrentNode
TreeWalker
が現在位置しているノード。
TreeWalker
の関連するフィルタがもはや受諾しなくなることがある。currentNode
は,それがroot
ノードが指定する部分木内に存在するかしないか,又はフィルタ及びwhatToShow
フラグによって受諾されるかどうかに関わらず,すべてのノードに対して明示的に設定されてもよい。currentNode
が,要求された方向でフィルタが適用されることによって,現在ビューの一部ではない場合であっても,更なるたどりが,currentNode
に相対的に発生する。たどりが可能ではない場合,currentNode
は,変更されない。
|
NOT_SUPPORTED_ERR: |
boolean
のexpandEntityReferences
,読取り専用
TreeWalker
に対して可視かどうかを決定する。falseの場合は,それら及びそれらの子孫は,拒否される。この拒否は,whatToShow
及び(存在する場合には)フィルタに優先する点に注意すること。
whatToShow
フラグを使用し,TreeWalker
の生成するときにexpandEntityReferences
をtrueに設定すること。実体参照ノードをもつが,実体展開をもたない文書のビューを生成するためには,実体参照ノードを見せるようにwhatToShow
フラグを使用し,expandEntityReferences
をfalseに設定すること。NodeFilter
のfilter
,読取り専用
Node
のroot
,読取り専用
TreeWalker
のroot
ノード。unsigned long
のwhatToShow
,読取り専用
TreeWalker
を介して提示されるかを決定する。利用可能な定数の集合は,NodeFilter
インタフェースの中で定義される。whatToShow
が受諾しないノードは飛ばされるが,その場合でも,それらの子どもは検討される。この飛ばしは,(存在する場合には)フィルタに優先する点に注意すること。 firstChild
TreeWalker
を現ノードの最初の可視の子まで移動し,その新しいノードを返す。現ノードに可視の子どもがない場合は,null
を返し,現ノードを保持する。
|
新しいノード,又は現ノードが |
lastChild
TreeWalker
を現ノードの最後の可視の子まで移動し,その新しいノードを返す。現ノードに可視の子どもがない場合は,null
を返し,現ノードを保持する。
|
新しいノード,又は現ノードが |
nextNode
TreeWalker
を,現ノードに相対的な文書順で次の可視のノードまで移動し,その新しいノードを返す。現ノードに次のノードがない場合,又はnextNodeの検索がTreeWalker
のroot
ノードから上に移動しようとした場合は,null
を返し,現ノードを保持する。
|
新しいノード,又は現ノードが |
nextSibling
parentNode
previousNode
TreeWalker
を,現ノードに相対的な文書順で前の可視のノードに移動し,その新しいノードを返す。現ノードに前のノードがない場合,又はpreviousNode
の検索がTreeWalker
のroot
ノードから上に移動しようとした場合は,null
を返し,現ノードを保持する。
|
新しいノード,又は現ノードが |
previousSibling
DocumentTraversal
は,繰返し子,並びにノード及びその子どもを文書順でたどる木散策を生成するメソッドを含む。ここでいう文書順とは,深さの方向を最初にする前順たどりであって,文書のテキスト表現で開始タグが現れる順番と等価になっている。Traversal(たどり)機能をサポートするDOMでは,DocumentTraversal
は,Documentインタフェースを実装する同じオブジェクトによって,実装される。
// 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
を生成する。
Node
のroot
whatToShow
フラグ及び(存在する場合には)フィルタは考慮されない。ルートは,null
であってはならない。unsigned long
のwhatToShow
SHOW_
値の集合については,NodeFilter
の記述を参照すること。
OR
を使用して,これらのフラグを組み合わせることができる。NodeFilter
のfilter
TreeWalker
と一緒に使用されるNodeFilter
,又はフィルタが存在しないことを示すnull
。boolean
のentityReferenceExpansion
新しく生成された |
|
NOT_SUPPORTED_ERR: 指定された |
createTreeWalker
TreeWalker
を生成する。
Node
のroot
TreeWalker
に対してroot
として振る舞うノード。whatToShow
フラグ及びNodeFilter
は,この値の設定時には考慮されない。すなわち,あらゆるノード型が,root
として受諾される。TreeWalker
のcurrentNode
は,可視かどうかに関係なく,このノードに対して初期化される。root
は,parentNode
及びnextNodeといった文書構造の中を上方向に検索するたどりメソッドのための停止位置として機能する。root
は,null
であってはならない。unsigned long
のwhatToShow
NodeFilter
の記述を参照すること。
OR
を使用して,これらのフラグを組み合わせることができる。NodeFilter
のfilter
TreeWalker
と一緒に使用されるNodeFilter
,又はフィルタが存在しないことを示すnull
。boolean
のentityReferenceExpansion
EntityReference
ノードの内容は,論理ビューの中で提示されない。
新しく生成された |
|
NOT_SUPPORTED_ERR: 指定された |