(转)flex 数据基础-使用XML和XMLList
flex 数据基础-使用XML和XMLList
2010-12-15 11:05
本文引自“民工甲”的文章: http://hi.baidu.com/diwu0510/blog/item/eb985ffb7248cb989f514653.html
flex的一个特性是数据驱动。这么说不太清楚,举个例子吧,在网页里做一个数据表格,要先画好表格结构然后把数据填进去,而在flex里则是为datagrid指定一个数据源,数据源的结构决定了datagrid的呈现样式。很多时候数据源是XML和XMLList充当的,所以了解XML和XMLList还是有很有必要的。
一般情况下,由数据端语言生成XML或XMLList提供给Flex,由Flex直接使用或转换成ArrayCollection展现数据。
那么XML和XMLList有什么区别呢,很简单,看是否含有根节点。举例来说:
<root>
<node type="student" name="学生一">
<node type="student" name="学生二">
<node type="teacher" name="老师一">
</root>
这就是一个典型的XML,其中<root>是根节点,<node>是子节点。type,name是属性名,等号右边是属性值。而
<node type="student" name="学生一" />
<node type="student" name="学生二" />
<node type="teacher" name="老师一" />
这一部分就是一个XMLList。
好了,知道了什么是XML和XMLList,下面看怎么使用他们。
1、使用AS创建XML
前面的代码不罗嗦,直接看script里的
<mx:Script>
<![CDATA[
Private var myData:XML;
private function initApp():void
{
myData = <root>
<node type="student" name="小花" />
<node type="student" name="小龙" />
<node type="student" name="小刚" />
</root>
}
]]>
</MX:Script>
注意一下,这是比较基础的flex特性,全局变量可以在函数体外定义,但实例话对象并赋值这个过程必须在函数体内进行,不然会报错说变量未定义。用上面的代码举例:
Private var myData:XML = new XML();
myData = <root>
……
</root>
这样写代码,OK,保存的时候就会提示变量未定义。创建一个function,在函数体内为myData赋值才是正确的。
其实也可以在声明变量的时候直接赋值,也不会报错,如下:
Private var myData:XML = <root>
……
</root>
在函数内调用myData也不会任何问题。
ok,言归正传,我们在initApp()这个函数里为myData赋值,也就是说必须运行initApp()这个函数才能使用,为了能自动为myData赋值,还需要在windowedApplication标签加入creationComplete="initApp()",作用是在程序初始化结束后会执行initApp()这个函数。
另外,这种方式只能定义XML,既必须有根节点,不能定义XMLList。
除了直接给XML变量赋值外,还可以使用构造函数,如下:
<mx:Script>
<![CDATA[
private var myData:XML;
private function initApp():Void
{
var myStr:String = "<root>
……
</root>"
myData = new XML(myStr);
}
]]>
</mx:Script>
这种形式要注意下XML中的引号要换成单引号。
2、用标签创建XML/XMLList
废话不说,直接看标签代码
<mx:XML id="myData">
<root>
<node type=……
</root>
</mx:XML>
注意啊, 在flex4里,直接插入这个标签是会报错的,正确的做法应该是在<mx:XML>外增加一个父标签<fx:Declarations>。
同样的定义XMLList,只是没有<root>标签而已,不啰嗦。
3、输出XML某一类节点
非常简单,,可以直接使用点语法,看例子:
假设有这样一个XML,要取节点名为girl的子节点组成的XMLList,如下:
private var myData:XML = <student>
<boy name="小刚"/>
<boy name="小刚"/>
<girl name="小花"/>
<girl name="小兰"/>
</student>
private var girls:XMLList ;
private function initApp():Void
{
girls = myData.girl;
trace(girls);
}
注意这个地方,如果名为girl的节点只有一个,系统会报错,后面会解释。
XML对象跟节点相关的功能总结下,简单,不多解释,记住就好:
1) 获取全部节点 myData.elements("*")
2) 按节点名称获取节点 myData.elements("node")
3) 获取节点下的所有所有节点 myData.node[0].elements() 第一个node节点下的所有内容,比如说:
<root>
<node>
<child name="john"/>
<childe name="Tom"/>
</node>
</root>
显示的就是
<child name="john"/>
<childe name="Tom"/>
4) 单条数据的情况,注意,下面一段呼应上面的红色内容:
myData2 = <root>
<boy name="数据2"/>
</root>
trace(myData2.elements()) 怎么显示呢?嘿嘿,没错,就是啥都没有,为啥?这里说一下Flex的一个默认的情况,如果XML元素只有一个节点,那么Flex默认输出其节点内容而不是把节点整个显示出来,而结点内容为空,自然就啥都显示不出来了。下面的情况会有所不同:
myData3 = <root>
<boy name="数据2">这个节点有内容了</boy>
</root>
trace(myData3.elements()); 什么情况呢?没错,就是会显示 “这个节点有内容了”这行字。
是不是单行节点无法显示整个XMLList内容呢?当然不是,只要这样就可以了:
trace(myData2.elements().toXMLString());
5) 获取下级节点的个数 myData.elements().length()
这里这么写也没什么问题,不过事实上没这么简单。举个例子吧:
<root>
<people type="student">
<boy name="小刚"/>
<girl name="小花"/>
</people>
<people type="teacher" name="老师"/>
<class name="小5班"/>
</root>
好,如果要查看root下所有二级子节点的个数,myData.elements().length()没有问题,显示的值为3;
如果要获取root下所有后代的个数,就应该这样写 myData.descendants("*").length(),显示值为5;
注意啊,这个descendants("*")返回的也是XMLList,不过返回的值很有意思,没事儿可以测试下,这里只说length相关,就不啰嗦了。
6) 获取节点名字 myData.elements()[0].name() 不解释
获取节点内容 myData.elements()[0] 也可以用myData.elements()[0].text();
7) 获取父节点 节点名.parent() myData.element[0].childe[0].parent().@name 其实就是element[0]的name属性
8)取得属性值和属性名 myData.node[0].@name myData第一个节点的属性name的值等价于myData.node[0].attribute("name"),读取全部的值myData.node[0].atttibute("*")
9) 对XML按条件过滤 myData.elements()[0].(@name=="Tom"),注意如果myData下的子孙节点有的没有@name这个属性,将取不到任何信息。
10)添加节点组合生成XML
myData.appendChild(<node ……/>),这是在最后添加一个节点
myData.prependChild(<node....../>),这是在最前面田间一个节点
myData.insertChildAfter(myData.node[0],<node ..../>),这是在第一个节点后面添加
myData.insertChildBefore(myData.node[0],<node ..../>),这是在第一个节点前面添加
myData.newElement=<node ....../>
myData.newElement=<node ......>内容</node>
myData.node[1] = "aaa" 有这个节点就修改节点的内容,没有的话就创建一个节点
节点名字可以由变量组成 var bl:int=2; myData["node"+bl] = "name";
写一个用数组构成XML的例子:
private function buildXML():Void
{
var ids:Array = [121,122,123];
var names:Array = [["a1","a2"],["b1","b2"],["c1","c2"]];
var arrData:XML = new XML("<root></root>");
for(var i:int=0; i<ids.length;i++)
{
var node:XML = new XML();
node = <employee id={ids[i]}>
<last>{names[i][0]}</last>
<first>{names[i][0]}</first>
</employee>
arrData.appendChild(node);
}
}
11) 添加、修改节点属性
myData.node[1].@name="aaa" 有name属性则属性值改为aaa,没有就创建一个name属性
也可以动态添加属性,比如说用循环
for(var i:int=0; i<3; i++)
{
myData.node[1].@["name"+i] = "tom";
}
12) 删除节点和属性
删除节点 delete myData.node[1]; 注意,这里可以删除多个节点
删除属性 delete myData.node[1].@name 注意,这里同样可以删除多个
删除所有属性,需要使用循环
var attri:XMLList = myData.node.@*;
4、读取外部XML/XMLList
1)使用XML标签 <mx:XML source="data/xml.xml" id="myData">
2)使用URLLoader,在Action中加载
import flash.net.URLLoader;
import flash.net.URLRequest;
private function loadXML():Void
{
var request:URLRequest = new URLRequest("data/xml.xml");
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE,completeHander);
loader.load(request);
}
private function completeHander(e:Event):Void
{
var myData2:XML = new XML(e.target.data);
}
如果在变异过程中出现错误提示“无法访问本地资源....”,需要设置编译参数:-use-netwrok = false
3)使用HTTPService,看代码:
import mx.rpc.events.ResultEvent;
private function initApp():Void
{
ser.send();
}
private function resultHandler(e:ResultEvent):woid
{
var myData3:XML = e.result asXML;
trace(myData3);
声明HTTPService标签
<mx:HTTPService id="ser" url="data/xml.xml" result="resultHandler(event)" resultFormat="e4x"/>
}