E4X in Firefox
nanto_vi (TOYAMA Nao)
自己紹介
- 外山真 (とやまなお)
- 肩書き: 学生
- Not in
Education, Employment or Training
E4Xとは?
- ECMAScript for XML
- ECMAScriptにネイティブXMLサポートを追加
- ネイティブ → Date, Array and etc.
- Firefox 1.5/JavaScript 1.6で実装
型
- XML型
- DOM Nodeに相当
- 属性・テキストノードなども含む
- XMLList型
- DOM NodeList/DocumentFragmentに相当
- 1項目のXMLListはXMLとして扱える
XML/XMLListコンストラクタ
- new XML("<a><b/></a>")
- → <parent xmlns="[デフォルト名前空間]"><a><b/></a></parent>
- XML宣言・文書型宣言は含められない
- new XMLList("<a/><b/><c/>")
リテラル表記
- <a><b/></a>
- <><a/><b/><c/></>
- 式(Expression)の埋め込み
- <{elem} {attr}={value}>{content}</{elem}>
- <a attr={ "\"" }/> → <a attr="""/>
- <a>{ "<b/>" }</a> → <a><b/></a>
演算子
- 文字列化
- <a>content</a> → "content"
- <a><b/></a> → "<a>\n <b/>\n</a>"
- typeof <a/> == typeof <></> == "xml"
- 等価演算子
- <a/> == <a/> (cf. {} != {}, [] != [])
- <a/> !== <a/>
- <a/> + <b/> == <><a/><b/></>
ノードの取得 (1)
- x.child, x["child"]
- 子要素を収めたXMLList
- xがXMLListのときは、x中の各XMLの子要素
- x..descendant
- x.*, x..*
- 子ノード、子孫ノードを収めたXMLList
- テキストノードを含む
ノードの取得 (2)
- list[n]
- XMLList中のn番目のXML
- XML型のxに関して、x[0] === x
- x.*[n]
- x.@attr, x.@["attr"]
- 存在しなければ空XMLList
フィルタリング
- list.(expr)
- フィルタリング結果のXMLList
- expr評価時にはlist中の各要素がそれぞれスコープチェーンに追加される
- books.book.(@author == "Alan")
- author属性が"Alan"であるbook要素の集合
プロパティへの代入
- XML/XMLList型を代入
- 子要素が置き換わる
- x = <a><b>c</b></a>
- x.b = <d/>
- その他の型を代入
- 子要素の内容が置き換わる
- x.b = "other than xml"
- → <a><b>other than xml</b></a>
存在しないプロパティへの代入
- XML/XMLList型を代入
- 要素を最後に追加
- x.d = <d/> → <a><b>c</b><d/></a>
- その他の型を代入
- 要素を作成し最後に追加
- x.d = "e" → <a><b>c</b><d>e</d></a>
- 途中の要素も作成される
- x = <a/>; x.b.c.d = "";
- → <a><b><c><d/></c></b></a>
ノードの削除
- delete演算子
- x = <a attr="value"><b/><c/></a>
- delete x.b → <a attr="value"><c/></a>
- delete x.*[0] → <a attr="value"><c/></a>
- delete x.@attr → <a><b/><c/></a>
- 空文字列の代入
- x = <a><b><c/></b></a>; x.b = "";
メソッド呼び出し
- x = <a><b/><c/><d/></a>
- x.*.length → <></>
- x.*.length() → 3
- メソッドの移譲
- XMLList → XML
- XML → String
- <a>b</a>.toUpperCase() → "B"
- replaceメソッド(既にXMLにある)以外
各種メソッド
- appendChild, prependChild, insertChildBefore, insertChildAfter
- x.appendChild(xml) ≒ x.* += xml
- E4X: x.appendChild(c) == x
- DOM: x.appendChild(c) == c
- nodeKind()
- "element", "attribute", "text" and etc.
- copy(), parent(), toXMLString() and etc.
列挙
- x = <a><b/><c/><d/></a>
- for (var i in x.*)
- for each (var i in x.*)
- → i = <b/>, <c/>, <d/>
- 一般のオブジェクトにも使用可能
XML名前空間
- Namespace型
- ns = new Namespace([[prefix,] uri])
- x.ns::child, x.@ns::attr, x.@*::*
- QName型
- qn = new QName([[ns,] name])
- x.hasOwnProperty(qn)
- x.ns::[name] == x[new QName(ns, name)]
デフォルト名前空間
- default xml namespace = ns;
- リテラル表記で作成される要素
- 非修飾名の解決
- x = <ns:a xmlns:ns={ ns }><ns:b/></ns:a>
- QNameオブジェクトの作成
- new QName(name).uri == ns.uri
SpiderMonkeyによる拡張
- function名前空間
- XML [[Get]]/[[Put]] → Object [[Get]]/[[Put]]
- x.name → <></>
- x.function::name → function name() { }
- html..*.(/h[1-6]$/.test(function::name()))
- AttributeName型/コンストラクタ
- x = <a ns:attr="val" xmlns:ns={ ns }/>
- x.hasOwnProperty(new AttributeName(ns, "attr"))
SpiderMonkeyのバグ (1)
- 関数内でのデフォルト名前空間
- default xml namespace = ns;
- x = <a><b>D</b><b xmlns="">N</b></a>
- x.b → <b xmlns="">N</b>
- x.ns::b → <b xmlns="...">D</b>
- 内容にゴミが混じることがある
- <{ "a" } attr="value">c</a>
- → <a attr="value">>c</a>
SpiderMonkeyのバグ (2)
- 名前空間宣言が消失することがある
- <a xmlns="..."><b xmlns=""/></a>
- → '<a xmlns="..."><b/></a>'
- x = <a/>; x.@ns::attr = "value";
- XMLオブジェクトに対する列挙
- for each (var i in <a><b/><c/><d/></a>)
DOMとの変換
- DOMノード → E4X XML
- XMLSerializer → XML/XMLList
- new XML(new XMLSerializer().serializeToString(node));
- E4X XML → DOMノード
- DOMParser → importNode
- document.importNode(new DOMParser().parseFromString(x.toXMLString(), "application/xml").documentElement, true)
使用例 (1)
- Greasemonkey
- userChrome.js
- Overlayファイルの動的生成
- doc.loadOverlay("data:application/vnd.mozilla.xul+xml;charset=utf-8," + encodeURI(x.toXMLString()), null)
使用例 (2)
- Calendar (Sunbird/Lightning)
- Google Calendarのフィードのパース
- HTMLエクスポート
- コンパイル成功 → 整形式の保証
- ヒアドキュメントとして
- 改行も含められる
- <>foo { bar }</>, <![CDATA[baz]]>
資料
- 仕様書
- 簡単! 快適! E4XでHappy Firefox Lifeを!