名前空間付き属性のあれこれ (属性のプロパティ値とXMLSerializer, DOMParser)
各実装によっていろいろ挙動が異なることを発見したのでメモっておく。
以下のブラウザで確認した。
- Firefox 15.0.1
- GoogleChrome 23.0.1262.0 dev-m
- Opera 12.50
コメント欄参照。
通常のHTMLでは名前空間に対応しない仕様みたい。XHTMLにしてやったら大抵うまく動いた。
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
ではprefixとlocalNameにきちんと分かれる。
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")
部分で、名前空間指定がなく設定できないよというエラーが出るべきではないかと思うのだが...。
他にも問題がある。
- Firefox 以外は名前空間が付かないので、可逆変換がほぼ無理
- Chrome は
setAttributeNS
した属性のシリアライズ時に名前空間名が付かない - Chrome で、DOMParser の仕様としてパースに失敗しても
<parsererror xmlns="http://www.mozilla.org/newlayout/xml/parsererror.xml">エラーメッセージ</parsererror>
を返す仕様(参照: http://html5.org/specs/dom-parsing.html#domparser)なのだが、返していない
どのブラウザも真っ当な動きをしていないみたいで辛い...。