JavaScript解析XML实现多级级联下拉列表

1.创建XML文档:cascaded_select.xml

  1. <?xml version="1.0" encoding="GBK"?>
  2. <select>
  3.     <province key="sx" value="陕西">
  4.         <city key="xa" value="西安"/>
  5.         <city key="bj" value="宝鸡"/>
  6.         <city key="wn" value="渭南">
  7.             <xian key="fp" value="富平">
  8.                 <zhen key="zq" value="张桥"/>
  9.             </xian>
  10.         </city>
  11.         <city key="ak" value="安康"/>
  12.     </province>
  13.     <province key="js" value="江苏">
  14.         <city key="nj" value="南京"/>
  15.         <city key="xz" value="徐州"/>
  16.     </province>
  17.     <province key="sh" value="上海"/>
  18. </select>



2.创建BlueParseXML.js,用来加载解析XML文档

  1. /**
  2.  * @description 解析并封装XML
  3.  * @author BluesLee
  4.  * @lastModif BluesLee
  5.  * @createDate 2007-10-13
  6.  * @modifDate 2007-10-15
  7.  * @version 1.0
  8.  */
  9.     //解析XML文件对象构造器
  10.     function BlueParseXML(){
  11.     }    
  12.     BlueParseXML.prototype.xml;//定义对象属性xml
  13.     BlueParseXML.prototype.loadFinish;//加载完成函数
  14.     BlueParseXML.prototype.nodeProperties=new Array();//节点属性数组
  15.     BlueParseXML.prototype.key="key";
  16.     BlueParseXML.prototype.value="value";
  17.     BlueParseXML.prototype.nodeList;//节点集合
  18.     BlueParseXML.prototype.rootName;
  19.     BlueParseXML.XML_NULL=-1;//未加载xml,或加载失败
  20.     //加载xml文件
  21.     BlueParseXML.prototype.loadXML=function(url){
  22.         var newXML;
  23.         var obj=this;
  24.         //如果它受支持,采用标准的2级DOM技术
  25.         if(document.implementation && document.implementation.createDocument){
  26.             //创建新的Document对象
  27.             newXML=document.implementation.createDocument("","",null);
  28.             //设置装载完毕时触发事件
  29.             newXML.οnlοad=function(){
  30.                 if(obj.loadFinish){
  31.                     obj.loadFinish();
  32.                 }
  33.             }
  34.             newXML.load(url);
  35.         }else{//IE浏览器创建Document对象
  36.             newXML=new ActiveXObject("Microsoft.XMLDOM");
  37.             //设置onload
  38.             newXML.onreadystatechange=function(){
  39.                 if(newXML.readyState==4){
  40.                     if(obj.loadFinish){
  41.                         obj.loadFinish();
  42.                     }
  43.                 }
  44.             }
  45.             newXML.load(url);
  46.         }
  47.         this.xml=newXML;
  48.     }
  49.     //解析遍历xml
  50.     BlueParseXML.prototype.parseXML=function(){
  51.         if(this.xml==null){
  52.             alert("XML未加载,请先加载XML文件!");
  53.             return parseXML.XML_NULL;
  54.         }
  55.         var rootNode=this.xml.documentElement;
  56.         this.rootName=rootNode.tagName;
  57.         this.nodeList=new ChildNodeList();
  58.         this.level=this.iteratorNode(this.nodeList,rootNode,1);
  59.         return this.level;
  60.     }
  61.     //遍历节点,将节点信息封装存入ChildNodeList中
  62.     BlueParseXML.prototype.iteratorNode=function(list,node,level){
  63.         if(!isNaN(level) && level>0){
  64.             list.nodeLevel=level;
  65.         }
  66.         var result=list.nodeLevel;//节点级别
  67.         var flag=true;//判断节点是否有子节点标记
  68.         for(var child=node.firstChild;child!=null;child=child.nextSibling){
  69.             flag=false;//有子节点
  70.             if(list.nodeName==null || list.nodeName==""){
  71.                 list.nodeName=child.tagName;                
  72.             }
  73.             if(list.nodeName==child.tagName){
  74.                 var nodeInfo=new NodeInfo();
  75.                 nodeInfo.nodeLevel=list.nodeLevel;//设置节点级别
  76.                 nodeInfo.nodeName=list.nodeName;//设置节点名称
  77.                 nodeInfo.key=child.getAttribute(this.key);//设置节点属性
  78.                 nodeInfo.value=child.getAttribute(this.value);
  79.                 for(var index=0;index<this.nodeProperties.length;index++){
  80.                     nodeInfo[this.nodeProperties[index]]=child.getAttribute(this.nodeProperties[index]);
  81.                 }
  82.                 list.addElement(nodeInfo.key,nodeInfo);//把节点加入父节点的子节点集合            
  83.                 var n=this.iteratorNode(nodeInfo.childNodeList,child,list.nodeLevel+1);
  84.                 if(n>result){//如果子节点返回的节点级别大于改节点级别,设置返回节点级别为最大级别
  85.                     result=n;
  86.                 }
  87.             }
  88.         }
  89.         if(flag){//当改节点没有子节点时返回的节点级别-1
  90.             result=result-1;
  91.         }
  92.         return result;
  93.     }
  94.     //扩展String对象,增加trim方法去掉字符串前后空格
  95.     String.prototype.trim=function(){        
  96.         return this.replace(/^s*/g,"").replace(/s*$/g,"");
  97.     }
  98.     /**//** 
  99.      * @description 自定义集合对象(利用对象属性键值对,类似Hashtable使用)
  100.      * @author BluesLee
  101.      * @lastModif BluesLee
  102.      * @createDate 2007-10-13
  103.      * @modifDate 2007-10-15
  104.       * @version 1.0
  105.      */
  106.     ChildNodeList.prototype.nodeLevel=1;
  107.     ChildNodeList.prototype.nodeName;
  108.     ChildNodeList.prototype.keyArray;
  109.     ChildNodeList.prototype.ELEMENT_NULL=-1;//元素为空
  110.     ChildNodeList.prototype.ELEMENT_EXIST=-2;//元素已经存在
  111.     ChildNodeList.prototype.ELEMENT_NOT_EXIST=-3;//元素不存在
  112.     ChildNodeList.prototype.INDEX_OUT=-4//数组下标越界
  113.     ChildNodeList.prototype.ERROR_DELETE=-5//删除元素出错
  114.     function ChildNodeList(){
  115.         this.keyArray=new Array();
  116.     }
  117.     //添加集合元素
  118.     ChildNodeList.prototype.addElement=function(key,element){
  119.         if(key==null || element==null){
  120.             return ChildNodeList.ELEMENT_NULL;
  121.         }
  122.         if(this[key]!=null){
  123.             return ChildNodeList.ELEMENT_EXIST;
  124.         }
  125.         var index=this.keyArray.length;
  126.         this.keyArray[index]=key;
  127.         this[key]=element;
  128.         return index;
  129.     }
  130.     //根据下标删除集合元素
  131.     ChildNodeList.prototype.deleteElementByIndex=function(index){
  132.         if(index>=this.keyArray.length){
  133.             return ChildNodeList.INDEX_OUT;
  134.         }
  135.         var key=this.keyArray[index];
  136.         for(var i=index;i<this.keyArray.length;i++){
  137.             this.keyArray[i]=this.keyArray[i+1];
  138.         }
  139.         this.keyArray.length=this.keyArray.length-1;
  140.         delete this[key];
  141.         return index;
  142.     }
  143.     //根据key删除集合元素
  144.     ChildNodeList.prototype.deleteElementByKey=function(key){
  145.         if(this[key]==null){
  146.             return ChildNodeList.ELEMENT_NOT_EXIST;
  147.         }
  148.         for(var index=0;index<this.keyArray.length;index++){
  149.             if(this.keyArray[index]==key){
  150.                 return this.deleteElementByIndex(index);
  151.             }
  152.         }
  153.         return ChildNodeList.ERROR_DELETE;
  154.     }
  155.     //根据key查找元素
  156.     ChildNodeList.prototype.getElementByKey=function(key){
  157.         return this[key];
  158.     }
  159.     //根据下标查找元素
  160.     ChildNodeList.prototype.getElementByIndex=function(index){
  161.         return this.getElementByKey(this.keyArray[index]);
  162.     }
  163.     //获取集合大小
  164.     ChildNodeList.prototype.size=function(){
  165.         return this.keyArray.length;
  166.     }
  167.     /**//** 
  168.      * @description 节点信息封装对象
  169.      * @author BluesLee
  170.      * @lastModif BluesLee
  171.      * @createDate 2007-10-13
  172.      * @modifDate 2007-10-15
  173.       * @version 1.0
  174.      */
  175.     NodeInfo.prototype.nodeLevel;
  176.     NodeInfo.prototype.nodeName;//节点名称
  177.     NodeInfo.prototype.key;//节点名称,对应xml节点key属性
  178.     NodeInfo.prototype.value;//节点内容,对应xml节点value属性
  179.     NodeInfo.prototype.childNodeList;//子节点列表,用ChildNodeList对象封装
  180.     //构造器
  181.     function NodeInfo(){
  182.         this.childNodeList=new ChildNodeList();
  183.     }


