[1] [[DOM水準3]] で定義されている[DFN[[[界面]] [CODE(DOMi)[XPathNSResolver]]]] は、 [[XPath]] [[式]]を解釈するに当たって[[名前空間接頭辞]]を[[名前空間URI]] に[[解決]]する必要が生じた時に呼び出される[[メソッド]] [CODE(DOMm)[[[lookupNamespaceURI]]]] が定義されている[[界面]]です。 [2] 仕様書: - [[DOM水準3]] -- [[XPath]] [CODE(DOMi)[XPathNSResolver]] [3] 界面: - '''メソッド [CODE(DOMm)[[[lookupNamespaceURI]]]]''': [[名前空間接頭辞]]を受け取り、[[名前空間URI]] を返します。 [4] '''[CODE(DOMi)[Node]] の [CODE(DOMm)[XPathNSResolver]]''': [[DOM水準3]] の [CODE(DOMi)[[[Node]]]] [[界面]]でも [CODE(DOMm)[lookupNamespaceURI]] メソッドが定義されています。 [CODE(DOMi)[XPathNSResolver]] のメソッドは [CODE(DOMi)[Node]] のメソッドの subset のような定義になっています。 ([CODE(DOMi)[Node]] 界面を直接使わないのは、 [[節点]]を使わなくても名前空間解決ができるようにするためと、 [[DOM水準3]] [[中核]]モジュールの実装がなくても [[XPath]] モジュールを使えるようにするためらしいです。) [5] '''接頭辞無しの既定名前空間''': [[XPath 1.0]] において[[名前空間接頭辞]]が無い [CODE[[[QName]]]] ([[既定名前空間]]) は [[null名前空間]]に固定されています。 ですから少なくても [[XPath 1.0]] の[[式]]の解釈のために [CODE(DOMm)[[[lookupNamespaceURI]]]] の引数に [CODE(DOM)[[[null]]]] や空文字列が渡されることはなく、渡された場合の結果は未定義とされています [SRC[DOM 水準3 XPath]]。 [WEAK[([CODE(DOMi)[[[Node]]]] 界面の同名のメソッドは [CODE(DOM)[[[null]]]] が渡された場合の動作も定義されています。)]] [[#comment]] * 作成 [6] '''節点から作成''': [CODE(DOMi)[[[XPathEvaluator]]]] [[界面]]で定義されている [CODE(DOMm)[[[createNSResolver]]]] メソッドは、 [CODE(DOMi)[[[Node]]]] を受け取って [CODE(DOMi)[[[XPathNSResolver]]]] を作成します。 作成された [CODE(DOMi)[[[XPathNSResolver]]]] は、 [CODE(DOMm)[[[lookupNamespaceURI]]]] メソッドが呼ばれたら [CODE(DOMi)[[[Node]]]] の [CODE(DOMm)[[[lookupNamespaceURI]]]] メソッドを呼ぶような動作をします [SRC[DOM 水準3 XPath]]。 [[XML]] の[[要素]]の[[内容]]として書かれている [[XPath]] の[[式]]を、その[[要素]]における[[名前空間]]の束縛に従って解釈する、 というような場面でこの方法で作成した [CODE(DOMi)[[[XPathNSResolver]]]] を使うと便利そうです。 [7] '''節点からキャストで作成''': [[DOM水準3]] の[[中核]]モジュールと [[XPath]] モジュールの両方に対応した気が利いた [WEAK[([Q[[[界面]]]]の概念を持つ言語での)]] [[DOM]] の実装なら、 [[DOM水準3]] の [CODE(DOMi)[[[Node]]]] 界面を実装した物体が [CODE(DOMi)[[[XPathNSResolver]]]] 界面も実装しているはずです。ですから、 [PRE(example java code)[ resolver = (XPathNSResolver) document.getElementById ("someElement"); ]PRE] のようなことが [WEAK[(>>6 を使わずに)]] できるでしょう。 [8] '''[CODE(DOMm)[lookupNamespaceURI]] メソッドを持った物体を作成''': [[型]]に関して弱い言語なら、適当に [CODE(DOMi)[[[lookupNamespaceURI]]]] メソッドを持つ物体を用意すれば OK です。例えば >>7 にある例は [PRE(example JS code)[ resolver = document.getElementById ("someElement"); ]PRE] のように特に何もしなくても大丈夫です。また、 [PRE(example JS code)[ resolver = { lookupNamespaceURI: function (pfx) { switch (pfx) { case 'xhtml1': return "http://www.w3.org/1999/xhtml"; case 'xhtml2': return "http://www.w3.org/2002/06/xhtml2/"; default: return null; } } }; ]PRE] のような感じで物体を作ってもよいです。 * 呼び出し順序 [16] [[Chrome]] も [[Firefox]] も、[[名前空間接頭辞]]それぞれに対して呼び出します。同じ[[名前空間接頭辞]]を複数使ってもキャッシュされたりはせず、毎回呼び出されます。 [TIME[2013-09-28T10:25:25.600Z]] [SRC[>>15]] [17] [[Chrome]] も [[Firefox]] も基本的には[[式]]の前から後ろへと呼び出していきます。しかし同じ[[ステップ]]内で [[Firefox]] は[[名前テスト]] → [[述語]]の順に呼び出しますが、 [[Chrome]] は[[述語]] → [[名前テスト]]の順に呼び出します。[[述語]]が複数ある場合どちらのブラウザーでも前から後ろへと呼び出します。 [TIME[2013-09-28T10:27:24.500Z]] [SRC[>>15]] [19] 構文エラーがある場合、 [[Chrome]] も [[Firefox]] もその前にある[[名前空間接頭辞]]については呼び出しますが、 それ以後の[[名前空間接頭辞]]は呼び出しません。 [SRC[>>18]] [[Firefox]] は[[字句解析]]レベルでのエラーがあるとそれ以前の[[名前空間接頭辞]]についても呼び出しませんが、 [[Chrome]] は呼び出します。 [SRC[>>20]] また [[Chrome]] は >>17 の通り[[述語]]を先に処理するので、[[述語]]で構文エラーがあると[[名前テスト]]の[[名前空間接頭辞]]は呼び出されません。 [SRC[>>21]] [TIME[2013-09-28T10:29:18.00Z]] [23] [[Chrome]] も [[Firefox]] も、 [[QName]] や [[NameTest]] の全体の構文解析が終わってから[[名前空間接頭辞]]について呼び出すようです。 [TIME[2013-09-28T11:20:02.300Z]] [REFS[ - [15] - [18] - [20] - [21] ]REFS] * コールバック this 値 [24] [[Firefox]] でも [[Chrome]] でも [CODE(JS)@en[[[Function]]]] を指定した場合の [[callback this value]] はその[[関数]]自体になるようです。 [TIME[2013-10-07T14:14:52.000Z]] * 返す値の解釈 [22] [[Chrome]] も [[Firefox]] も [CODE[[[null]]]] が返されると [CODE(JS)@en[[[document.evaluate]]]] は [CODE(DOM)@en[[[NamespaceError]]]] を返します。 [CODE[[[undefined]]]] や[[空文字列]]を含むその他の値は[[名前空間URL]]と解釈するようです。ただし[[空文字列]]はどの[[名前空間]]とも ([[null名前空間]]とも) 一致しません。 [[例外]]を投げると [[Firefox]] は [CODE(DOM)@en[[[SyntaxError]]]]、 [[Chrome]] は [CODE(DOM)@en[[[NamespaceError]]]] を返します。 ([CODE(DOM)@en[[[null]]]] と[[例外]]の場合そこで構文解析は終了します。) [TIME[2013-09-28T10:53:58.800Z]] * 歴史 ** [CODE(DOMi)@en[NSResolver]] [27] [[Selectors API]] ははじめ [[DOM3 XPath]] を参照していましたが、かなり初期に自身で [DFN[[CODE(DOMi)@en[[[NSResolver]]]]]] を定義するようになりました。 [REFS[ - [26] [CITE[2006/webapi/selectors-api/Overview.html - diff - 1.6]] ([TIME[2013-10-12 08:38:19 +09:00]] 版) ]REFS] * メモ [9] 参考: - [10] [CITE[XUL Apps > Tips > DOM3 XPathをノードの検索に活用する - outsider reflex]] - [11] [CITE[Hawk's W3 Laboratory : XML : XPathと名前空間]] - [12] [CITE[Hatena::agenda]] [[XPath]] モジュール全体の使い方は >>10 を見ればよいでしょう。 >>11 と >>12 は名前空間の扱いに少々誤解がみられます。 [13] [CITE@ja[XPath, $X function, NSResolver < 16 < March < 2006 < nulog, NULL::something : out of the headphone]] ([CODE[2007-06-09 23:04:20 +09:00]] 版) ([[名無しさん]] [WEAK[2007-06-09 14:07:18 +00:00]]) [14] [CITE[d:id:quaa]] ([TIME[2007-06-07 22:15:24 +09:00]] 版) ([[名無しさん]] [WEAK[2007-06-09 14:07:44 +00:00]]) [25] [[Chrome]] では [[NoInterfaceObject]] ですが [[Firefox]] では [CODE(JS)@en[window.XPathNSResolver]] が存在します。 [TIME[2013-10-07T14:18:24.00Z]] [28] [[Chrome]] は [[null]] が指定された時に [CODE(DOMi)@en[[[Node]]]] の[[既定名前空間]]ではなく、 [[null]] を返すようです。この点で [CODE(DOMi)@en[[[Node]]]] の [CODE(DOMm)@en[[[lookupNamespaceURI]]]] を呼び出すのと結果が異なります。 ([[空文字列]]だとどちらも [[null]] になります。) [[Firefox]] はどちらでも [[null]] になるので [CODE(DOMi)@en[[[XPathNSResolver]]]] で特別な処理をしているのかどうかは観測できません。 [TIME[2013-10-12T08:41:39.300Z]] [29] [CITE@en-US[Selectors API]] ( ([TIME[2007-08-29 13:51:08 +09:00]] 版)) [30] [CITE@en[384003 – XPathEvaluator does not accept a Node as NSResolver]] ( ([TIME[2013-11-01 00:13:05 +09:00]] 版))