咖啡伴侶

          呆在上海
          posts - 163, comments - 156, trackbacks - 0, articles - 2

          ActionScript 中XML處理方法

          Posted on 2008-04-08 14:41 oathleo 閱讀(1617) 評論(0)  編輯  收藏 所屬分類: Flex

          今天我們來看看AS3中新的XML處理方法:E4X,直到現在,ECMA腳本語言規范(ECMA-262)--AscriptScript 3.0的核心基礎,并沒有提供任何的XML數據處理類或方法。AcriontScript之前的版本(從Flash 5中的ActionScript開始)有一些處理XML數據的類和方法,但是它們并不是基于ECMAScript標準的。

          新的ECMA腳本語言規范第4版草稿中定義了一系列新的處理XML數據的類和方法。這些類和方法的集合并命名為E4X("ECMAScript for XML"),ActionScript 3.0包括如下新的E4X類: XMLXMLListQNameNamespace

          E4X類的方法、屬性和操作的開法基于以下的目標:

          • 簡單--E4X盡可能的使得處理XML數據的代碼容易編寫并且易于理解。
          • 一致性--E4X的方法于Actionscript的其它部分協調一致。
          • 友好--實用非常好理解的操作符處理XML數據,如點號(.)。

          注意:為避免與E4X中的新的XML類沖突,原來ActionScript 2.0中的XML類在ActionScript 3.0被重命名為XMLDocument,為了向前兼容,在ActionScript 3.0中遺留下來的類--XML、XMLNode、XMLParser和XMLTag--被包含進了flash.xml包中。新的E4X類是核心類--使用它們不需要import任何包。

          初始化XML對象

          XML對象可以代表一個XML元素、屬性、注釋、處理指令或文本元素。在ActionScript 3.0中我們可以直接將XML數據賦值給變量:

          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>

          你也可以使用new 構造器來從XML數據文本創建一個XML對象實例:

          var myXML:XML = new XML("<order><item id='1'><menuName>burger</menuName><price>3.95</price></item></order>")
          

          如果XML數據不是格式完好的(如少了結束標簽),那么將會出現運行時錯誤。

          注意,你也可以將變量實例傳入XML數據中:

          var tagname:String = "item";
          var attributename:String = "id";
          var attributevalue:String = 5;
          var content:String = "Chicken";
          var x:XML = <{tagname} {attributename}={attributevalue}>{content}</{tagname}>;
          trace (x.toXMLString())
             // Output: <item id="5">Chicken</item>
          

          通常,我們的應用是從外部源導入XML數據,如web service或RSS feed,以下是一個從遠程URL導入XML數據的例子:

          var myXML:XML = new XML();
          var XML_URL:String = "http://www.example.com/Sample3.xml";
          //創建URLRequest。
          var myXMLURL:URLRequest = new URLRequest(XML_URL);
          //使用URLLoader導入數據。
          var myLoader:URLLoader = new URLLoader(myXMLURL);
          //添加事件監聽器,以在XML數據導入完成后處理XML數據。
          myLoader.addEventListener("complete", xmlLoaded);
          //導入完成后,創建使用導入的數據創建XML對象
          function xmlLoaded(evtObj:Event) {
                 var myXML:XML = XML(myLoader.data);
                 trace("Data loaded.");
          
          }
          

          為了演示代碼的清晰性,本文中的大部份示例都第1種直接使用文本的方法創建XML對象。

          E4X包含一些直觀的方法XML數據的操作符(如.和@:用于訪問屬性):

          //獲取第1個item的menuName值
          trace(myXML.item[0].menuName); // Output: burger
          //獲取第1個item的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添加新的子節點:

          var newItem:XML =
             <item id="3">
                 <menuName>medium cola</menuName>
                 <price>1.25</price>
             </item>
          
          myXML.appendChild(newItem);
          

          當然你也可以使用@和.操作符來更新數據:

          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數據

          你可以使用.(點號)和..操作符訪問XML對象的子節點,使用@操作符訪問某一節點的屬性。考慮以下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的子節點的XMLList對象,該XMLList包含兩個XML對象(兩個book節點)。

          對象x..lastName表示一個包含XML樹結構下部所有的lastName屬性的XMLList對象,該XMList包含兩個XML對象(兩個LastName屬性)。

          對象x.book.editor.lastName表示一個包含所有x對象的所有名稱為book的子節點的所有名稱為editor的子節點的所有lastName節點的XMLList對象,該XMLList只包含一個XML對象(值為"Case"的lastName屬性)。

          訪問父節點和子節點

          parent()方法返回XML對象的父節點。

          你可以使用子節點列表的順序索引值來訪問特定的子節點,例如,假定某一XML對象x有兩個名稱為book的子節點,你可以如下訪問它們:

          //第1個book節點
          x.book[0]
          //第2個book節點
          x.book[1]
          

          要訪問孫子節點,我們可以如下直接使用兒子和孫子節點的索引值來訪問:

          x.book[0].title[0]

          不過如果x.book[0]只有一個名稱為title的子節點的話,那么可以省略索引:

          x.book[0].title

          類似的,如果x對象只有一個book子節點,并且該book節點的子節點對象只有一個title對象,那么兩個索引值都可以省略:

          x.book.title

          注意,你也可以使用child()方法,直接使用名稱訪問特定的子節點:

          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數據

          我們可以使用特定的元素名稱和屬性值來定位到特定的元素考慮以下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節點
          x.employee.(lastName == "McGee") // The first employee node
          //lastName為“McGee”的employee對象的firstName節點,第1個employee節點的節點
          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子節點
          x.employee.(@id == 347).lastName
          //所有id屬性值大于347的employee對象列表
          x.employee.(@id > 300) // An XML list with both employee properties
          //所有position子節點值包含“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對象節點的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的所有屬性名稱,實際上就是個節點的索引值:

          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的所有節點:

          var total2:Number = 0;
          for each (var item:XML in myXML..item)
          {
            total2 += Number(item@quantity) * Number(item.price);
          }
          

          使用with語句

          我們可以使用with語句,來指明后續的屬性和節點值都是基于某一XML對象,前面的for each ... in示例代碼,使用with語句的代碼如下:

          var total:Number = 0;
          for each (var item in myXML..item)
          {
             with (item)
              {
                   //{內的屬性和節點對象都是基于item XML對象的,所有不需要使用item.來訪問。
                   total += Number(@quantity) * Number(price);
               }
          
          }
          trace(total);
          

          修改XML對象

          我們可以使用prependChild()方法或者appendChild()方法在XML對象的子節點列表的前面或者最后面添加節點:

          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()方法在特定的節點前面活著回后面添加節點:

          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>)
          

          注意,我們也可以在構造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[i]}>
                             <last>{names[i][0]}</last>
                             <first>{names[i][1]}</first>
                         </employee>
          
                     x = x.appendChild(newnode)
          
          }
          

          我們也可以使用=操作符來給XML對象節點賦值:

          var x:XML =
             <employee>
                 <lastname>Smith</lastname>
             </employee>
          
          x.firstname = "Jean";
          x.@id = "239";
          

          以上代碼將把XML對象X設置成如下:

          <employee id="239">
             <lastname>Smith</lastname>
             <firstname>Jean</firstname>
             </employee>
          

          我們也可以使用+和+=操作符來連結XMLList:

          var x1:XML = <a>test1</a>
          var x2:XML = <b>test2</b>
          var xList:XMLList = x1 + x2;
          xList += <c>test3</c>
          

          刪除XML對象

          E4X規范中定義有delete和deleteByIndex方法用來刪除特定的XML節點,但是在當前版本的ActionScript 3.0實現中,并沒有實現這兩個方法,所有我們不能直接使用這兩個方法,不過我們可以使用遍歷XML樹,剔除特定的節點,重新構造新的XML對象的方法來刪除某一特定節點,以下我們將刪除employee的lastname子節點:

          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函數有兩個參數,第1的參數是被刪除節點的父節點,第2的參數是被刪除節點的在父節點的子節點列表中索引值。先遍歷父節點的索引屬性,然后遍歷其所有的子節點,跳過我們要刪除的節點,然后將它們組合成新的XML對象返回。

          如果XML對象非常復雜,數據量必較大的話,以上刪除節點的實現方法效率是非常好低,所有正確的選擇還是使用E4X定義的刪除方法,不過這個功能要等到ActionScript 3.0的下一個測試版本才能夠實現。

          XML類型轉換

          我們可以將XML對象和XMLList對象轉換為字符串,同樣的,我們也可以將字符串轉換為XML對象和XMLList對象。順便,請記住所有的XML屬性值、名稱和文本值都是字符串。

          轉換XML和XMLList對象為字符串

          XML對象和XMLList對象都有有兩個成員方法:toString()和toXMLString()方法。toXMLString()方法返回包含所有標簽、屬性、命名空間聲明和XML對象內容的字符串,對與復雜的XML對象(包含有子元素),toString()方法的效果和toXMLString()方法的效果一樣,但是對與簡單的XML對象(只包含一個文本元素),toString()方法只返回元素的文本內容:

          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
          

          將文本字符串轉換為XML對象

          我們可以使用new構造方法從字符串創建一個XML對象

          var x:XML = new XML('<a>test<b>');

          但是如果我們試圖將一個非XML或者結構不完整的字符串轉換為XML對象,那么將會報運行時錯誤:

          var x:XML = new XML('<a>test'); // Throws an error

          從Internet讀取Rss Fead數據

          以下代碼將讀取本站的rss fead數據:

          <?xml version="1.0" encoding="utf-8"?>
            <mx:Application xmlns:mx="http://www.macromedia.com/2005/mxml" xmlns="*" creationComplete="doInit()">
            <mx:Script>
            <![CDATA[
              private function doInit():Void{
                getRssData("http://blog.eshangrao.com/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)

          注意,我們沒有直接使用節點名稱訪問節點(不知道為什么,如果使用item.title訪問title節點的話,返回是空的,可能跟我的RSS XML的中rdf指令有關,如果有朋友知道解決的辦法,請告訴我),而是使用了children()方法,該方法返回某一XML對象的所有子節點對象,

          主站蜘蛛池模板: 阿拉善右旗| 兴和县| 油尖旺区| 古浪县| 伊川县| 沙田区| 镇巴县| 阿勒泰市| 嘉峪关市| 碌曲县| 岳普湖县| 新郑市| 和顺县| 板桥市| 弋阳县| 海淀区| 保康县| 双流县| 灵丘县| 常德市| 庄浪县| 芜湖市| 新化县| 贵德县| 鄂尔多斯市| 甘孜县| 阜康市| 黄山市| 威信县| 左贡县| 韩城市| 奇台县| 白银市| 民和| 贵南县| 册亨县| 蓬安县| 永泰县| 克什克腾旗| 沈阳市| 泽普县|