ECMAScript E4X 體驗與實作現況
E4X 全名為 ECMAScript for XML ,是 ECMA-357 Standard 的規範項目。它屬於 ECMAScript 的選用性能力,所以 ECMAScript 實作品不一定會實作的。目前看來,最積極支援 E4X 的就是 Mozilla 。它旗下兩種 ECMAScript 引擎 (SpiderMonkey, Rhino) 都支援 E4X。另外, Adobe 的 ActionScript 也支援 E4X ,只是用法略有不同。
E4X 最主要的能力,就是將 XML 文件直接視為 ECMAScript 中的原生型態 (primitive type)。一份 XML 資料在 E4X 眼中,其地位等同於 1,2,3, "hello" 這些原生型態的資料。E4X 基本上將 XML 資料視為容器,因此提供許多與 Array 相同的方法。這意味著你可以像是在面對 Array 般地操作 XML 資料。
瀏覽器上的 ECMAScript/JavaScript 引擎
我測試了4種常見瀏覽器上的 ECMAScript 引擎。目前看來,只有 Mozilla Firefox 積極地支援 E4X 。其他3種瀏覽器,都不支援 E4X。
瀏覽器 | ECMAScript 引擎 | 支援E4X |
---|---|---|
Firefox 3.x | SpiderMonkey/TraceMonkey (C語言) | OK |
IE 8 | JScript | Failed |
Google Chrome 4.x | V8 (C++) | Failed |
Opera 10 | Carakan | Failed |
以下為 E4X 範例程式碼。各位可以瀏覽器開啟 JavaScript Shell 網頁,直接將下列的 ECMAScript 程式碼貼上去測試。
e4x1.js
// JavaScript Document
//E4X
var x = <list><item key="a">1</item><item key="b">2</item></list>
print( x.item[0] )
print( x.item[0].@key )
print( x.item.(@key == "a") ) // XPATH
pc = x.item.length()
x.item[pc] = <item/>
x.item[pc].@key = "c"
x.item[pc] = 30
pc = x.item.length()
x.item[pc] = <item key="d">40</item>
print( x.item.(@key=="d") )
print( x )
E4X 與 ActionScript
Adobe Flex3 採用的 ActionScript 3 ,支援 E4X。為了支援 E4X ,還特地將 ActionScript2 時期就提供的 XML 類別改名為 XMLDocument 類別。所以 ActionScript3 的 XML 類別,是符合 E4X 的。
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo"
creationComplete="initApp()">
<fx:Script>
<![CDATA[
public function initApp():void
{
var x:XML = <list><item key="a">1</item></list>;
x.item[1] = <item key="b">2</item>;
x.item[2] = Number(x.item.(@key == "a")); // XPATH
x.item[2].@key = "c"
var s:String = '<item key="d">' + x.item.length() + '</item>'
x.item += new XML(s)
mainTxt.text = x.toString();
}
]]>
</fx:Script>
<s:TextArea id="mainTxt" width="400"/>
</s:Application>
E4X 與 Mozilla Rhino
Mozilla rhino 是目前 ECMAScript 實作品中,少數以 Java 實作者。我們可以在 Rhino 網頁取得 rhino 的 jar 。Ubuntu 的使用者,可以直接安裝 rhino 這個套件,安裝後就有一個名為 rhino
的指令可以執行 rhino 。
由於 rhino 運行於 JVM 之上,因此 rhino 提供一個名叫 Packages.java 的 host 個體以及一個擴充函數 importPackage()
。透過這個個體,我們可以在 rhino 中呼叫 Java class 。
此處將展示我們在 rhino 中,如何透過 Java 的 IO class 讀取 XML 文件,再使用 E4X 操作內容。這也是 rhino 與 E4X 最有趣的應用。
Packages.java 是一個 host object,所以使用時可以省略名稱空間 Packages。使用系統函數 importPackage()
可以從 Packages.java 中匯入其中的類別到系統的名稱空間中。被匯入的類別,使用時可以省略前置的名稱,一如我們在 Java 語言中使用 import
時的用法。
e4x2.js
// JavaScript Document
//Packages.java 使用時可以省略名稱空間 Packages。
//匯入 java.io 類別。其意等同 Java 語言中的 import java.io;
importPackage(java.io);
try {
var fin = new BufferedReader(new FileReader("c:/desktop/sample.xml"));
var str = "", buf = "";
buf = fin.readLine();
if ( buf != null && /^<\?xml/.test(buf) ) {
while ((buf = fin.readLine()) != null) {
str = str + buf;
}
}
fin.close();
}
catch (e) {
}
//print(str)
var x;
try {
x = new XML(str); //unserialize
}
catch(e) {
//print(e)
}
print(x);
print(x.item[1]);
x.item[2] = <item key="c">3</item>;
print(x);
var output_str = x.toString(); //serialize
print(output_str);
print(output_str.length);
sample.xml
<?xml version="1.0" encoding="utf8"?>
<list>
<item key="a">1</item>
<item key="b">2</item>
</list>
當我使用 rhino 時,我發現不同的 JVM 版本,對 E4X 有不同的支援度。我使用 Sun Java 6 與 OpenJDK6 這兩套 JVM 去執行同一個 rhino jar。當 rhino 運行在 Sun Java 6 JVM 時,可支援 E4X 。當 rhino 運行在 OpenJDK6 JVM 時,不支援 E4X 。我不知道這個差異性的原因出在哪。
另外,Java6 內建在 javax.script 套件中的 JavaScript 引擎,是被拿掉 E4X 能力的 rhino 。這在官方文件上有寫明。大概是怕 E4X 太方便,會倒打自己一巴掌吧。
E4X (ECMAScript for XML - ECMA Standard 357) has been excluded. Use of an XML literal in JavaScript code will result in a syntax error.
Java Scripting Programmer's Guide
下列為在 Java 平台上,使用 JavaScript 語言的參考文件。