名前空間付き属性のあれこれ (属性のプロパティ値とXMLSerializer, DOMParser)

各実装によっていろいろ挙動が異なることを発見したのでメモっておく。

以下のブラウザで確認した。

<update>

コメント欄参照。
通常のHTMLでは名前空間に対応しない仕様みたい。XHTMLにしてやったら大抵うまく動いた。

</update>

HTML中の名前空間付き属性とsetAttributeNS

<p xmlns:ns="namespace" ns:attr="value">hoge</p>

というHTMLがあったとする。

var p = document.getElementsByTagName("p")[0];
p.setAttributeNS("namespace", "ns:jsAttr", "jsValue");

というJavaScriptを書いた。この時のp要素の属性(Attr)のプロパティ値

各ブラウザにおける属性のプロパティ値
Browser attr 備考
prefix localName namespaceURI value
Firefox ns:attr value
xmlns:ns namespace
ns jsAttr namespace jsValue setAttributeNSで設定
Chrome xmlns:ns namespace
ns:attr value
ns jaAttr namespace jsValue setAttributeNSで設定
Opera xmlns:ns namespace
ns:attr value
ns jsAttr namespace jsValue setAttributeNSで設定

どれも似たような動きで、HTMLのコード中の属性には、prefixがなく、localNameにまとめて出てくる。一方、setAttributeNSではprefixlocalNameにきちんと分かれる。

3つエンジンで同じ挙動ということは、これが仕様なのかだろうか?(どの辺りを読めば良いか分からないので、確認していない)

XMLSerializerとDOMParser

次のJSをHTMLDocument中で実行する

var p = document.createElement("p");
p.setAttribute("ns:attr", "setAttribute");
p.setAttributeNS("namespace", "ns:attr", "setAttributeNS");

var str = (new XMLSerializer).serializeToString(p);
console.log(str);
var doc = (new DOMParser).parseFromString(str, "application/xml");
console.log(doc.documentElement.localName);
各ブラウザにおけるシリアライズした値とそれをパースした結果
Browser serializeToString documentElement.localName 備考
Firefox <p xmlns="http://www.w3.org/1999/xhtml" ns:attr="setAttribute" ns:attr="setAttributeNS" xmlns:ns="namespace"></p> parsererror parseFromString時に"属性が二重に定義されています"のエラーが出力される
Chrome <p ns:attr="setAttribute" attr="setAttributeNS"></p> doc.documentElementが null である例外が出る
Opera <p ns:attr="setAttribute" ns:attr="setAttributeNS"/> parsererror

はい、どれも真っ当にパースできなかった。XMLSerializer の出力が真っ当ではないので当たり前だが。
そもそも、p.setAttribute("ns:attr", "setAttribute")部分で、名前空間指定がなく設定できないよというエラーが出るべきではないかと思うのだが...。

他にも問題がある。


どのブラウザも真っ当な動きをしていないみたいで辛い...。