Hatena::agenda経由で、ブラウザでミニマムXML (3):作るの記事を拝見したところ、ブラウザでDOM(document.implementation.createDocument)により作成された新規の文書ノードについて、以下のような記述がありました。
新規の文書ノードはXML DOMの文書ノードと考えても(たいていは)大丈夫です。しかし、これはいいことばかりではありません。HTMLが持っていた豊富な機能性が使えないのです。例えば、getElementByIdメソッドは存在しないか、動かないか、動くかも知れないがお手軽にはいかないかです。
こういう状況が改善されるためには、XHTMLマークアップが一般化して、XML DOM(DOMコア)の拡張としてのHTML DOMが、ブラウザのdocumentとして実装される必要があります。いったい、いつになることやら。はたして、そのようになるかどうかもあやしいですしね。
この記述を読んで思ったのは、「文書要素の名前空間URIがXHTMLのものになっていれば、DOM HTMLも使えるものなのでは?」ということでした。以前にCSS切替スクリプトを作った時なんかでも、Firefoxではapplication/xhtml+xmlの文書でDOM HTMLのプロパティがふつうに使えていた覚えがあったので、新規に作成した文書でそうならないとは考えにくかったのです。
Firefoxでの実装を確認するため、以下のようなスクリプトを元にbookmarkletを作り、色々と書き換えて試してみました。
(function(){
var ns = 'http://www.w3.org/1999/xhtml';
var doc = document.implementation.createDocument(ns, 'html', null);
var html = doc.documentElement;
var body = doc.createElementNS(ns, 'body');
var p1 = doc.createElementNS(ns, 'p');
var p2 = doc.createElementNS(ns, 'p');
var p3 = doc.createElement('p');
html.appendChild(body);
body.appendChild(p1);
body.appendChild(p2);
body.appendChild(p3);
p1.appendChild(doc.createTextNode('foo'));
p2.appendChild(doc.createTextNode('bar'));
p3.appendChild(doc.createTextNode('baz'));
p1.id = 'p1';
p1.title = 'title test';
p2.setAttribute('id', 'p2');
p2.className = 'hoge';
p3.setAttribute('id', 'p3');
alert(html.innerHTML /* ここで色々確認*/ );
})();
結果、文書要素の名前空間URIがXHTMLのものとなるように新規文書を作り、かつ文書内の要素もXHTMLの名前空間URIを持つように作れば、DOM HTMLで使える属性への簡易アクセスのためのプロパティ(id, title, className等)やinnerHTML、またid属性を目標にしたgetElementByIdも問題なく使えるようでした。(確認はFirefox 1.0.7と1.5 Beta 2で行いました)
要素はcreateElementNSで作らないといけない、というのが推測と違っていた点でした。createElementで作った要素は、namespaceURIの値がnullとなっており、DOM仕様で言うところのHTMLElementとは見なされないようです。