3.创建BlueCasadedSelect.js文件,用来生成级联下拉框

  1. /** 
  2.  * @description 级联下拉对象
  3.  * @author BluesLee
  4.  * @lastModif BluesLee
  5.  * @createDate 2007-10-13
  6.  * @modifDate 2007-10-15
  7.  * @version 1.0
  8.  */
  9. BlueCasadedSelect.prototype.selectList;
  10. BlueCasadedSelect.prototype.defaultValue="-1";
  11. BlueCasadedSelect.prototype.defaultText="请选择…";
  12. BlueCasadedSelect.prototype.nodeList;//节点总集合
  13. BlueCasadedSelect.prototype.isAddOnChangeEvent=false;
  14. BlueCasadedSelect.prototype.SELECTLIST_NULL=-1;//下拉对象数组为空
  15. BlueCasadedSelect.prototype.SELECTLIST_TYPE_NOT_ARRAY=-2;//下拉对象数组不是数组对象
  16. BlueCasadedSelect.prototype.SELECTLIST_EMPTY=-3;//下拉对象数组为空数组
  17. BlueCasadedSelect.prototype.SELECTLIST_LENGTH_OUT=-4;//下拉对象数组小于节点集合级别
  18. BlueCasadedSelect.prototype.NODELIST_EMPTY=-5;//节点集合为空
  19. BlueCasadedSelect.prototype.EVENT_NULL=-6;//事件源为空
  20. //构造器
  21. function BlueCasadedSelect(nodeList){
  22.     if(nodeList!=null){
  23.         this.nodeList=nodeList;
  24.     }else{
  25.         this.nodeList=new ChildNodeList();
  26.     }
  27. }
  28. /**//**
  29.  * 创建下拉列表
  30.  * @author BluesLee
  31.  * @lastModif BluesLee
  32.  * @createDate 2007-10-13
  33.  * @lastModifDate 2007-10-13
  34.  * @param parentNode 下拉列表父节点对象
  35.  * @param nameList 下拉列表名字集合[可选参数]
  36.  * @version 1.0
  37.  */
  38. BlueCasadedSelect.prototype.createSelect=function(parentNode,nameList){
  39.     if(nameList==null){
  40.         if(this.nodeList.size()>0){
  41.             return this.createSelectDefault(parentNode,this.nodeList);
  42.         }
  43.         return this.NODELIST_EMPTY;
  44.     }
  45.     if(this.selectList==null){
  46.         this.selectList=new Array();
  47.     }
  48.     this.selectList.length=nameList.length;
  49.     var obj=this;
  50.     for(var i=0;i<nameList.length;i++){
  51.         var select=document.createElement("select");
  52.         select.setAttribute("name",nameList[i]);
  53.         select.setAttribute("id",nameList[i]);
  54.         select.options.length=1;
  55.         select.options[0].value=this.defaultValue;
  56.         select.options[0].text=this.defaultText;
  57.         if(i<nameList.length-1){
  58.             select.attachEvent("onchange",function(){obj.changeSelect(select);});
  59.             this.isAddOnChangeEvent=true;
  60.         }
  61.         this.selectList[i]=select;
  62.         parentNode.appendChild(select);
  63.     }
  64.     return this.selectList.length;
  65. }
  66. /**//**
  67.  * 创建下拉列表(默认创建方法)
  68.  * @author BluesLee
  69.  * @lastModif BluesLee
  70.  * @createDate 2007-10-13
  71.  * @lastModifDate 2007-10-13
  72.  * @param parentNode 下拉列表父节点对象
  73.  * @param nodeList XML文档节点集合
  74.  * @version 1.0
  75.  */
  76. BlueCasadedSelect.prototype.createSelectDefault=function(parentNode,nodeList){
  77.     if(this.selectList==null){
  78.         this.selectList=new Array();
  79.     }
  80.     var obj=this;
  81.     if(nodeList!=null && nodeList.nodeName!=null){
  82.         this.selectList.length=this.selectList.length+1;
  83.         var select=document.createElement("select");
  84.         select.setAttribute("name",nodeList.nodeName);
  85.         select.setAttribute("id",nodeList.nodeName);        
  86.         select.options.length=1;
  87.         select.options[0].value=this.defaultValue;
  88.         select.options[0].text=this.defaultText;
  89.         this.selectList[this.selectList.length-1]=select;
  90.         parentNode.appendChild(select);
  91.         for(var i=0;i<nodeList.size();i++){            
  92.             var childNodeList=nodeList.getElementByIndex(i).childNodeList;
  93.             if(childNodeList.size()>0){
  94.                 select.attachEvent("onchange",function(){obj.changeSelect(select);});
  95.                 this.isAddOnChangeEvent=true;
  96.                 this.createSelectDefault(parentNode,childNodeList);
  97.                 break;
  98.             }            
  99.         }
  100.     }
  101.     return this.selectList.length;
  102. }
  103. /**//**
  104.  * 添加下拉列表onChange事件响应
  105.  * @author BluesLee
  106.  * @lastModif BluesLee
  107.  * @createDate 2007-10-13
  108.  * @lastModifDate 2007-10-13
  109.  * @version 1.0
  110.  */
  111. BlueCasadedSelect.prototype.addOnChangeEvent=function(){
  112.     if(this.isAddOnChangeEvent){
  113.         return;
  114.     }
  115.     if(this.selectList==null){
  116.         return this.SELECTLIST_NULL;
  117.     }
  118.     if(this.selectList.constructor!=Array){
  119.         return this.SELECTLIST_TYPE_NOT_ARRAY;
  120.     }
  121.     if(this.selectList.length<=0){
  122.         return this.SELECTLIST_EMPTY;
  123.     }
  124.     var obj=this;
  125.     for(var i=0;i<this.selectList.length-1;i++){
  126.         var select=this.selectList[i];
  127.         select.attachEvent("onchange",function(){obj.changeSelect(select);});
  128.     }
  129.     this.isAddOnChangeEvent=true;
  130. }
  131. /**//**
  132.  * 初始化下拉列表
  133.  * @author BluesLee
  134.  * @lastModif BluesLee
  135.  * @createDate 2007-10-13
  136.  * @lastModifDate 2007-10-13
  137.  * @param paramList 初始化每一级下拉默认选项参数列表
  138.  * @param nodeList XML文档节点集合[可选参数]
  139.  * @version 1.0
  140.  */
  141. BlueCasadedSelect.prototype.init=function(paramList,nodeList){
  142.     var currentList;
  143.     if(nodeList==null){
  144.         currentList=this.nodeList;
  145.     }else{
  146.         currentList=nodeList;
  147.     }
  148.     if(this.selectList==null){
  149.         return this.SELECTLIST_NULL;
  150.     }
  151.     if(this.selectList.constructor!=Array){
  152.         return this.SELECTLIST_TYPE_NOT_ARRAY;
  153.     }
  154.     if(this.selectList.length<=0){
  155.         return this.SELECTLIST_EMPTY;
  156.     }
  157.     if(this.selectList.length<currentList.nodeLevel){
  158.         return this.SELECTLIST_LENGTH_OUT;
  159.     }
  160.     if(currentList.size()<=0){        
  161.         return this.NODELIST_EMPTY;
  162.     }
  163.     var select=this.selectList[currentList.nodeLevel-1];
  164.     var defaultValue=paramList[currentList.nodeLevel-1];
  165.     for(var i=0;i<currentList.size();i++){
  166.         var nodeInfo=currentList.getElementByIndex(i);
  167.         var index=select.options.length;
  168.         select.options.length=index+1;
  169.         select.options[index].value=nodeInfo.key;
  170.         select.options[index].text=nodeInfo.value;
  171.         if(defaultValue!=null && defaultValue==nodeInfo.key){
  172.             select.options[index].selected=true;
  173.             if(nodeInfo.childNodeList.size()<=0){
  174.                 for(var j=currentList.nodeLevel;j<this.selectList.length;j++){
  175.                     var sel=this.selectList[j];
  176.                     var n=sel.options.length;
  177.                     sel.options.length=n+1;                    
  178.                     sel.options[n].value=nodeInfo.key;
  179.                     sel.options[n].text=nodeInfo.value;
  180.                     sel.options[n].selected=true;
  181.                 }
  182.             }else{
  183.                 this.init(paramList,nodeInfo.childNodeList);
  184.             }
  185.         }
  186.     }
  187.     return select.options.length;
  188. }
  189. /**//**
  190.  * 下拉列表联动
  191.  * @author BluesLee
  192.  * @lastModif BluesLee
  193.  * @createDate 2007-10-13
  194.  * @lastModifDate 2007-10-13
  195.  * @param event 事件源下拉对象
  196.  * @version 1.0
  197.  */
  198. BlueCasadedSelect.prototype.changeSelect=function(event){
  199.     if(event==null){
  200.         return this.EVENT_NULL;
  201.     }
  202.     if(this.selectList==null){
  203.         return this.SELECTLIST_NULL;
  204.     }
  205.     if(this.selectList.constructor!=Array){
  206.         return this.SELECTLIST_TYPE_NOT_ARRAY;
  207.     }
  208.     if(this.selectList.length<=0){
  209.         return this.SELECTLIST_EMPTY;
  210.     }
  211.     if(this.nodeList.size()<=0){
  212.         return this.NODELIST_EMPTY;
  213.     }
  214.     var nextList=this.nodeList;
  215.     var nextSelect=event;
  216.     var flag=false;
  217.     var n=0;
  218.     for(var i=0;i<this.selectList.length;i++){
  219.         var select=this.selectList[i];
  220.         if(flag){
  221.             this.selectList[i].options.length=1;
  222.         }else{
  223.             if(nextList.getElementByKey(select.value)!=null){
  224.                 nextList=nextList.getElementByKey(select.value).childNodeList;
  225.             }else{
  226.                 nextList=new ChildNodeList();
  227.             }
  228.         }
  229.         if(select==event){
  230.             nextSelect=this.selectList[i+1];
  231.             flag=true;
  232.             n=i;
  233.         }
  234.     }
  235.     if(nextList.size()<=0 && event.value!=this.defaultValue){
  236.         for(var i=n+1;i<this.selectList.length;i++){
  237.             nextSelect=this.selectList[i];
  238.             var index=nextSelect.options.length;
  239.             nextSelect.options.length=index+1;
  240.             nextSelect.options[index].value=event.value;
  241.             nextSelect.options[index].text=event.options[event.selectedIndex].text;
  242.             nextSelect.options[index].selected=true;
  243.         }
  244.         return nextSelect.options.length;
  245.     }
  246.     for(var i=0;i<nextList.size();i++){
  247.         var nodeInfo=nextList.getElementByIndex(i);
  248.         var index=nextSelect.options.length;
  249.         nextSelect.options.length=index+1;
  250.         nextSelect.options[index].value=nodeInfo.key;
  251.         nextSelect.options[index].text=nodeInfo.value;
  252.     }
  253.     return nextSelect.options.length;
  254. }


