E4X 增加了 JavaScript 程序語言對 XML 的支持,XML 作為在應用程序和平台之間交換文檔和數據的通用方法,得到了廣泛認可。這種認可直接使 XML 成為解決共享文檔和數據的互操作性問題的有效方法。XML 結構組件的靈活性促成了它強大豐富的功能。E4X 使 XML 的結構組件的使用更加方便,因此大大增加了靈活性。
E4X 的目的是簡化編寫 XML 的 Javascript 代碼,是一個與 XML 節點和屬性交互的高效的、強大的工具。E4X 的主要目標是為 JavaScript 開發人員提供一種不依靠文檔對象模型(Document Object Model,DOM)處理 XML 文檔的簡單高效的方法。
Javascript 語言使用 E4X 實用程序為全局對象傳遞新屬性。反過來,XML 對象的很多屬性在 E4X 的序列化和分析函數中是有用的。E4X 重用現有的 JavaScript 運算符(用於 XML 的創建、操作及導航)。
E4X 開發需要的時間很短,而且容易掌握。這些優點可以使讀、寫操作和相關運算變得簡單高效。因此產生的簡便性簡化了代碼編寫,方便代碼的修改並且縮短了代碼的部署周期。另外,靈活敏捷的 E4X 技術是為日益重要的移動應用程序量身定做的。
為了說明 E4X 的功能和靈活性,我將一個音樂目錄作為主要輸入源,描述處理 XML 數據所使用的主要特征。本文中的大多數的例子基於 清單 1 中的 XML 文檔。
清單 1. 用於許多示例的 XML 音樂對象
<mp3>
<music genre="classical">
<artist>Ludwig van Beethoven</artist>
<song>Fifth Symphony</song>
</music>
<music genre="jazz">
<artist>Grover Washington, Jr.</artist>
<song>The Best Is Yet to Come</song>
</music>
<music genre="classical">
<artist>Johann Sebastian Bach</artist>
<song>Double Concerto in D- for Two Violins</song>
</music>
<music genre="jazz">
<artist>Dave Brubeck</artist>
<song>Take Five</song>
<song>Truth Is Fallen</song>
</music>
<music genre="classical">
<artist>Johannes Brahms</artist>
<song>Piano Sonata No. 1 in C major</song>
</music>
</mp3>
創建 XML 對象
這個過程的第一步是創建 XML 對象。E4X 提供了一種 XML() 類型,用來存儲 XML 元素。在 清單 2 中,使用 JavaScript 開發人員熟悉的格式創建新的 XML 對象。
清單 2. 創建 XML 對象
var xmlMusic = new XML() ;
XML 對象創建後,就能裝載 XML 文檔。E4X 有兩個首選的方法來創建 XML 對象。第一種方法是創建 XML 對象,然後裝載它。如 清單 3 所示。
清單 3. 裝載 XML 對象:方法 1
<script type="text/Javascript ; e4x=1">
var xmlMusic=new XML() ;
XMLMusic = <mp3>
<music genre="classical">
<artist>Ludwig van Beethoven</artist>
<song>Fifth Symphony</song>
</music>
<music genre="jazz">
<artist>Grover Washington, Jr.</artist>
<song>The Best Is Yet to Come</song>
</music>
<music genre="classical">
<artist>Johann Sebastian Bach</artist>
<song>Double Concerto in D- for Two Violins</song>
</music>
<music genre="jazz">
<artist>Dave Brubeck</artist>
<song>Take Five</song>
<song>Truth Is Fallen</song>
</music>
<music genre="classical">
<artist>Johannes Brahms</artist>
<song>Piano Sonata No. 1 in C major</song>
</music>
</mp3>
</script>
或者在創建 XML 後,將 XML 文檔作為一個字符串載入到元素中。如 清單 4 所示。
清單 4. 裝載 XML 對象:方法 2
<script type="text/Javascript ; e4x=1">
var xmlMusic=new XML('<mp3><music genre="classical">
<artist>Ludwig van Beethoven</artist>
<song>Fifth Symphony</song></music>
<music genre="jazz"><artist>Grover Washington, Jr.</artist>
<song>The Best Is Yet to Come</song>
</music><music genre="classical">
<artist>Johann Sebastian Bach</artist>
<song>Double Concerto in D- for Two Violins</song></music>
<music genre="jazz"><artist>Dave Brubeck</artist>
<song>Take Five</song><song>Truth Is Fallen</song>
</music><music genre="classical">
<artist>Johannes Brahms</artist>
<song>Piano Sonata No. 1 in C major</song>
</music></mp3>');
</script>
注意,表達式 e4x=1 被添加到 script 語句中。E4X 廣泛用於將 XML 解析到 Javascript 對象中。不過,直接使用 XML 語法將會出現問題。如果嵌入到其他基於標記的環境中,會產生一些無法預料的問題。默認情況下,該問題導致 E4X 在火狐浏覽器 1.5 版的 HTML 頁面中不可用,因為在 Html 中,它與公認的方法(取消來自不兼容浏覽器的腳本)相沖突。為解決這一問題,使用 E4X 時,在表單 type="text/Javascript; e4x=1" 的 script 語句中部署一個屬性。
盡管 XML 對象表現形式和運行機制與常規 JavaScript 對象相似,但是,這兩個對象並不相同。一些 E4X 語法只適用於 E4X XML 對象。Javascript 開發人員對這些語法是熟悉的,但是 E4X 並不為 XML 到本地 JavaScript 對象的直接映像提供便利。相反,它提供了直接映像的假象(illusion)。
訪問數據
XML 對象支持在常規 JavaScript 編程中使用的小圓點(.)和方括號([])符號。E4X 並不訪問對象屬性,而是過載這些運算符,並通過它們訪問子元素。
下面的訪問例子以 上面 創建的 XMLMusic 對象為基礎。要查看全部元素的內容,請使用 清單 5 中的語法。
清單 5. 查看全部元素的內容
document.write(XMLMusic);
該語句的輸出結果為:
Ludwig van Beethoven Fifth Symphony
Grover Washington, Jr. The Best Is Yet to Come
Johann Sebastian Bach Double Concerto in D- for Two Violins
Dave Brubeck Take Five Truth Is Fallen
Johannes Brahms Piano Sonata No. 1 in C major
要查找第三個藝術家,輸入與類似於 清單 6 的語句。
清單 6. 浏覽藝術家 3
document.write ( XMLMusic.music[2].artist );
該語句的輸出結果為:
Johann Sebastian Bach
注意:E4X 從 0 開始記數,因此獲取第三個記錄的索引值為 2。
為獲取第一個音樂節點的所有內容,輸入 清單 7 所示的語句。
清單 7. 獲取第一個音樂節點
document.write (XMLMusic.music[0].*);
該語句的輸出結果為:
Ludwig van Beethoven Fifth Symphony
從這些例子中可以看到,使用 E4X 訪問 XML 節點是非常簡單的。
訪問屬性
可以使用符號(@)訪問 XML 對象的屬性。屬性操作是處理 XML 數據中比較難掌握的部分之一。使用 E4X 可以大大簡化這一任務。例如,要檢索古典流派的所有數據,輸入類似於 清單 8 的語句。
清單 8. 訪問節點屬性
document.write(XMLMusic.music.(@genre==”classical”) );
該語句的輸出結果為:
Ludwig van Beethoven Fifth Symphony
Johann Sebastian Bach Double Concerto in D- for Two Violins
Johannes Brahms Piano Sonata No. 1 in C major
要獲取古典流派中的藝術家名字,輸入 清單 9 中的語句。
清單 9. 獲取古典藝術家名字
document.write(XMLMusic.music.(@genre=="classical").artist );
Which outputs only the names:
Ludwig van Beethoven
Johann Sebastian Bach
Johannes Brahms
在此,E4X 的強大功能、靈活性和簡單易用得到了有力的證明。這樣,不必再因屬性難操作而避免使用它們了。可以很清楚地看到,E4X 能夠輕松處理它們。
添加子節點
E4X 允許使用簡單 JavaScript 符號為一個現有元素添加子元素。例如,如果想要為一個現有的藝術家添加一首歌曲 — 比如 Johann Sebastian Bach 的 Brandenburg Concertos — 使用 “+=” 運算符,如 清單 10 所示。
清單 10. 使用 += 運算符添加一個節點
XMLMusic.music[2].song += "Brandenburg concertos" ;
document.write (XMLMusic.music[2]);
添加節點後的輸出結果為:
Johann Sebastian Bach
Double Concerto in D- for Two Violins
Brandenburg Concertos
現在,Bach 作為 XMLMusic 對象的一部分,有兩個作品,在該語句運行之前只有一個作品。
改變子對象的內容
要改變一個元素或屬性的值,必須對其賦一個新值。如 清單 11 所示。
清單 11. 用 = 運算符修改一個節點
XMLMusic.music[3].song = "Pick Up Sticks" ;
document.write ( XMLMusic.music[3] );
輸出結果為:
Dave Brubeck
Pick Up Sticks
注意:因為使用等號(=)替換 XMLMusic.music[3].song 的內容,Dave Brubeck 的歌曲都被修改,只保留新內容。
刪除子節點
可以使用 delete 語句刪除一個子節點,如 清單 12 所示。
清單12. 刪除子節點
delete XMLMusic.music.song[1] ;
document.write (XMLMusic.music[1].*);
輸出結果為:
Grover Washington, Jr.
歌曲節點被刪除,藝術家節點仍然存在。
過濾
E4X 提供了一種特殊的過濾運算符(圓括號),用來選擇文檔中與特定標准匹配的節點。過濾運算符為數據設置一個條件,從子節點中選出需要的元素。過濾運算符通過用圓括號內的表達式執行。實際上,您已經見過這個運算符了,現在,正式介紹它。
例如,過濾一個屬性,如 清單 13 所示。
清單13. 使用屬性過濾數據
document.write (XMLMusic.music.(@genre=="jazz") );
過濾後的輸出結果為:
Grover Washington, Jr. The Best Is Yet to Come
Dave Brubeck Take Five Truth Is Fallen
除了屬性之外,還可以使用藝術家來過濾數據,如 清單 14 所示。
清單 14. 使用藝術家的名字查找歌曲
document.write (XMLMusic.music.(artist == "Dave Brubeck").song);
過濾的輸出結果為:
Take Five
Truth Is Fallen
處理 XMLList
E4X 識別兩種基本類型:XML() 和 XMLList()。XMLList 對象表示 XML 屬性的一個有序集合 — 比如,菜譜、大洲、電話號碼以及化學元素的列表。由一個以上的節點組成的 E4X 實際上是 XML() 和 XMLList() 對象的組合。XMLList 類型是一個快速查詢的重要工具 — 例如,當查找一個給定節點的子節點時,便可生成一個 XMLList。
下面的代碼概括了 XMLList 的框架,它是基於音樂的示例,包括多個節點:
<music></music>
<music></music>
<music></music>
<music></music>
<music></music>
XMLList 對象有一個初始化程序,它是一個描述 XMLList 對象初始化的表達式。 XMLList 初始化程序描述了 XML 屬性的結構列表,並使用了匿名的 XML 元素語法。初始化程序以 <> 字符開始,以 </> 字符結束。清單 15 中的代碼序列闡明了初始化 XMLList 對象的方法。
清單 15. 初始化 XMLList 對象
var XMLListObject =
<><artist>Ludwig van Beethoven</artist> <song>Fifth Symphony</song></>;
那麼,XML 對象和 XMLList 對象之間有什麼不同呢?本質上的差別是 XML 類型處理一種包含多個子節點的特定對象,XMLList 處理一個包含多個 XML 對象的集合。
E4X 刻意去區別 XML 對象和 XMLList 對象,但這一項幾乎不可能完成。因此,XML 值與 XMLList 值之間若有區別也是可以忽略的。
執行計算
可以像在 XML 中一樣,使用 E4X 對 XML 數據執行計算。例如,可以對一個新的 XML 文檔中的數據進行數學運算。XML 文檔如 清單 16 所示。
清單 16. 計算示例
<script type="text/Javascript ; e4x=1">
var xmlCatalog=new XML() ;
XMLCatalog=<inventory>
<item genre="apparel">
<description>Dress</description>
<price>50.00</price>
<quantity>3</quantity>
</item>
<item genre="Accessory">
<description>Hat.</description>
<price>25.00</price>
<quantity>5</quantity>
</item>
<item genre="apparel">
<description>tIE</description>
<price>15.00</price>
<quantity>7</quantity>
</item>
<item genre="Accessory">
<description>Belt</description>
<price>15.00</price>
<quantity>1</quantity>
</item>
<item genre="apparel">
<description>Suit</description>
<price>100.00</price>
<quantity>2</quantity>
</item>
</inventory>
</script>
這裡給出計算數據的腳本。使用 while 循環語句,計算庫存的總值和倉庫中現有項目的總量。清單 17 使用 length() 方法確定 XML 對象的大小和控制循環。
清單 17. 使用 E4X 進行計算
<script type="text/Javascript ; e4x=1">
var i = 0 ;
var totItems=0 ;
var totInventoryValue=0 ;
while ( i < XMLCatalog.item.length() )
{
totInventoryValue += XMLCatalog.item[i].quantity *
XMLCatalog.item[i].price ;
totItems+= XMLCatalog.item[i].quantity * 1 ;
i = i + 1 ;
}
document.write ("Total number of items: " + totItems + "<p>");
document.write ("Total inventory value: $" + totInventoryValue + "<p>");
</script>
該腳本的輸出結果為:
Total number of items: 18
Total inventory value: $595
使用 XMLObject 方法
E4X 提供了一組計算 XML 對象和 XMLList 對象的方法,從 清單 17 中已經看到如何在腳本中用 length() 方法來控制流程。E4X 方法可以完成很多任務,包括標識屬性、名稱空間以及添加和標識子元素等。
前面提到過,E4X 用一個大小值來消除 XML 對象和 XMLList 對象之間的區別。因此,在 E4X 中,可供 XML 對象使用的方法對有適當大小的 XMLList 對象也適用。
表 1 列出了 XML 對象和 XMLList 對象可用的方法。所有列出的方法都可用於 XML 對象,所有含 “是” 的方法可用於 XML 對象和 XMLList 對象。
表1. XML 和 XMLList 對象可用的方法XML 對象方法
可用於 XMLList 對象XML 對象方法
可用於 XMLList 對象 addNamespace(namespace) 否 name() 否 appendChild(child) 否 namespace([prefix]) 否 attribute(attributeName) 是 namespaceDeclarations() 否 attributes() 是 nodeKind() 否 child(propertyName) 是 normalize() 是 childIndex() 否 parent() 是 children() 是 processingInstructions([name]) 是 comments() 是 prependChild(value) 否 contains(value) 是 removeNamespace(namespace) 否 copy() 是 replace(propertyName, value) 否 descendants([name]) 是 setChildren(value) 否 elements([name]) 是 setLocalName(name) 否 hasComplexContent() 是 setName(name) 否 hasSimpleContent() 是 setNamespace(ns) 否 inScopeNamespaces() 否 text() 是 insertChildAfter(child1, child2) 否 toString() 是 insertChildBefore(child1, child2) 否 toXMLString() 是 length() 是 valueOf() 是 localName() 否在 清單 10 中,采用 += 運算符為 XMLMusic 對象添加一個歌曲節點,使用 appendChild() 方法可得到相同的輸出結果。使用 appendChild() 方法,可以在現有對象或元素末尾添加一個節點。為演示這一功能,清單 18 重復清單 10 中執行的處理過程,但使用 appendChild() 方法代替 += 運算符。
清單 18. 使用 appendChild() 方法添加一個節點
XMLMusic.music[2].appendChild(<song>Brandenburg Concertos</song>) ;
document.write (XMLMusic.music[2].*);
該代碼產生的輸出結果為:
Johann Sebastian Bach
Double Concerto in D- for Two Violins
Brandenburg Concertos
可以看到,輸出結果顯示在 XMLList 對象的第三個元素中添加歌曲,和清單 10 中的代碼的結果相同。
還可以用 prependChild() 方法添加節點。prependChild() 方法在指定元素的子節點之前添加一個節點。例如,同樣使用 Bach 的協奏曲 Brandenburg Concertos,使用 prependChild() 方法,清單 19 中的代碼將作品放在當前歌曲列表的前面,而不是後面。
清單 19. 使用 prependChild() 方法添加一個節點
XMLMusic.music[2].song[0].prependChild(<song>Brandenburg Concertos</song>) ;
document.write (XMLMusic.music[2].*);
結果顯示協奏曲已經插入到最初歌曲節點的前面:
Johann Sebastian Bach
Brandenburg Concertos
Double Concerto in D- for Two Violins
使用 insertBefore() 方法,可以在兩個現有節點之間插入一個節點。清單 20 處理包含兩首歌曲的 Dave Brubeck 數據,使用 insertBefore() 方法可以將歌曲 “Eleven Four” 置於當前兩個節點之間。
清單 20. 使用 insertBefore() 方法添加一個節點
xmlMusic.music[3].insertChildBefore(XMLMusic.music[3].song[1],<song>Eleven Four</song>);
document.write (XMLMusic.music[3].*);
該代碼產生的輸出結果為:
Dave Brubeck
Take Five
Eleven Four
Truth Is Fallen
可以使用另外一種方法 attributes() 來確定一個對象中的屬性。例如,使用 清單 21 中的代碼,列出 XMLMusic 對象的所有屬性。
清單 21. 使用 attribute() 方法確定屬性
document.write (XMLMusic.music.attributes());
該方法生成 XMLMusic 對象包含的所有屬性的列表:
classical
jazz
classical
jazz
classical
可以使用 attributes() 確定 jazz 風格的所有元素。借助 length() 方法,清單 22 中的代碼顯示含 jazz 屬性的所有節點。
清單 22. 確定含 jazz 屬性的元素
var i = 0 ;
while ( i < XMLMusic.music.length() )
{
if ( XMLMusic.music[i].attributes() == "jazz" ) {
document.write (XMLMusic.music[i].* + "<p>");
}
i = i + 1 ;
}
該代碼產生的輸出結果為:
Grover Washington, Jr. The Best Is Yet to Come
Dave Brubeck Take Five Truth Is Fallen
E4X 中的方法(如運算符)提供了一種處理 XML 數據的簡單機制。
浏覽器的兼容性
E4X 是最為簡單易用的處理 XML 數據的方法之一。然而,並不是所有的浏覽器都支持 E4X。目前,Windows® Internet Explorer® 不支持它.但是火狐浏覽器和所有基於開源 Rhino JavaScript 技術的系統都支持 E4X。
結束語
從這篇簡短的文章中可以看到,使用 E4X 可以簡化與 XML 相關的工作。Javascript 開發人員的主要障礙是不能以簡單高效的方式處理 XML 數據。Javascript 腳本語言是非常簡單和有序的,現在借助 E4X 改進後的功能,JavaScript E4X 解決了棘手的數據處理問題。嘗試一下吧!