E4X in Firefox
nanto_vi (TOYAMA Nao)
自己紹介
- 外山真 (とやまなお)
  
- 肩書き: 学生
- Not in Education, Employment orTraining
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を!