JavaScript: document.evaluate、nodeValue、デフォルト名前空間

$gを更新した。

それ絡みで気付いたことのメモ。

nodeValueとtextContent

tmp = xp.snapshotItem(i);
ret[i] = tmp.nodeValue || tmp.textContent;

第3引数にtypeofがobjectとなる引数を与えた場合の挙動を改良。


DOM:element.nodeValue - MDC

//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だとちゃんと取れる模様。

Comment: 0

Comment Form
Name
URL
Comment

Trackback: 0

Trackback URL
http://mayokara.info/note/trackback/317
Attention
スパム対策のため、当エントリへのリンクがないトラックバックをブロックしています。