自定义命名空间使用技巧之——命名空间与XML

来源:互联网 发布:淘宝代理数据包下载 编辑:程序博客网 时间:2024/05/01 22:41

      在一部分AS3项目中XML是我们经常使用的一种保存数据的手段,我们经常用XML来保存一些数据或者一些参数的设置。使用FLEX的朋友更是对MXML这个XML的加强定制版非常熟悉。那么在编写代码的时候我们就不得不经常写一些解析XML内容的代码。今天我要讲的有个小技巧也是刚整理出来的一种命名空间来方便解析XML的方法。有朋友已经从LEX的MXML中领悟到这种使用方法的话请勿见笑。

一、复杂类型变量值的转换
  在XML中我们都知道在用AS3的XML类读取进来后,其各种值基本都是以String的形式存在的。所以在想存放一些比如数组或者在制作UI的时候的一些复合属性时我们需要对这些字符串进行加工以便转换成AS3的其他变量类型。比如下面的一个XML:

<object>
   <id>1000</id>
   <name>test</name>
   <childIdList>23,23,523,5,235,23,52,35,235,235,4646</childIdList>
</ object >


在内部我们要把XML转换数据到myClass类中的具体属性的话可能会写以下形式的函数 :
首先是myClass类:

package{
   public class myClass{
      public var id:int;
      public var name:String;
      public var childIdList:Array = new Array;
      public function myClass(){                       
      }
   }
}

第一种写法:

public function buildObjectByXML(data:XML):void{
        var myObject:myClass = new myClass;
        myObject.id = data.id as int;
        myObject.name = data.name as String;
        myObject.childIdList = data.childIdList.split(“,”);
}


第二种写法:

function buildObjectByXML(data:XML):void {
        var myObject:myClass = new myClass;
        var nodeList:XMLList = data.children();
        for each (var node:XML in nodeList) {
                var valueName:String = node.localName();
                if(!myObject.hasOwnProperty(valueName)) continue;
                if (valueName == "childIdList") {
                        myObject[valueName] = node.toString().split(",");
                } else {
                        myObject[valueName] = node.toString();
                }
        }
}

其中第一种写法就是人肉所有属性然后具体区别对待如何转换,第二种则是遍历XML中的元素然后用if条件来筛选后再进行具体区别和转换。两者所有的转换过程和算法都集中在buildObjectByXML函数中,其缺点就是万一需要设置的XML中属性复杂变量繁多的话阅读性就直线下降,比如我们在写XML配置的UI组件的时候就经常会碰到这样的情况。碰到这样的状况如果后期变量比较固定少做修改还好,如果要频繁修改的话我们就不得不经常面对一个非常长的而且复杂难读的buildObjectByXML函数。

  那么如何使用命名空间来优化这一结构呢?首先,
XML本身也拥有命名空间(详细请阅读AS3帮助)。第二命名空间不同的情况下可以使用同名函数或者变量。集合以上两个特点我们可以把上面的XML以及myClass改造成如下形式:
首先是XML:

<object xmlns:xmlSet=”http://www.aslii.com/xmlSet”>
   <id>1000</id>
   <name>test</name>
   <xmlSet:childIdList>23,23,523,5,235,23,52,35,235,235,4646</ xmlSet:childIdList>
</ object >


然后是myClass类:

package{
   public class myClass{
      public namespace xmlSet = http://www.aslii.com/xmlSet;
      public var id:int;
      public var name:String;
      public var childIdList:Array = new Array;
      public function myClass(){                       
      }
      xmlSet function set childIdList(dataString:String):void{
        this.childIdList = dataString.split(“,”);
      }
}
}


最后是我们的buildObjectByXML函数:

function buildObjectByXML(data:XML):void {
        var myObject:myClass = new myClass;
        var nodeList:XMLList = data.children();
        for each (var node:XML in nodeList) {
                var valueName:String = node.localName();
                var ns:Namespace = node.namespace();
                if(myObject.hasOwnProperty(valueName)) {
                        myObject.ns::[valueName] = node.toString();
     }
        }
}


从中我们可以看到,具体转换类型的代码被移到了具体的类中以一个固定的命名空间以及和属性相同的名字存在。而且这么写如果后期有添加删除属性只需要在具体类中添加对应的方法和变量即可,buildObjectByXML函数就无须再做任何改动了。如果转换的时候算法有所改变我们也可以很轻松的很有针对性的去对象类中找到对应函数名的set函数。

二、用命名空间+XML来组建自己的组件配置文件
  这部分写UI的朋友应该会有兴趣,其实内容也基本是仿造MXML的做法。细心的朋友可能早已发现FLEX的MXML的结构其实非常频繁的使用了XML的命名空间系统,但是其MXML只能用在编写阶段,最后被编译成了SWF。在被编译成SWF之后我们就无法再使用MXML了。其利用XML命名空间来转换成实例的过程被固化在FLEX编辑器中而不是SWF动态编译,所以那部分转换代码我们无法看到他是咋写的。其实其原理和上面利用命名空间来指定特定命名空间的set函数一样,我们只需要在解析XML的时候把命名空间指定的函数内算法和创建元件关联起来即可。而具体写法其实就是写一套顶级的命名空间函数。
比如,我要写一套lii组件,需要通过XML来配置界面。那么可以如下简单实现:
首先是XML:

<root xmlns:lii="http://www.aslii.com/liiUI">
        <lii:Button id="xx" x="0" y="0" width="232" height="333"/>
</root>


然后是一个默认默认包的顶级类:

package{
        public class LiiUIManager{
                public static const core:LiiUIManager = new LiiUIManager();
                public namespace lii = "http://www.aslii.com/liiUI";
                public var uiList:Array = new Array;
                public var length:int;
                public function LiiUIManager(){
                }
                lii static function set Button(data:XML):void{
                        trace("[ new lii::Button ]");
                        core.uiList[length] = new myButton();
                        core.length += 1;
                        //以下用XML解析转换属性代码并且进行详细构造,这里就不写了。
                }
                public static function buildUI(data:XML):void{
                        var nodeList:XMLList = data.children();
                        for each (var node:XML in nodeList) {
                                var valueName:String = node.localName();
                                var ns:Namespace = node.namespace();
                                LiiUIManager.ns::[valueName] = node;
                        }
                }
        }
}


最后是执行解析:

LiiUIManager.buildUI(xml);


 而且我们可以把它们写成可以动态编译的实时解析与构造而不像FLEX那样必须经过编辑器编译构造。这只是个小小的例子,具体的大家可以尽情发挥自己的想像力与创造力。FLEX的MXML并不神秘就是如此简单,我们也可以拥有。

原创粉丝点击