最近使用Flex+As3做了一个类似于XML解析的小程序,现将使用Flex解析XML文件的方法总结如下(本片文章好多地方参考于http://hdxiong.iteye.com/blog/580136):
首先带解析的XML文件:
- <WorkFlow>
- <Route ID="17" Name="" FromElementID="7" ToElementID="4"/>
- <Route ID="16" Name="" FromElementID="6" ToElementID="4"/>
- <Route ID="15" Name="" FromElementID="1" ToElementID="3"/>
- <Route ID="14" Name="" FromElementID="12" ToElementID="2"/>
- <Route ID="13" Name="" FromElementID="4" ToElementID="12"/>
- <Route ID="11" Name="" FromElementID="5" ToElementID="4"/>
- <Route ID="10" Name="" FromElementID="3" ToElementID="5"/>
- <Route ID="9" Name="" FromElementID="3" ToElementID="6"/>
- <Route ID="8" Name="" FromElementID="3" ToElementID="7"/>
- <Node type="BeginNode" ID="1" x="457" y="55">
- <Name>开始</Name>
- </Node>
- <Node type="EndNode" ID="2" x="469" y="666">
- <Name>结束</Name>
- </Node>
- <Node type="ForkNode" ID="3" x="465" y="190">
- <Name>分支</Name>
- </Node>
- <Node type="JoinNode" ID="4" x="455" y="464">
- <Name>合并</Name>
- </Node>
- <Node type="TaskNode" ID="5" y="330" x="458" taskNum="2">
- <Name>照明</Name>
- <NodeTyle>收费</NodeTyle>
- <task name="开灯" taskid="1"/>
- <task name="加速" taskid="2"/>
- </Node>
- <Node type="WorkNode" ID="6" y="327" x="637">
- <Name>充电</Name>
- <NodeTyle>收费</NodeTyle>
- </Node>
- <Node type="TaskNode" ID="7" y="327" x="301" taskNum="1">
- <Name>加亮</Name>
- <NodeTyle>收费</NodeTyle>
- <task name="调大瓦数" taskid="1"/>
- </Node>
- <Node type="WorkNode" ID="12" y="562" x="465">
- <Name>业务</Name>
- <NodeTyle>归档</NodeTyle>
- </Node>
- </WorkFlow>
下面详述XML文件的解析过程:
1.文件的读取
文件的读取使用的是Flex的FileReferenceList和FileReference类。简要叙述如下:
-
-
-
- private var fr:FileReference= new FileReference();
- fr.addEventListener(Event.COMPLETE,onFileComplete);
- private function OpenFile():void
- {
- var fileRefList:FileReferenceList = new FileReferenceList();
- var allFilter:FileFilter = new FileFilter("xml (*.xml)", "*.xml");
- if (fr.browse(new Array(allFilter))) {
- fr.addEventListener(Event.SELECT,onFileSelect);
- }
- }
-
- private function onFileComplete(event: Event):void
- {
- var xml:XML=new XML(fr.data.toString());
- this.myDrawBoard.Clear();
- this.myDrawBoard.ParseFromXml(xml);
- }
- private function onFileSelect(event: Event):void {
- fr.load();
- }
2.xml文件的解析
xml文件的解析分有多种基本操作,现总结如下:
首先解析过程中我们会用到如下几个类:
import flash.system.ApplicationDomain;//由于解析的内容包含我自己封装的节点类的信息所以需要读取全局类域信息
XMLList类,用于实现把XML对象作为数组的方式读取,方便的进行for each操作。
这里简单的按照以下例子说明:
XML文件说明:
2.1、Load a XML(这部分不是我程序中使用的方法)
- var xmlLoader:URLLoader = new URLLoader();
- var xmlData:XML = new XML();
-
- xmlLoader.addEventListener(Event.COMPLETE, LoadXML);
-
- xmlLoader.load(new URLRequest("http://www.kirupa.com/net/files/sampleXML.xml"));
-
- function LoadXML(e:Event):void {
- xmlData = new XML(e.target.data);
- trace(xmlData);
- }
运行结果:
2.2、Access All Specified element of the XML Directly(直接遍历XML对象的所有指定子节点)
- function ParseBooks(bookInput:XML):void {
- trace("XML Output");
- trace("------------------------");
- trace(bookInput.Book);
- }
输出结果如下:
XML Output
------------------------
<Book ISBN="0553212419">
<title>Sherlock Holmes: Complete Novels and Stories, Vol 1</title>
<author>Sir Arthur Conan Doyle</author>
</Book>
<Book ISBN="0743273567">
<title>The Great Gatsby</title>
<author>F. Scott Fitzgerald</author>
</Book>
<Book ISBN="0684826976">
<title>Undaunted Courage</title>
<author>Stephen E. Ambrose</author>
</Book>
<Book ISBN="0743203178">
<title>Nothing Like It In the World</title>
<author>Stephen E. Ambrose</author>
</Book>
另外如果我们想要读取节点的某个特殊子节点,例如我们只想获得每本书的Author,可按如下操作:
- function ParseBooks(bookInput:XML):void {
- trace("XML Output");
- trace("------------------------");
- trace(bookInput.Book.author);
- }
我们也可以初始化一个XMLList对象来遍历特殊子节点,代码如下:
- function ParseBooks(bookInput:XML):void {
- trace("XML Output");
- trace("------------------------");
-
- var authorList:XMLList = bookInput.Book.author;
-
- for each (var authorElement:XML in authorList) {
- trace(authorElement);
- }
- }
运行结果如下:
XML Output
------------------------
<author>Sir Arthur Conan Doyle</author>
<author>F. Scott Fitzgerald</author>
<author>Stephen E. Ambrose</author>
<author>Stephen E. Ambrose</author>
2.3、Access All Specified element of the XML indirectly
XMLList类对象支持许多数组对象支持的操作,另外注意到我们过滤掉XML类的子节点的返回值对象都是通过XMLList来实现的,所以我们可以用类似于遍历数组的方式来访问XML的子节点信息。
代码如下:
- for (var i:int = 0; i < authorList.length(); i++)
- {
- var authorElement:XML = authorList[i];
- trace(authorElement);
- }
运行结果与上面相同。
2.3、Calling all Child (获得节点的所有子节点属性)
function ParseBooks(bookInput:XML):void {
- trace("XML Output");
- trace("------------------------");
-
- var bookChildren:XMLList = bookInput.Book.children();
-
- for each (var bookInfo:XML in bookChildren) {
- trace(bookInfo);
- }
- }
运行结果如下(与之前有所不同):
XML Output
------------------------
Sherlock Holmes: Complete Novels and Stories, Vol 1
Sir Arthur Conan Doyle
The Great Gatsby
F. Scott Fitzgerald
Undaunted Courage
Stephen E. Ambrose
Nothing Like It In the World
Stephen E. Ambrose
在上述代码中我们可以通过将trace(bookinfo)改为trace(bookinfo.name)来获得节点类型,从而输出如下:
XML Output
------------------------
title
author
title
author
title
author
title
author
更复杂一点的操作:
- function ParseBooks(bookInput:XML):void {
- trace("XML Output");
- trace("------------------------");
-
- var bookChildren:XMLList = bookInput.Book.children();
-
- for each (var bookInfo:XML in bookChildren) {
- if (bookInfo.name() == "author") {
- trace(bookInfo);
- }
- }
- }
输出结果(即只输出所有author的节点的内容)。
2.4、Reading attributes(读取节点属性值)
到目前为止我们都是在处理节点(元素)以及节点的嵌套信息。节点的属性值与节点的嵌套信息不同之处在于,节点属性值直接保存在节点的内部。所以读取节点的属性值操做与处理其他节点信稍有不同。
在我们的例子XML文件中,节点的属性信息即book节点的ISBN属性的位置是直接位于book节点内部的。我们用以下AS代码来过滤book节点的ISBN信息。
- function ParseBooks(bookInput:XML):void {
- trace("XML Output");
- trace("------------------------");
-
- var bookAttributes:XMLList = bookInput.Book.attributes();
-
- for each (var bookISBN:XML in bookAttributes) {
- trace(bookISBN);
- }
- }
让我们把注意力集中到重点的代码上:
var bookAttributes:XMLList = bookInput.Book.attributes();
为了读取节点的属性值我们调用了attribute函数,它的返回值是一个XMLList对象,输出结果就如同我们之前调用children()函数来访问嵌套信息时输出的是真正的信息值。
有一点需要注意的是,在我们的示例XML文件中所有的node节点都只有一个属性值,在实际应用中如果一个节点有多个属性值又该怎么过滤特有的属性节点呢,有下面两种方式:
方法1:
- function ParseBooks(bookInput:XML):void {
- trace("XML Output");
- trace("------------------------");
-
- var bookAttributes:XMLList = bookInput.Book.attributes();
-
- for each (var bookISBN:XML in bookAttributes) {
- if (bookISBN.name() == "ISBN") {
- trace(bookISBN);
- }
- }
- }
方法2:
- function ParseBooks(bookInput:XML):void {
- trace("XML Output");
- trace("------------------------");
-
- var bookAttributes:XMLList = bookInput.Book.attribute("ISBN");
-
- for each (var bookISBN:XML in bookAttributes) {
- trace(bookISBN);
- }
- }
2.5、Filetering Node Values(过滤节点信息)
在As3中我们可以过滤出我们自己真正感兴趣的XML信息,比如我们只想找出示例XML文件中作者名是Stephen E. Ambrose 的节点信息,我们可以使用如下代码:
function ParseBooks(bookInput:XML):void {
- trace("XML Output");
- trace("------------------------");
-
- var authorList:XMLList = bookInput.Book.(author == "Stephen E. Ambrose");
- trace(authorList);
- }
输出结果如下:
XML Output
------------------------
<Book ISBN="0684826976">
<title>Undaunted Courage</title>
<author>Stephen E. Ambrose</author>
</Book>
<Book ISBN="0743203178">
<title>Nothing Like It In the World</title>
<author>Stephen E. Ambrose</author>
</Book>
进一步,如果我们只想提取出Stephen E. Ambrose 所写的书的Title的话,我们可以使用以下代码:
var authorList:XMLList = bookInput.Book.(author == "Stephen E. Ambrose").title;
2.6、Fuiltering Attribute Information
通过节点信息来提取特定节点数据的话只有一点不同,为了提取出一组特定ISBN的节点信息我们只需使用@操作符,具体代码如下:
- function ParseBooks(bookInput:XML):void {
- trace("XML Output");
- trace("------------------------");
-
- var bookList:XMLList = bookInput.Book.(@ISBN == "0743203178").title;
- trace(bookList);
- }