翻译的一篇国外的XML in Flash,觉得这篇文章写的不错,和大家分享下,对原文有部分删减,其中也包含了本人的一些体会。
原文出处:
作者:jen dehaan
翻译:Liu21st
文章内容索引:
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标记必须是闭合的,意思是说假如你有个
标记,就必须有对应的
标记结尾,或者单独使用
。这也是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内容到对象实例中了。
手动追加的方式可以用:
users_xml.parseXML("
Liu21st"
;
如果你在Flash中trace(users_xml);你会得到下面的输出:
Liu21st
trace XML对象是个很有用的方法
还可以在申明XML对象的时候初始化数据,下面把两种方法比较下:
// 创建一个XML 类
var users_xml:XML = new XML();
users_xml.parseXML("
Liu21st"
;
trace(users_xml);
// 第二种创建方法
var users_xml:XML = new XML("
Liu21st"
;
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属性访问一个文本节点的值。如下面的:
// create and display an XML packet.
var users_xml:XML = new XML();
users_xml.parseXML( "
Liu21st"
;
trace( "packet:" +users_xml);
trace( "name:" +users_xml.firstChild.firstChild.nodeValue);
/* traces Liu21st */
如果在上面的代码中只使用一个firstChild,你会发现输出的结果是null,我们来尝试下不同的输出:
trace("a:"+users_xml.firstChild.firstChild.nodeValue);
//traces a:Liu21st
trace("b:"+users_xml.firstChild.nodeValue);
// traces b:null
trace("c:"+users_xml.nodeValue);
// traces c:null
trace("d:"+users_xml.firstChild);
// traces d:
Liu21st
trace("e:"+users_xml.firstChild.firstChild);
// traces e:Liu21st
现在你应该了解Flash中基本的XML访问方式,我们可以通过firstChild和nodeValue来遍历XML树的结构。
// create and display an XML packet.
var users_xml:XML = new XML();
users_xml.parseXML( "
Liu21st
计算机编程
深圳"
;
trace("packet:"+users_xml);
for (var i = 0; i
trace( "node " + i + ":" + users_xml.firstChild.childNodes[ i ].firstChild.nodeValue);
}
/* traces the following:
packet:
Liu21st
计算机编程
深圳
node 0:Liu21st
node 1:计算机编程
node 2:深圳
*/
上面的XML数据格式化查看为:
Liu21st
计算机编程
深圳
这个XML节点有些复杂,使用循环语句可以依次得到每个节点的值,因为childNodes属性是个数组。除了nodeValue属性外,还有两个属性nodeName和nodeType也可以处理XML数据。
使用nodeName属性,你可以访问节点名称,如name、occupation和city。nodeType就比较复杂些,它指明节点的类型:文本节点或XML元素。我们还记得前面用createElement 和 createTextNode 方法来创建XML数据,正是对应了不同节点类型。如果是XML元素(如
)则返回1,如果是文本节点(如Liu21st)则返回3。
XML不仅仅包含这些标记,你还可以给节点增加属性,看下面的例子:
分析XML的节点属性和之前类似:
// create and display an XML packet.
var users_xml:XML = new XML();
users_xml.parseXML( '
'
;
for (var i = 0; i
var thisNode:XMLNode = users_xml.firstChild.childNodes[ i ];
trace("node " + i + " (" + thisNode.nodeName+ "
:" + thisNode.attributes.value);
}
/* traces the following:
node 0 (name):Liu21st
node 1 (occupation):计算机编程
node 2 (city):深圳
*/
在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不存在或者遇到错误,会看到类似于下面的错误信息:
xml failed to load.
Error opening URL "file:///C|/Documents%20and%20Settings/
/somexmlfile.xml"
如果加载成功,会在输出面板中显示:
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文档
接下来,用下面的代码来输出
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 : };
你会看到下面的结果:
xml loaded successfully.
number of children:7
为了使得XML分析时不被这些whitespace干扰,可以设置ignoreWhite属性:
1 : external_xml.ignoreWhite = true;
输出结果如下:
xml loaded successfully.
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数据到远程脚本可以使用下面的代码:
XML.prototype.ignoreWhite = true;
var packet_xml:XML = new XML("
Liu21st
77"
;
var target_xml:XML = new XML();
packet_xml.xmlDecl = "";
packet_xml.sendAndLoad("
target_xml);
target_xml.onData = function(data) {
_root.myText.text = data;
};
这里引入了一些新的概念,第一行给每个XML对象设置了ignoreWhite属性,取代了为每个XML对象实例单独设置。接下来的两行创建了两个XML对象,第一个实例packet_xml 用来存放需要发送的数据信息,target_xml实例用来存放从服务器端返回的数据信息。
sendAndLoad使用 POST 方法将XML数据发送到指定的 URL,下载服务器的响应,然后将其加载到参数中定的 targetXMLobject 中。而send方法只是发送数据到服务器端,并不接收任何响应。这两个方法都非常有用,但有些区别,send方法会打开新的浏览器或者覆盖当前的浏览器页面,而sendAndLoad并不会打开任何浏览器窗口。
另外一个重要的概念是xmlDecl属性,它指定有关文档的 XML 声明的信息。我们知道Html的申明信息是:
而XML1.0的申明是
接下来的sendAndLoad方法就是和远端脚本交换数据了。
packet_xml.sendAndLoad("
target_xml);
其中的URL地址可以根据你的不同的服务器端脚本更换,在这里使用php、asp或cfm并不本质的区别,都是采用POST方法传递数据,不同的只是不同的脚本语言对POST数据的接收方式不同而已。
onData事件我们之前已经了解过了,可以用来保存服务器端的响应数据。
如果要使用send方法,可以换成下面的代码:
XML.prototype.ignoreWhite = true;
var packet_xml:XML = new XML("
Liu21st
77"
;
packet_xml.xmlDecl = "";
packet_xml.send("
"_blank"
;
这段代码要比之前简洁些,它的作用是以新窗口的方式打开一个指定的URL页面,对于需要跳转到某个页面的时候这个方法很有效。不同的是target_xml 参数不再需要,而是定义一个目标窗口,有效的参数还有:
_blank: 指定一个新窗口
_parent: 指定当前帧的父级
_self : 指定当前窗口中的当前帧,默认参数
_top: 指定当前窗口中的顶级帧
6. 接收XML数据从服务器端
要从上面的例子中接收并返回数据通过服务器端ColdFusion脚本可以使用下面的代码
<--- this is ColdFusion code, not ActionScript. --->
showdebugoutput="no">
.content />
file="#ExpandPath('./xmlpacket.xml')#"
output="#XMLPacket#"
addnewline="Yes" />
1
7. 使用 xmlconnector 分析XML
下面的内容仅适合FlashMX2004专业版,因为XMLConnector 组件FlashMX2004才引入。
下来会看到怎样通过改组件同步Blog(假设他有一个可用的公共XML)并在Flash表单中显示结果。下面这个例子使用了XMLConnector 组件链接一个远程的XML并在一个List组件中显示标题,但用户点击标题后,相应的文章描述会显示在TextArea组件中。因为使用的是xmlconnector组件,你只可以从简单的XML文件抓取内容,如果你使用WebServiceConnector 组件可以完成更多的功能。
是个很好的例子。
步骤一: 添加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项来显示不同的描述信息了。
我们还可以添加更多的组件来显示更多的绑定信息,例如显示作者和链接地址等
步骤八:完成测试
现在你可以完整的看到效果了,恭喜你成功了!你成功地同步了外部XML数据,并且显示在舞台的相关组件中,然而这一切你没有添加一行脚本代码。
范例演示:
在该演示中,为了做到开始就显示第一条文章的概要,我添加了部分代码:
1 : function bindingExecuted() {
2 : headlines_lc.selectedIndex = 0;
3 : headlines_lc.refreshDestinations();
4 : }
5 : headlines_lc.addEventListener("bindingExecuted", this);
源代码下载:[ up/1095930408.fla ]
8. 版本历史
1.0 November 26, 2003 Initial release.
1.1 November 27, 2003 Added section on XMLConnector.
1.2 June 15, 2004 Cosmetics.
昨天在翻译Flash中的XML使用方法(下)的时候后面部分涉及到数据绑定的使用,囫囵吞枣地学习一下,觉得不够清楚和透彻。从这篇开始把数据绑定的思路和使用方法详细描述下。
数据绑定其实涉及的方面也很多,可以简单的使用,也可以有更复杂的应用,我们先从什么是数据绑定和怎么使用开始。
1. 什么是数据绑定
数据绑定是FlashMX2004专业版的特性之一,是一种将组件相互连接起来的方式。可以将组件视为具有属性的简单黑箱。属性能让您将数据放进组件中并从中取出数据。可以简单的理解为“当组件 A 的属性 X 改变时,将新值复制到组件 B 的属性 Y”。
具体操作的时候,可以使用“组件检查器”面板的“绑定”选项卡在创作工具内添加、查看和删除数据绑定。
尽管数据绑定适用于任何组件,但它的主要用途是将 UI 组件连接到外部数据源(如 Web 服务和 XML 文档)。这些外部数据源是以带属性(可绑定到其他组件属性)的组件的形式提供的。“组件检查器”面板是 Flash MX Professional 2004 内用于数据绑定的主要工具。它包含一个“架构”选项卡(用于定义组件的架构)和一个“绑定”选项卡(用于在组件属性之间创建绑定)。
Macromedia Flash MX Professional 2004 提供了灵活的基于组件的体系结构和对象模型,用于连接到外部数据源、管理数据和将数据绑定到用户界面组件。数据绑定位于体系结构的数据管道层,提供了在组件属性之间共享数据的机制。管道集成了诸如格式器和编码器等对象,可以提供对组件间的数据传播方式的完全控制。
2. 使用数据绑定
可以使用“组件检查器”面板中的“绑定”选项卡在 Flash 创作环境中直观地创建和配置数据绑定,也可以使用 mx.data.binding 包中的类以编程方式创建和配置绑定。我们常用的是第一种方式,第二种方式我会在后面的文章中讲述。
因为数据绑定是一种交互性的,所以最简单的数据绑定都至少需要两个组件。下面我们拖入一个List组件和TextInput组件,分别命名为list和textInput。
注意:必须把组件拖动到时间轴的第一帧,因为只有当组件存在于主时间轴的第 1 帧、影片剪辑的第 1 帧或屏幕的第 1 帧中时,才支持在组件之间进行数据绑定。
如果你没有指定实例名,在进行绑定的时候系统会提示你输入实例名。
下面我们给List组件添加数据项,通过属性栏或者脚本设置都可以,这里直接在属性栏添加。
接下来,我们就要来创建数据绑定了。选择list组件,打开组件检查器,选择绑定栏。
点击添加绑定按钮,弹出添加绑定对话框,
会显示该组件所有的可用于绑定的属性,每个属性会显示名称和数据类型。我们注意到,每个属性的最左边有个箭头,分为几种类型:
-向左的箭头:这种属性的数据只能被发送
-向右的箭头:数据只能传入这种属性
-双向箭头:数据可以被发送或传入
在这个例子中,我们需要使用selectedItem属性,但是selectedItem属性是一个对象,并且有label和data属性,所以我们需要使用路径表达式来实现绑定。勾选绑定对话框下面的使用路径表达式,并输入label,确认就可以了。
现在已经绑定的list组件的selectedItem.label属性,但是绑定对象还没有设定,在组件检查器中选中bound to属性栏,在弹出窗口中设置为textInput组件的text属性就可以了。
这样,基本的数据绑定功能就实现了,我们来看下效果吧。
请注意我们没有手动添加任何一行代码。
源文件下载:[ up/1096002744.fla ]
3. 其它需要注意的地方
Flash Player 7 与 Flash Player 6 中数据绑定的比较
组件之间的绑定基于默认组件事件触发(例如,每次在数据网格或数据集中选择一条新记录时,都将触发数据网格和数据集的 selectedIndex 之间的绑定)。只要触发了该事件,绑定即会排入队列,以便尽快执行。但这会因您所使用的 Flash Player 版本而有所不同。如果发布到 Flash Player 7,绑定将立即执行。而如果发布到 Flash Player 的早期版本,绑定将排到下一帧的最开始。
注意:如果组件(例如,数据集)提供了自己的事件用于访问可能会与数据绑定不同步的数据,将绑定排到下一帧有可能会导致这些组件出现问题。但是,这些组件只能用于 Flash Player 7。我们建议您在使用数据绑定时发布到 Flash Player 7。