Flash中的XML使用方法
文章内容索引:
1. XML介绍
2. 创建XML数据
3. 分析XML数据
4. 加载外部XML数据
5. 发送XML数据到服务器端
6. 接收XML数据从服务器端
7. 使用 xmlconnector 分析XML
8. 版本历史
1.XML介绍
今天,XML几乎成了因特网的基础。在某种特定的环境下甚至可以替代数据库,和允许用户聚合内容(在Blog界中已经非常普遍了)。
XML (全称可扩展标记语言:eXtensible Markup Language) 是一种标记语言,相比HTML有更加严格的规则。XML标记必须是闭合的,意思是说假如你有个<p>标记,就必须有对应的< /p>标记结尾,或者单独使用<p />。这也是XML满足Well-formed的基本要求。
Flash有很多方法可以和其它如ColdFusion, PHP, Perl, ASP, Java等语言来交互XML数据信息,一般可以通过
XML类的 load, send and sendAndLoad 方法或者FlashMX2004专业版中的XMLConnector类来接收和发送XML数据信息以及组件数据绑定。
2. 创建XML数据
创建一个XML对象非常简单,在脚本中添加下面的代码即可:
1 : var users_xml:XML = new XML();
注意上面的代码有使用一些技巧,其一就是变量的命名充分利用了FlashMX的代码提示功能,第二就是使用了强制类型申明(译者注:关于代码提示方面可参考本站的相关文章),在这里就不再赘述了。
下面就可以加载XML内容到对象实例中了。
手动追加的方式可以用:
1: users_xml.parseXML("<name>Liu21st</name>");
如果你在Flash中trace(users_xml);你会得到下面的输出:
1: <name>Liu21st</name>
trace XML对象是个很有用的方法
还可以在申明XML对象的时候初始化数据,下面把两种方法比较下:
1: // 创建一个XML 类
2: var users_xml:XML = new XML();
3: users_xml.parseXML("<name>Liu21st</name>");
4: trace(users_xml);
5:
6: // 第二种创建方法
7: var users_xml:XML = new XML("<name>Liu21st</name>");
8: trace(users_xml);
复杂一点的方法就是通过createElement, createTextNode 和 appendChild等操作添加XML数据,下面的方法创建和上面等效的XML数据:
1 : var users_xml:XML = new XML();
2 : users_xml.appendChild(users_xml.createElement("name"));
3 : users_xml.firstChild.appendChild(users_xml.createTextNode("Liu21st"));
4 : trace(users_xml);
下面就要来讨论如何取得XML类中的数据信息
3. 分析XML数据
我们很快就创建好了一个XML数据,但是分析XML数据却显得相对复杂多了,在分析XML数据之前你需要了解XML的一些名词,如:节点、子节点、父节点的概念和它们之间的关联。(译者注:关于这方面概念的讨论就不在这里浪费了,可能也没有必要)
要取得子节点的值并没有这么直接了当,我们首先要通过firstChild属性来访问父级节点的子级列表中的第一个子级,nodeValue属性访问一个文本节点的值。如下面的:
1: // create and display an XML packet.
2: var users_xml:XML = new XML();
3: users_xml.parseXML( "<name>Liu21st</name>" );
4: trace( "packet:" users_xml);
5:
6: trace( "name:" users_xml.firstChild.firstChild.nodeValue);
7: /* traces Liu21st */
如果在上面的代码中只使用一个firstChild,你会发现输出的结果是null,我们来尝试下不同的输出:
1: trace("a:" users_xml.firstChild.firstChild.nodeValue);
2: //traces a:Liu21st
3:
4: trace("b:" users_xml.firstChild.nodeValue);
5: // traces b:null
6:
7: trace("c:" users_xml.nodeValue);
8: // traces c:null
9:
10: trace("d:" users_xml.firstChild);
11: // traces d:<name>Liu21st</name>
12:
13: trace("e:" users_xml.firstChild.firstChild);
14:
现在你应该了解Flash中基本的XML访问方式,我们可以通过firstChild和nodeValue来遍历XML树的结构。
1: // create and display an XML packet.
2: var users_xml:XML = new XML();
3: users_xml.parseXML( "< user><name>Liu21st</name><occupation>计算机编程< /occupation> <city>深圳</city></user>" );
4: trace("packet:" users_xml);
5: for (var i = 0; i<users_xml.firstChild.childNodes.length; i ) {
6: trace( "node " i ":" users_xml.firstChild.childNodes[ i ].firstChild.nodeValue);
7: }
8:
9: /* traces the following:
10: packet: <user><name>Liu21st</name><occupation>计算机编程< /occupation> <city>深圳</city></user>
11: node 0:Liu21st
12: node 1:计算机编程
13: node 2:深圳
14: */
上面的XML数据格式化查看为:
1: <user>
2: <name>Liu21st</name>
3: <occupation>计算机编程</occupation>
4: <city>深圳</city>
5: </user>
这个XML节点有些复杂,使用循环语句可以依次得到每个节点的值,因为childNodes属性是个数组。除了nodeValue属性外,还有两个属性nodeName和nodeType也可以处理XML数据。
使用nodeName属性,你可以访问节点名称,如name、occupation和city。nodeType就比较复杂些,它指明节点的类型:文本节点或XML元素。我们还记得前面用createElement 和 createTextNode 方法来创建XML数据,正是对应了不同节点类型。如果是XML元素(如<name>)则返回1,如果是文本节点(如Liu21st)则返回 3。
XML不仅仅包含这些标记,你还可以给节点增加属性,看下面的例子:
1: <user>
2: <name value="Liu21st" />
3: <occupation value="计算机编程" />
4: <city value="深圳" />
5: </user>
分析XML的节点属性和之前类似:
1: // create and display an XML packet.
2: var users_xml:XML = new XML();
3: users_xml.parseXML( '<user><name value= "Liu21st" /><occupation value= "计算机编程" /><city value= "深圳" /></user>' );
4: for (var i = 0; i<users_xml.firstChild.childNodes.length; i ) {
5: var thisNode:XMLNode = users_xml.firstChild.childNodes[ i ];
6: trace("node " i " (" thisNode.nodeName "):" thisNode.attributes.value);
7: }
8:
9: /* traces the following:
10: node 0 (name):Liu21st
11: node 1 (occupation):计算机编程
12: node 2 (city):深圳
13: */
在FlashMX2004专业版中XML还可以通过XMLConnector 组件来加载、发送和分析,在后面会讲述。
4. 加载外部XML数据
加载外部的XML数据源可以使用XML类的load或sendAndLoad 方法。
1 : var external_xml:XML = new XML();
2 : external_xml.load( "somexmlfile.xml" );
3 : external_xml.onLoad = function (success:Boolean) {
4 : if (success) {
5 : trace( "xml loaded successfully." );
6 : } else {
7 : trace( "xml failed to load." );
8 : };
9 : }
如果外部XML不存在或者遇到错误,会看到类似于下面的错误信息:
1: xml failed to load.
2: Error opening URL "file:///C|/Documents and Settings/<bunch of folders>/somexmlfile.xml"
如果加载成功,会在输出面板中显示:
1: xml loaded successfully
我们需要使用onLoad事件来侦测何时XML加载完成,因为Flash是同步的,加载XML的同时并不会暂停影片的播放来等待响应。事实上在加载XML的开始swf文件仍然在继续播放。这个概念很重要,因为你要明白在加载XML文件完成之前是无法访问XML的节点和属性的,Flash会返回undefined。
另外一个类似的事件是onData事件,onData默认会调用onLoad,除非你重新定义了onData。
01 : var external_xml:XML = new XML();
02 : external_xml.load("somexmlfile.xml");
03 : external_xml.onData = function(data:String) {
04 : trace("XML packet loaded.");
05 : trace("packet:" data);
06 : this.onLoad(true);
07 : };
08 : external_xml.onLoad = function(success:Boolean) {
09 : if (success) {
10 : trace("xml loaded successfully.");
11 : } else {
12 : trace("xml failed to load.");
13 : }
14 : };
有一点需要注意的是onLoad和onData的参数并不相同。
要完全掌握XML,需要了解whitespace的概念(空格, tab键, 回车, 换行等),在Flash中分析的时候,这些whitespace依然会被XML类当作节点来分析,但这样并不是我们想要的。
下面是一个xml文档
1: <user>
2: <name value="Liu21st" />
3: <occupation value="计算机编程" />
4: <city value="深圳" />
5: </user>
接下来,用下面的代码来输出
01 : var external_xml:XML = new XML();
02 : external_xml.load( "somexmlfile.xml" );
03 : external_xml.onLoad = function(success:Boolean) {
04 : if (success) {
05 : trace( "xml loaded successfully." );
06 : trace(external_xml);
07 : trace( "number of children:" this.firstChild.childNodes.length);
08 : } else {
09 : trace( "xml failed to load." );
10 : }
11 : };
你会看到下面的结果:
1: xml loaded successfully.
2: <user>
3:
4: <name value="Liu21st" />
5:
6: <occupation value="计算机编程" />
7:
8: <city value="深圳" />
9:
10: </user>
11: number of children:7
为了使得XML分析时不被这些whitespace干扰,可以设置ignoreWhite属性:
1 : external_xml.ignoreWhite = true;
输出结果如下:
1: xml loaded successfully.
2: <user><name value="Liu21st" /><occupation value="计算机编程" /><city value="深圳" /></user>
3: number of children:3
注:如果觉得给每个XML对象设置ignoreWhite属性很麻烦,可以用:
1 : XML.prototype.ignoreWhite = true;
5. 发送XML数据到服务器端
使用XML类的send 或 sendAndLoad 方法可以发送XML数据到服务器端语言(php、asp、cf等)开发的远程页面,这样就可以从数据库存储和接收数据,以及充分发挥服务器端语言的优势。例如你有一个用Flash开发的游戏,通过构建XML数据包然后发送到服务器端脚本,就可以实现积分榜的功能,并把前10名的分数存储在数据库中。这并不是说XML是Flash和远程脚本交换数据的唯一解决方式,事实上,解决方法众多,包括使用LoadVars类、WebService和 XMLConnector 组件,甚至还可以使用Flash Remoting。
发送XML数据到远程脚本可以使用下面的代码:
1: XML.prototype.ignoreWhite = true;
2: var packet_xml:XML = new XML("<game><name>Liu21st</name><score>77</score></game>");
3: var target_xml:XML = new XML();
4: packet_xml.xmlDecl = "<?xml version=\"1.0\"";
5: packet_xml.sendAndLoad("http://localhost:8500/packetfromflash.cfm", target_xml);
6: target_xml.onData = function(data) {
7: _root.myText.text = data;
8: };
这里引入了一些新的概念,第一行给每个XML对象设置了ignoreWhite属性,取代了为每个XML对象实例单独设置。接下来的两行创建了两个XML对象,第一个实例packet_xml 用来存放需要发送的数据信息,target_xml实例用来存放从服务器端返回的数据信息。
sendAndLoad使用 POST 方法将XML数据发送到指定的 URL,下载服务器的响应,然后将其加载到参数中定的 targetXMLobject 中。而send方法只是发送数据到服务器端,并不接收任何响应。这两个方法都非常有用,但有些区别,send方法会打开新的浏览器或者覆盖当前的浏览器页面,而sendAndLoad并不会打开任何浏览器窗口。
另外一个重要的概念是xmlDecl属性,它指定有关文档的 XML 声明的信息。我们知道Html的申明信息是:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
而XML1.0的申明是
<?xml version="1.0" ?>
接下来的sendAndLoad方法就是和远端脚本交换数据了。
1: packet_xml.sendAndLoad("http://localhost:8500/packetfromflash.cfm", target_xml);
其中的URL地址可以根据你的不同的服务器端脚本更换,在这里使用php、asp或cfm并不本质的区别,都是采用POST方法传递数据,不同的只是不同的脚本语言对POST数据的接收方式不同而已。
onData事件我们之前已经了解过了,可以用来保存服务器端的响应数据。
如果要使用send方法,可以换成下面的代码:
1: XML.prototype.ignoreWhite = true;
2: var packet_xml:XML = new XML("<game><name>Liu21st</name><score>77</score></game>");
3: packet_xml.xmlDecl = "<?xml version=\"1.0\"";
4: packet_xml.send("http://localhost:8500/packetfromflash.cfm", "_blank");
这段代码要比之前简洁些,它的作用是以新窗口的方式打开一个指定的URL页面,对于需要跳转到某个页面的时候这个方法很有效。不同的是target_xml 参数不再需要,而是定义一个目标窗口,有效的参数还有:
_blank: 指定一个新窗口
_parent: 指定当前帧的父级
_self : 指定当前窗口中的当前帧,默认参数
_top: 指定当前窗口中的顶级帧
6. 接收XML数据从服务器端
要从上面的例子中接收并返回数据通过服务器端ColdFusion脚本可以使用下面的代码
1: <--- this is ColdFusion code, not ActionScript. --->
2: <cfsilent>
3: <cfsetting enablecfoutputonly="Yes"
4: showdebugoutput="no">
5:
6: <cfset XMLPacket = getHTTPRequestData( ).content />
7:
8: <cffile action="WRITE"
9: file="#ExpandPath('./xmlpacket.xml')#"
10: output="#XMLPacket#"
11: addnewline="Yes" />
12: </cfsilent>
13: <cfoutput><result>1</result></cfoutput>
7. 使用 xmlconnector 分析XML
下面的内容仅适合FlashMX2004专业版,因为XMLConnector 组件FlashMX2004才引入。
下来会看到怎样通过改组件同步Blog(假设他有一个可用的公共XML)并在Flash表单中显示结果。下面这个例子使用了XMLConnector 组件链接一个远程的XML并在一个List组件中显示标题,但用户点击标题后,相应的文章描述会显示在TextArea组件中。因为使用的是 xmlconnector组件,你只可以从简单的XML文件抓取内容,如果你使用WebServiceConnector 组件可以完成更多的功能。http://www.fullasagoog.com/webservice.cfm 是个很好的例子。
步骤一: 添加XMLConnector组件到舞台
XMLConnector组件是不可视组件,所以放的位置无所谓,在属性栏中设置实例名为xmlcon
步骤二:添加List和TextArea组件
分别拖动一个List和TextArea组件到舞台的合适位置,分别命名为headlines_ls 和description_txt
点击查看全图
步骤三:设置XmlConnector组件
在XMLConnector中输入链接的XML文件的URL地址,在这个例子,我使用了我的Blog,因此URL为
http://blog.liu21st.com/rss2.php,当然你可以使用其它的xml路径,改变direction属性为receive,因为这里不需要发送任何数据。
步骤四:导入XML Schema
这一部分似乎有点复杂,XMLConnector让你可以创建复杂的应用程序而不需要太多的脚本代码。让XMLConnector知道XML文件结构的唯一方法就是手动定义或外部导入XML schema ,比较方便的方式是导入外部的XML结构。
可以从这里右键另存xml文件作为你的结构: http://blog.liu21st.com/rss.php
保存到本地后,在XMLConnector的组件检查器中导入
点击查看全图
注意用红色框标注的位置,很多朋友找不到导入按钮。
选中resluts:xml后导入你要的xml文件,并把readonly属性设为true
步骤五:绑定XML结构到List和TextArea组件
添加第一个绑定,打开绑定选择窗口后选择item:array节点后选择确定,组件检查器面板中会显示添加了results.RDF.item 绑定项。
点击查看全图
设置Bound To 属性,会打开选择窗口,我们在这里选择List组件的dataProvider : Array 项
点击查看全图
第二个绑定项目我们选择item项下面的description项,面板中会显示results.RDF.item.[n].description
点击查看全图
我们把bound to属性选择为TextArea组件的text : String 项。
步骤六:触发XML文件
点击行为面板,添加数据->添加数据源,在弹出窗口中选择 XMLConnector
点击查看全图
点击查看全图
我们还可以直接在脚本窗口输入下面代码来替换上面的操作:
1 : this.xmlcon.trigger();
如果你的XML数据不是utf8格式数据,可能还需要添加下面的一行来确保正常显示:
1 : System.useCodepage = true;
步骤七:测试和调整
现在已经可以开始测试你的swf文件了,但是我们会发现List组件的label会比较乱,因为没有指定label显示字段,下面我们来调整下。
在绑定窗口中选择results.RDF.item,然后更改formatter属性为Rearrange Fields,在下面的formatter options属性弹出框中输入label=title,然后确定 。
我们再对results.RDF.item.[n].description绑定做些调整,描述信息默认总是显示第一个。因为Index for 'item' 属性设置为0,我们可以更改为List组件的selectedIndex : Number 项。
点击查看全图
这样,就会根据我们选择的List项来显示不同的描述信息了。
我们还可以添加更多的组件来显示更多的绑定信息,例如显示作者和链接地址等Emotion
步骤八:完成测试
现在你可以完整的看到效果了,恭喜你成功了!你成功地同步了外部XML数据,并且显示在舞台的相关组件中,然而这一切你没有添加一行脚本代码。
在该演示中,为了做到开始就显示第一条文章的概要,我添加了部分代码:
1 : function bindingExecuted() {
2 : headlines_lc.selectedIndex = 0;
3 : headlines_lc.refreshDestinations();
4 : }
5 : headlines_lc.addEventListener("bindingExecuted", this);
