document.contentType == "application/xhtml+xml"なページでの$X

document.evaluateと名前空間がわからない - by edvakf in hatenaへのレスです。

document.contentTypeが"application/xhtml+xml"の場合、名前空間があるので、通常のXPathでは要素を取得できません。resolverとprefixが必要になります。*1

で、m.twitterはHTTPヘッダーで

Content-Type: application/xhtml+xml; charaset=UTF8; charset=utf-8

を返しているので、XMLとして扱われ、そうでない大抵のサイトはHTML上でXHTMLを宣言していても、text/htmlで返すので、HTMLとして扱われます。

Content-Type: text/html; charset=utf-8

繰り返しですが、 namespace がある Document では prefix がないと要素の取得ができません( prefix がないと resolver が働かない)。なので、$X('//x:a')とすればOKなはずなんですが、$Xがうまく機能してないみたいでエラーになるみたいです。
てなわけで、を参考に修正版$Xをあげて置きました。

http://gist.github.com/3242

これを使って

$X('//x:a')

ってするとHTMLでもXMLでも取得できます。

あれ、でも本家がlookupNamespaceURIを使ってないのにはなにか理由があるのかな。うまく動いてる気がするけど。
あーOperaで動いてないみたい

[追記:2008/10/07 16:37] Operaで動いてなかったので修正。document.contentTypeって非標準なんですね。油断してた。
結局resolverだけでみるとこんな感じ。

function (prefix) {
    return document.createNSResolver(context).lookupNamespaceURI(prefix) || document.documentElement.namespaceURI || "";
}

[追記:2008/10/07 17:02] さらに修正、contextに指定した要素がnamespaceURIを持ってるならそれを使う作戦。

function (prefix) {
  return document.createNSResolver(context).lookupNamespaceURI(prefix) ||
         context.namespaceURI || document.documentElement.namespaceURI || "";
}

これを導入したoAutoPagerizeで、下のSITEINFO使って、m.twitter.comでAutoPagerできるのを確認。

{
	 url:         'http://m\\.twitter\\.com/.*'
	,nextLink:    '//h:a[@accesskey="6"]'
	,pageElement: '//h:body/h:ul/h:li'
	,exampleUrl:  'http://m.twitter.com/os0x'
},

*1:resolverとかprefixってなにさっていうと、名前空間は http://www.w3.org/1999/xhtml みたいにURLで確保されて、この長ったらしいURLはいちいち書きたくないから prefix を決めて代用しようぜって感じ。そのprefixと名前空間の対応を解決するのがresolverです。と、理解してるんですが、あってるか不安。あとで調べます。