4.创建测试页面cascaded_select.html


  1. <!--深蓝忧郁级联下拉框-->
  2. <script src="BlueParseXML.js">
  3. //加载XML
  4. </script>
  5. <script src="BlueCasadedSelect.js">
  6. //生成级联下拉
  7. </script>
  8. <body>
  9. </body>
  10. <script>
  11.     function finish(){
  12.         alert("加载完成");
  13.     }
  14.     var myxml=new BlueParseXML();
  15.     //添加xml加载完成事件响应
  16.     myxml.loadFinish=finish;
  17.     myxml.loadXML("cascaded_select.xml");
  18.     var level=myxml.parseXML();
  19.     //多级级联下拉
  20.     var blueCasadedSelect=new BlueCasadedSelect(myxml.nodeList);
  21.     //生成下拉列表,下拉列表name属性为xml节点名
  22.     blueCasadedSelect.createSelect(document.body);
  23.     //如果下拉列表提前已有,则不需生成,需要设置下拉列表集合为已有下拉集合,并添加onchange事件响应内容
  24.     //blueCasadedSelect.selectList=sels;
  25.     //blueCasadedSelect.addOnChangeEvent();
  26.     blueCasadedSelect.init(new Array("sx","xa"));
  27.         //简单的树结构遍历测试
  28.     //====================================
  29.     document.write("<br>");
  30.     function iterator(list){
  31.         if(list.size()<=0){
  32.             return;
  33.         }
  34.         for(var i=0;i<list.size();i++){
  35.             var obj=list.getElementByIndex(i);
  36.             for(var j=1;j<list.nodeLevel;j++){
  37.                 document.write("——");
  38.             }
  39.             document.write("<a href='"+obj.key+"'>"+obj.nodeLevel+obj.value+"</a><br>");
  40.             iterator(obj.childNodeList);
  41.         }
  42.     }
  43.     iterator(myxml.nodeList);
  44.     //====================================
  45. </script>


http://blog.csdn.net/lip009/archive/2007/10/15/1826028.aspx
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值