JavaScript: document.evaluate、nodeValue、デフォルト名前空間
$gを更新した。
それ絡みで気付いたことのメモ。
nodeValueとtextContent
tmp = xp.snapshotItem(i); ret[i] = tmp.nodeValue || tmp.textContent;
第3引数にtypeofがobjectとなる引数を与えた場合の挙動を改良。
//a/@hrefのようにしてAttribute Nodeを集めたとき、それらのnodeValueプロパティを参照すると属性値(href属性の値)が得られる。
Element Nodeのときはnullになるので、この場合はtextContentをみる。
$g('//a', document, {})
// -> アンカーテキスト
// ["mayokara note", "Older >", ...]
$g('//a/@href', document, {})
// -> href属性値
// ["http://mayokara.info/note/", "http://mayokara.info/note/1", ...]
で、こういうことができる。
ただしa要素のhrefプロパティから取得した場合とは違い、Absolute URIにはならない。
Relative URIで書かれているものは、そのまま。
デフォルト名前空間について
var doc = context.ownerDocument || context, defaultNamespaceURI = (/xml$/).test(doc.contentType) ? doc.documentElement.getAttribute("xmlns") : "";
var resolver = function(prefix){
return doc.createNSResolver(context).lookupNamespaceURI(prefix) || defaultNamespaceURI;
};
XHTMLのみを対象とするのならhttp://www.w3.org/1999/xhtml決め打ちで良いのだけど、RSS 1.0を(GM_)XMLHttpRequestで取得してDOMParserに食わせたものにXPathを使いたいときはhttp://purl.org/rss/1.0/を返す必要がある。
Atomであればhttp://www.w3.org/2005/Atom。
そういうときのための修正。
デフォルトリゾルバは XML 文書のデフォルト名前空間を処理しません。
Introduction to using XPath in JavaScript - MDC # XML 文書のデフォルト名前空間を実装する
createNSResolverはdcやらrdfやらに引っ掛らなかったときにデフォルト名前空間のURIを返さない。nullが返る。
なので、documentElementのxmlns属性を見て、それを返すようにする。
namespaceURIプロパティは、RSS 1.0のようにdocumentElementのnodeNameがrdf:RDFのときxmlns:rdfのURIを返してくるので使えない。
デフォルト名前空間を含め、名前空間の接頭辞は宣言している要素とその子孫で有効ですが、子孫要素で同じ接頭辞(あるいはデフォルト)の名前空間が宣言されると、その内部では新しい宣言によって結びつきが上書きされます。
XML名前空間の簡単な説明 # デフォルト名前空間
厳密にはcontextから(取得されるノードから?)遡って調べなければならないのだけど、手を抜いた。
やるとすれば、contextの兄弟ノードとして適当なノードをinsertして、それのnamespaceURIプロパティを取るのが楽そう。
ついでに、きちんとcreateNSResolverを使うようにした(dc:dateなどのため)。
余録:Firefox2のDOMParser
RSS 1.0を食わせたとき、documentElementの子要素以下のノードが取れない。
Bugzillaにあたってみたけど、探すのに不得手なせいで見つけられなかった。
Firefox3だとちゃんと取れる模様。