最近更新: 2010-04-19

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.xSpiderMonkey/TraceMonkey (C語言)OK
IE 8JScriptFailed
Google Chrome 4.xV8 (C++)Failed
Opera 10CarakanFailed

以下為 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 語言的參考文件。

相關文章
樂多舊網址: http://blog.roodo.com/rocksaying/archives/12211077.html