新しく作成したXML文書でDOM HTMLを使う

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とは見なされないようです。