AS3的原生XML工具还凑合,但是有时候需要把自己定义的XML数据解析成ActionScript3的Object。
废话不说,代码:
package com.linkage.cmp.serialization.xml{
/**
* 静态工具类,将xml对象或者字符串转换成AS3对象。
* 注意:参数必须是标准单根结构的XML对象或者字符串,如果传递的参数不是合法的XML格式,将会抛出解析异常。
* @author 章小飞 [email protected]
* @since 2011-01-18
*/
public class XmlParser{
/**
* 私有:解析过程中内部使用的堆栈
*/
private static var stack:Array=[];
public function XmlParser(){
throw new Error("不能实例化工具类XmlParser");
}
public static function parse(obj:*):*{
var result:Object=null;
try{
if(!obj){
return result;
}
if(!(obj is XML)){
obj=new XML(obj.toString());
}
//清空堆栈
stack=[];
doParse(obj);
result=stack[0];
}catch(e:Error){
throw new Error("Xml2Obj无法解析所提供的XML数据");
}
return result;
}
/**
* 递归解析,前序遍历
*/
private static function doParse(root:XML):void{
var obj:Object={name:root.name().toString(),children:[]};
stack.push(obj);
//解析直接属性
var attrLen:int=root.attributes().length();
for(var j:int=0;j<attrLen;j++){
var attr:XML=root.attributes()[j];
obj[attr.name().toString()||"_temp"]=attr.toString();
}
//解析子标签
var len:int=root.children().length();
if(len){
for(var i:int=0;i<len;i++){
var sub:XML=root.children()[i];
var subLen:int=sub.children().length();
if(subLen){
doParse(sub);
var temp:Object=stack.pop();
var temp2:Object=stack[stack.length-1];
temp2.children.push(temp);
}else{
var top:Object=stack[stack.length-1];
delete top.children;
// top[top.name]=sub.toString();
// delete top.name;
top.value=sub.toString();
}
}
}
}
}
}
下面是测试用例:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<s:layout>
<s:BasicLayout/>
</s:layout>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import com.linkage.cmp.serialization.json.JSON;
import com.linkage.cmp.serialization.xml.XmlParser;
private function test():void{
//第一种用法,直接解析XML对象,可以嵌套任意深度
var xml:XML=<root>
<name>大漠穷秋</name>
<age>25</age>
<skills>
<skill>AS3</skill>
<skill>C++</skill>
<skill>Java</skill>
</skills>
</root>;
var obj:Object=XmlParser.parse(xml);
trace(JSON.encode(obj));
//第二种用法:直接给一个XML字符串
var str:String="<root type='001' attr2='002'><node>名称</node></root>";
var obj2:Object=XmlParser.parse(str);
trace(JSON.encode(obj2));
}
]]>
</fx:Script>
<s:Button click="test()" label="test">
</s:Button>
</s:Application>
说明:
XmlParser的包声明你自己改吧,应该木有难度。
这是FlashBuilder的工程,如果是Flex3,请自行更改测试代码里面的标签。
示例出来的效果是这样的:
{"children":[{"name":"name","value":"大漠穷秋"},{"name":"age","value":"25"},{"children":[{"name":"skill","value":"AS3"},{"name":"skill","value":"C++"},{"name":"skill","value":"Java"}],"name":"skills"}],"name":"root"}
{"type":"001","children":[{"name":"node","value":"名称"}],"name":"root","attr2":"002"}
子节点都放在children属性里面,最终形成”树“一样的数据结构。