AS3中新的XML處理方法 - E4X
AcriontScript之前的版本(從Flash 5中的ActionScript開始)有一些處理XML數(shù)據(jù)的類和方法,但是它們并不是基于ECMAScript標(biāo)準(zhǔn)的。
新的ECMA腳本語言規(guī)范第4版草稿中定義了一系列新的處理XML數(shù)據(jù)的類和方法。這些類和方法的集合并命名為E4X("ECMAScript for XML"),ActionScript 3.0包括如下新的E4X類: XML、XMLList、 QName和Namespace。 E4X類的方法、屬性和操作的開法基于以下的目標(biāo):
初始化XML對象 XML 對象可以代表一個XML元素、屬性、注釋、處理指令或文本元素。圩tem的id屬性值trace(myXML.item[0].@id); //Output:1 //獲取id屬性為2的item的menuName值trace(myXML.item.(@id==2).menuName); // Output: fries//獲取menuName為burger的item的price值trace(myXML.item.(menuName== "burger").price); // Output: 3.95 你也可以使用appendChild()方法給XML添加新的子節(jié)點: var newItem:XML = <item id="3"> <menuName>medium cola</menuName> <price>1.25</price> </item> myXML.appendChild(newItem); 當(dāng)然你也可以使用@和.操作符來更新數(shù)據(jù): myXML.item[0].menuName="regular burger"; myXML.item[1].menuName="small fries"; myXML.item[2].menuName="medium cola"; myXML.item.(menuName=="regular burger").@quantity = "2"; myXML.item.(menuName=="small fries").@quantity = "2"; myXML.item.(menuName=="medium cola").@quantity = "2"; 訪問XML數(shù)據(jù) 你可以使用.(點號)和..操作符訪問XML對象的子節(jié)點,使用@操作符訪問某一節(jié)點的屬性??紤]以下XML對象: var x:XML = <book ISBN="0942407296"> <title>Baking Extravagant Pastries with Kumquats</title> <author> <lastName>Contino</lastName> <firstName>Chuck</firstName> </author> <pageCount>238</pageCount> </book> <book ISBN="0865436401"> <title>Emu Care and Breeding</title> <editor> <lastName>Case</lastName> <firstName>Justin</firstName> </editor> <pageCount>115</pageCount> </book> </order> 對象x.book表示一個包含所有名稱為book的子節(jié)點的XMLList對象,該XMLList包含兩個XML對象(兩個book節(jié)點)。 對象x..lastName表示一個包含XML樹結(jié)構(gòu)下部所有的lastName屬性的XMLList對象,該XMList包含兩個XML對象(兩個LastName屬性)。 對 象x.book.editor.lastName表示一個包含所有x對象的所有名稱為book的子節(jié)點的所有名稱為editor的子節(jié)點的所有 lastName節(jié)點的XMLList對象,該XMLList只包含一個XML對象(值為"Case"的lastName屬性)。 訪問父節(jié)點和子節(jié)點 parent()方法返回XML對象的父節(jié)點。 你可以使用子節(jié)點列表的順序索引值來訪問特定的子節(jié)點,例如,假定某一XML對象x有兩個名稱為book的子節(jié)點,你可以如下訪問它們: //第1個book節(jié)點 x.book[0] //第2個book節(jié)點 x.book[1] 要訪問孫子節(jié)點,我們可以如下直接使用兒子和孫子節(jié)點的索引值來訪問: x.book[0].title[0]不過如果x.book[0]只有一個名稱為title的子節(jié)點的話,那么可以省略索引: x.book[0].title類似的,如果x對象只有一個book子節(jié)點,并且該book節(jié)點的子節(jié)點對象只有一個title對象,那么兩個索引值都可以省略: x.book.title 注意,你也可以使用child()方法,直接使用名稱訪問特定的子節(jié)點: var x.XML = <order> <book> <title>Dictionary</title> </book> </order> var childName:String = "book"; trace (x.child(childName).title) // Output: Dictionary 訪問屬性 我們使用使用@操作符訪問XMLNode屬性: var myXML:XML = <order> <item id=‘1‘> <menuName>burger</menuName> <price>3.95</price> </item> <item id=‘2‘> <menuName>fries</menuName> <price>1.45</price> </item> </order> //獲取第1個item的id屬性值 trace(myXML.item[0].@id);//Output:1 使用屬性或元素值過濾XML數(shù)據(jù) 我們可以使用特定的元素名稱和屬性值來定位到特定的元素考慮以下XML對象: var x:XML = <employeeList> <employee id="347"> <lastName>Zmed</lastName> <firstName>Sue</firstName> <position>Data analyst</position> </employee> <employee id="348"> <lastName>McGee</lastName> <firstName>Chuck</firstName> <position>Jr. data analyst</position> </employee> </employeeList> 以下是正確的訪問方法: //lastName為“McGee”的employee對象,第1個employee節(jié)點 x.employee.(lastName == "McGee") // The first employee node //lastName為“McGee”的employee對象的firstName節(jié)點,第1個employee節(jié)點的節(jié)點 x.employee.(lastName == "McGee").firstName // The firstName property of that node //lastName為“McGee”的id屬性 x.employee.(lastName == "McGee").@id // The value of the id attribute //所有id屬性值為347的employee對象列表 x.employee.(@id == 347) //id屬性值為347的employee對象的lastName子節(jié)點 x.employee.(@id == 347).lastName //所有id屬性值大于347的employee對象列表 x.employee.(@id > 300) // An XML list with both employee properties //所有position子節(jié)點值包含“analyst”的employee對象列表 x.employee.(position.toString().search("analyst") > -1) 使用for ... in和for each ... in 語句 ActionScript 3.0 包括了一個新用來遍歷XMLList對象的的for ... in語句和for each ...in語句。例如,考慮以下XML對象,myXML和myXML..item XMLList對象(包含兩個item XML對象節(jié)點的XML列表): var myXML:XML = <order> <item id=‘1‘ quantity=‘2‘> <menuName>burger</menuName> <price>3.95</price> </item> <item id=‘2‘ quantity=‘2‘> <menuName>fries</menuName> <price>1.45</price> </item> </order> for ... in語句可以讓我們遍歷XMLList的所有屬性名稱,實際上就是個節(jié)點的索引值: var total:Number = 0; for (var pname:String in myXML..item) { total += Number(myXML.item.@quantity[pname]) * Number(myXML.item.price[pname]); } for each ... in語句遍歷XMLList的所有節(jié)點: var total2:Number = 0; for each (var item:XML in myXML..item) { total2 += Number(item@quantity) * Number(item.price); } 使用with語句 我們可以使用with語句,來指明后續(xù)的屬性和節(jié)點值都是基于某一XML對象,前面的for each ... in示例代碼,使用with語句的代碼如下: var total:Number = 0; for each (var item in myXML..item) { with (item) { //{內(nèi)的屬性和節(jié)點對象都是基于item XML對象的,所有不需要使用item.來訪問。 total += Number(@quantity) * Number(price); } } trace(total); 修改XML對象 我們可以使用prependChild()方法或者appendChild()方法在XML對象的子節(jié)點列表的前面或者最后面添加節(jié)點: var x1:XML = <p>Paragraph 1</p> var x2:XML = <p>Paragraph 2</p> var x:XML = <body></body> x = x.appendChild(x1); x = x.appendChild(x2); x = x.prependChild(<p>Paragraph 0</p>); // x == <body><p>Paragraph 0</p><p>Paragraph 1</p><p>Paragraph 2</p></body> 使用insertChildBefore()方法或者insertChildAfter()方法在特定的節(jié)點前面活著回后面添加節(jié)點: var x:XML = <body> <p>Paragraph 1</p> <p>Paragraph 2</p> </body> var newNode:XML = <p>Paragraph 1.5</p> x = x.insertChildAfter(x.p[0], newNode) x = x.insertChildBefore(x.p[2], <p>Paragraph 1.75</p>) 注意,我們也可以在構(gòu)造XML對象的時候使用大括號({和})來引用變量: var ids:Array = [121, 122, 123]; var names:Array = [["Murphy","Pat"],["Thibaut","Jean"], ["Smith","Vijay"]] var x:XML = new XML("<employeeList></employeeList>"); for (var i:int = 0; i < 3; i++) { var newnode:XML = new XML(); newnode = <employee id={ids}> <last>{names[i][0]}</last> <first>{names[i][1]}</first> </employee> x = x.appendChild(newnode) } 我們也可以使用=操作符來給XML對象節(jié)點賦值: var x:XML = <employee> <lastname>Smith</lastname> </employee> x.firstname = "Jean"; x.@id = "239"; 以上代碼將把XML對象X設(shè)置成如下: <employee id="239"> <lastname>Smith</lastname> <firstname>Jean</firstname> </employee> 我們也可以使用+和+=操作符來連結(jié)XMLList: var x1:XML = <a>test1</a> var x2:XML = <b>test2</b> var xList:XMLList = x1 + x2; xList += <c>test3</c> [i]刪除XML對象 E4X 規(guī)范中定義有delete和deleteByIndex方法用來刪除特定的XML節(jié)點,但是在當(dāng)前版本的ActionScript3.0實現(xiàn)中,并沒有實 現(xiàn)這兩個方法,所有我們不能直接使用這兩個方法,不過我們可以使用遍歷XML樹,剔除特定的節(jié)點,重新構(gòu)造新的XML對象的方法來刪除某一特定節(jié)點,以下 我們將刪除employee的lastname子節(jié)點: private function deleteByIndex(xmlNode:XML,index:Number):XML{ var newStr:String=‘‘; newStr+=‘<‘+xmlNode.localName(); for each (var att:XML in xmlNode.attributes()){ newStr+=‘ ‘+att.localName()+‘="‘+att.toString()+‘"‘; } newStr+=‘>‘; var i:Number=0; for each(var node:XML in xmlNode.children()){ if(i!=index) newStr+=node.toXMLString(); i++; } newStr+=‘</‘+xmlNode.localName()+‘/>‘; return new XML(newStr); } var myXML:XML= <employee id="239"> <lastname>Smith</lastname> <firstname>Jean</firstname> <address> <city>shangrao</city> <load>daihu</load> <no>5</no> </address> </employee> myXML=deleteByIndex(myXML,0); 以上的deleteByIndex函數(shù)有兩個參數(shù),第1的參數(shù)是被刪除節(jié)點的父節(jié)點,第2的參數(shù)是被刪除節(jié)點的在父節(jié)點的子節(jié)點列表中索引值。先遍歷父節(jié)點的索引屬性,然后遍歷其所有的子節(jié)點,跳過我們要刪除的節(jié)點,然后將它們組合成新的XML對象返回。 如果XML對象非常復(fù)雜,數(shù)據(jù)量必較大的話,以上刪除節(jié)點的實現(xiàn)方法效率是非常好低,所有正確的選擇還是使用E4X定義的刪除方法,不過這個功能要等到ActionScript 3.0的下一個測試版本才能夠?qū)崿F(xiàn)。 XML類型轉(zhuǎn)換 我們可以將XML對象和XMLList對象轉(zhuǎn)換為字符串,同樣的,我們也可以將字符串轉(zhuǎn)換為XML對象和XMLList對象。順便,請記住所有的XML屬性值、名稱和文本值都是字符串。 轉(zhuǎn)換XML和XMLList對象為字符串 XML 對象和XMLList對象都有有兩個成員方法:toString()和toXMLString()方法。toXMLString()方法返回包含所有標(biāo) 簽、屬性、命名空間聲明和XML對象內(nèi)容的字符串,對與復(fù)雜的XML對象(包含有子元素),toString()方法的效果和toXMLString() 方法的效果一樣,但是對與簡單的XML對象(只包含一個文本元素),toString()方法只返回元素的文本內(nèi)容: var myXML:XML = <order> <item id=‘1‘ quantity=‘2‘> <menuName>burger</menuName> <price>3.95</price> </item> <order> trace(myXML.item0.menuName.toXMLString()) // Output: <menuName>burger</menuName> trace(myXML.item0.menuName.toString()) // Output: burger 將文本字符串轉(zhuǎn)換為XML對象 我們可以使用new構(gòu)造方法從字符串創(chuàng)建一個XML對象 var x:XML = new XML(‘<a>test<b>‘);但是如果我們試圖將一個非XML或者結(jié)構(gòu)不完整的字符串轉(zhuǎn)換為XML對象,那么將會報運行時錯誤: var x:XML = new XML(‘<a>test‘); // Throws an error從Internet讀取Rss Fead數(shù)據(jù) 以下代碼將讀取本站的rss fead數(shù)據(jù): <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.macromedia.com/2005/mxml" xmlns="*" creati> <mx:Script> <![CDATA[ private function doInit():Void{ getRssData("http://blog./rss.php",ta_view); } public function getRssData(url:String, outTxt:TextArea):Void { private var myXMLURL:URLRequest = new URLRequest(url); private var myLoader:URLLoader = new URLLoader(myXMLURL); myLoader.addEventListener("complete", xmlLoaded); } private function xmlLoaded(event:Event):Void{ ta_view.text=‘load ok‘; var myLoader:URLLoader = URLLoader(event.target); XML.ignoreProcessingInstructions=false; var myXML:XML =new XML(myLoader.data); private var outStr:String = ""; for each (var item:XML in myXML.children()) { if(item.localName()==‘item‘){ outStr += "<p><b>" + item.children()0.toString() + ":</b></p><p>"; outStr += item.children()6.toString() ; outStr += " <br/><a href=‘" + item.children()1.toString(); outStr += "‘><font color=‘#008000‘>More...</font></a></p>"; } } //ta_view.text=myXML.toString(); ta_view.htmlText = outStr; } ]]> </mx:Script> <mx:Canvas width="100%" height="100%"> <mx:TextArea id="ta_view"> <mx:layoutConstraints> <mx:EdgeAnchor bottom="10" top="10" left="10" right="10"/> </mx:layoutConstraints> </mx:TextArea> </mx:Canvas> </mx:Application> 運行示例(FlashPlayer8.5 required) 注 意,我們沒有直接使用節(jié)點名稱訪問節(jié)點(不知道為什么,如果使用item.title訪問title節(jié)點的話,返回是空的,可能跟我的RSSXML的中 rdf指令有關(guān),如果有朋友知道解決的辦法,請告訴我),而是使用了children()方法,該方法返回某一XML對象的所有子節(jié)點對象, 獲取更多AS3中E4X類的使用信息,請查看Adobe在線文檔,詳細(xì)API參考:Adobe Flex 2 API文檔 源至:http://blog./index.php/2006/01/04/164-flex2-actionscript3xml-e4x |
|