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

原创 2007年10月15日 16:49:00
1.创建XML文档:cascaded_select.xml
<?xml version="1.0" encoding="GBK"?>
<select>
    
<province key="sx" value="陕西">
        
<city key="xa" value="西安"/>
        
<city key="bj" value="宝鸡"/>
        
<city key="wn" value="渭南">
            
<xian key="fp" value="富平">
                
<zhen key="zq" value="张桥"/>
            
</xian>
        
</city>
        
<city key="ak" value="安康"/>
    
</province>
    
<province key="js" value="江苏">
        
<city key="nj" value="南京"/>
        
<city key="xz" value="徐州"/>
    
</province>
    
<province key="sh" value="上海"/>
</select>

 

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

/**
 * @description 解析并封装XML
 * @author BluesLee
 * @lastModif BluesLee
 * @createDate 2007-10-13
 * @modifDate 2007-10-15
 * @version 1.0
 
*/

    
//解析XML文件对象构造器
    function BlueParseXML(){
    }
    
    BlueParseXML.prototype.xml;
//定义对象属性xml
    BlueParseXML.prototype.loadFinish;//加载完成函数
    BlueParseXML.prototype.nodeProperties=new Array();//节点属性数组
    BlueParseXML.prototype.key="key";
    BlueParseXML.prototype.value
="value";
    BlueParseXML.prototype.nodeList;
//节点集合
    BlueParseXML.prototype.rootName;
    BlueParseXML.XML_NULL
=-1;//未加载xml,或加载失败

    
//加载xml文件
    BlueParseXML.prototype.loadXML=function(url){
        
var newXML;
        
var obj=this;
        
//如果它受支持,采用标准的2级DOM技术
        if(document.implementation && document.implementation.createDocument){
            
//创建新的Document对象
            newXML=document.implementation.createDocument("","",null);
            
//设置装载完毕时触发事件
            newXML.onload=function(){
                
if(obj.loadFinish){
                    obj.loadFinish();
                }

            }

            newXML.load(url);
        }
else{//IE浏览器创建Document对象
            newXML=new ActiveXObject("Microsoft.XMLDOM");
            
//设置onload
            newXML.onreadystatechange=function(){
                
if(newXML.readyState==4){
                    
if(obj.loadFinish){
                        obj.loadFinish();
                    }

                }

            }

            newXML.load(url);
        }

        
this.xml=newXML;
    }


    
//解析遍历xml
    BlueParseXML.prototype.parseXML=function(){
        
if(this.xml==null){
            alert(
"XML未加载,请先加载XML文件!");
            
return parseXML.XML_NULL;
        }

        
var rootNode=this.xml.documentElement;
        
this.rootName=rootNode.tagName;
        
this.nodeList=new ChildNodeList();
        
this.level=this.iteratorNode(this.nodeList,rootNode,1);
        
return this.level;
    }

    
//遍历节点,将节点信息封装存入ChildNodeList中
    BlueParseXML.prototype.iteratorNode=function(list,node,level){
        
if(!isNaN(level) && level>0){
            list.nodeLevel
=level;
        }

        
var result=list.nodeLevel;//节点级别
        var flag=true;//判断节点是否有子节点标记
        for(var child=node.firstChild;child!=null;child=child.nextSibling){
            flag
=false;//有子节点
            if(list.nodeName==null || list.nodeName==""){
                list.nodeName
=child.tagName;                
            }

            
if(list.nodeName==child.tagName){
                
var nodeInfo=new NodeInfo();
                nodeInfo.nodeLevel
=list.nodeLevel;//设置节点级别
                nodeInfo.nodeName=list.nodeName;//设置节点名称
                nodeInfo.key=child.getAttribute(this.key);//设置节点属性
                nodeInfo.value=child.getAttribute(this.value);
                
for(var index=0;index<this.nodeProperties.length;index++){
                    nodeInfo[
this.nodeProperties[index]]=child.getAttribute(this.nodeProperties[index]);
                }

                list.addElement(nodeInfo.key,nodeInfo);
//把节点加入父节点的子节点集合            
                var n=this.iteratorNode(nodeInfo.childNodeList,child,list.nodeLevel+1);
                
if(n>result){//如果子节点返回的节点级别大于改节点级别,设置返回节点级别为最大级别
                    result=n;
                }

            }

        }

        
if(flag){//当改节点没有子节点时返回的节点级别-1
            result=result-1;
        }

        
return result;
    }

    
//扩展String对象,增加trim方法去掉字符串前后空格
    String.prototype.trim=function(){        
        
return this.replace(/^s*/g,"").replace(/s*$/g,"");
    }

    
/*
     * @description 自定义集合对象(利用对象属性键值对,类似Hashtable使用)
     * @author BluesLee
     * @lastModif BluesLee
     * @createDate 2007-10-13
     * @modifDate 2007-10-15
      * @version 1.0
     
*/

    ChildNodeList.prototype.nodeLevel
=1;
    ChildNodeList.prototype.nodeName;
    ChildNodeList.prototype.keyArray;
    ChildNodeList.prototype.ELEMENT_NULL
=-1;//元素为空
    ChildNodeList.prototype.ELEMENT_EXIST=-2;//元素已经存在
    ChildNodeList.prototype.ELEMENT_NOT_EXIST=-3;//元素不存在
    ChildNodeList.prototype.INDEX_OUT=-4//数组下标越界
    ChildNodeList.prototype.ERROR_DELETE=-5//删除元素出错
    function ChildNodeList(){
        
this.keyArray=new Array();
    }

    
//添加集合元素
    ChildNodeList.prototype.addElement=function(key,element){
        
if(key==null || element==null){
            
return ChildNodeList.ELEMENT_NULL;
        }

        
if(this[key]!=null){
            
return ChildNodeList.ELEMENT_EXIST;
        }

        
var index=this.keyArray.length;
        
this.keyArray[index]=key;
        
this[key]=element;
        
return index;
    }

    
//根据下标删除集合元素
    ChildNodeList.prototype.deleteElementByIndex=function(index){
        
if(index>=this.keyArray.length){
            
return ChildNodeList.INDEX_OUT;
        }

        
var key=this.keyArray[index];
        
for(var i=index;i<this.keyArray.length;i++){
            
this.keyArray[i]=this.keyArray[i+1];
        }

        
this.keyArray.length=this.keyArray.length-1;
        
delete this[key];
        
return index;
    }

    
//根据key删除集合元素
    ChildNodeList.prototype.deleteElementByKey=function(key){
        
if(this[key]==null){
            
return ChildNodeList.ELEMENT_NOT_EXIST;
        }

        
for(var index=0;index<this.keyArray.length;index++){
            
if(this.keyArray[index]==key){
                
return this.deleteElementByIndex(index);
            }

        }

        
return ChildNodeList.ERROR_DELETE;
    }

    
//根据key查找元素
    ChildNodeList.prototype.getElementByKey=function(key){
        
return this[key];
    }

    
//根据下标查找元素
    ChildNodeList.prototype.getElementByIndex=function(index){
        
return this.getElementByKey(this.keyArray[index]);
    }

    
//获取集合大小
    ChildNodeList.prototype.size=function(){
        
return this.keyArray.length;
    }


    
/*
     * @description 节点信息封装对象
     * @author BluesLee
     * @lastModif BluesLee
     * @createDate 2007-10-13
     * @modifDate 2007-10-15
      * @version 1.0
     
*/

    NodeInfo.prototype.nodeLevel;
    NodeInfo.prototype.nodeName;
//节点名称
    NodeInfo.prototype.key;//节点名称,对应xml节点key属性
    NodeInfo.prototype.value;//节点内容,对应xml节点value属性
    NodeInfo.prototype.childNodeList;//子节点列表,用ChildNodeList对象封装
    //构造器
    function NodeInfo(){
        
this.childNodeList=new ChildNodeList();
    }

 

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

/*
 * @description 级联下拉对象
 * @author BluesLee
 * @lastModif BluesLee
 * @createDate 2007-10-13
 * @modifDate 2007-10-15
 * @version 1.0
 
*/

BlueCasadedSelect.prototype.selectList;
BlueCasadedSelect.prototype.defaultValue
="-1";
BlueCasadedSelect.prototype.defaultText
="请选择…";
BlueCasadedSelect.prototype.nodeList;
//节点总集合
BlueCasadedSelect.prototype.isAddOnChangeEvent=false;
BlueCasadedSelect.prototype.SELECTLIST_NULL
=-1;//下拉对象数组为空
BlueCasadedSelect.prototype.SELECTLIST_TYPE_NOT_ARRAY=-2;//下拉对象数组不是数组对象
BlueCasadedSelect.prototype.SELECTLIST_EMPTY=-3;//下拉对象数组为空数组
BlueCasadedSelect.prototype.SELECTLIST_LENGTH_OUT=-4;//下拉对象数组小于节点集合级别
BlueCasadedSelect.prototype.NODELIST_EMPTY=-5;//节点集合为空
BlueCasadedSelect.prototype.EVENT_NULL=-6;//事件源为空
//
构造器
function BlueCasadedSelect(nodeList){
    
if(nodeList!=null){
        
this.nodeList=nodeList;
    }
else{
        
this.nodeList=new ChildNodeList();
    }

}

/**
 * 创建下拉列表
 * @author BluesLee
 * @lastModif BluesLee
 * @createDate 2007-10-13
 * @lastModifDate 2007-10-13
 * @param parentNode 下拉列表父节点对象
 * @param nameList 下拉列表名字集合[可选参数]
 * @version 1.0
 
*/

BlueCasadedSelect.prototype.createSelect
=function(parentNode,nameList){
    
if(nameList==null){
        
if(this.nodeList.size()>0){
            
return this.createSelectDefault(parentNode,this.nodeList);
        }

        
return this.NODELIST_EMPTY;
    }

    
if(this.selectList==null){
        
this.selectList=new Array();
    }

    
this.selectList.length=nameList.length;
    
var obj=this;
    
for(var i=0;i<nameList.length;i++){
        
var select=document.createElement("select");
        select.setAttribute(
"name",nameList[i]);
        select.setAttribute(
"id",nameList[i]);
        select.options.length
=1;
        select.options[
0].value=this.defaultValue;
        select.options[
0].text=this.defaultText;
        
if(i<nameList.length-1){
            select.attachEvent(
"onchange",function(){obj.changeSelect(select);});
            
this.isAddOnChangeEvent=true;
        }

        
this.selectList[i]=select;
        parentNode.appendChild(select);
    }

    
return this.selectList.length;
}


/**
 * 创建下拉列表(默认创建方法)
 * @author BluesLee
 * @lastModif BluesLee
 * @createDate 2007-10-13
 * @lastModifDate 2007-10-13
 * @param parentNode 下拉列表父节点对象
 * @param nodeList XML文档节点集合
 * @version 1.0
 
*/

BlueCasadedSelect.prototype.createSelectDefault
=function(parentNode,nodeList){
    
if(this.selectList==null){
        
this.selectList=new Array();
    }

    
var obj=this;
    
if(nodeList!=null && nodeList.nodeName!=null){
        
this.selectList.length=this.selectList.length+1;
        
var select=document.createElement("select");
        select.setAttribute(
"name",nodeList.nodeName);
        select.setAttribute(
"id",nodeList.nodeName);        
        select.options.length
=1;
        select.options[
0].value=this.defaultValue;
        select.options[
0].text=this.defaultText;
        
this.selectList[this.selectList.length-1]=select;
        parentNode.appendChild(select);
        
for(var i=0;i<nodeList.size();i++){            
            
var childNodeList=nodeList.getElementByIndex(i).childNodeList;
            
if(childNodeList.size()>0){
                select.attachEvent(
"onchange",function(){obj.changeSelect(select);});
                
this.isAddOnChangeEvent=true;
                
this.createSelectDefault(parentNode,childNodeList);
                
break;
            }
            
        }

    }

    
return this.selectList.length;
}


/**
 * 添加下拉列表onChange事件响应
 * @author BluesLee
 * @lastModif BluesLee
 * @createDate 2007-10-13
 * @lastModifDate 2007-10-13
 * @version 1.0
 
*/

BlueCasadedSelect.prototype.addOnChangeEvent
=function(){
    
if(this.isAddOnChangeEvent){
        
return;
    }

    
if(this.selectList==null){
        
return this.SELECTLIST_NULL;
    }

    
if(this.selectList.constructor!=Array){
        
return this.SELECTLIST_TYPE_NOT_ARRAY;
    }

    
if(this.selectList.length<=0){
        
return this.SELECTLIST_EMPTY;
    }

    
var obj=this;
    
for(var i=0;i<this.selectList.length-1;i++){
        
var select=this.selectList[i];
        select.attachEvent(
"onchange",function(){obj.changeSelect(select);});
    }

    
this.isAddOnChangeEvent=true;
}


/**
 * 初始化下拉列表
 * @author BluesLee
 * @lastModif BluesLee
 * @createDate 2007-10-13
 * @lastModifDate 2007-10-13
 * @param paramList 初始化每一级下拉默认选项参数列表
 * @param nodeList XML文档节点集合[可选参数]
 * @version 1.0
 
*/

BlueCasadedSelect.prototype.init
=function(paramList,nodeList){
    
var currentList;
    
if(nodeList==null){
        currentList
=this.nodeList;
    }
else{
        currentList
=nodeList;
    }

    
if(this.selectList==null){
        
return this.SELECTLIST_NULL;
    }

    
if(this.selectList.constructor!=Array){
        
return this.SELECTLIST_TYPE_NOT_ARRAY;
    }

    
if(this.selectList.length<=0){
        
return this.SELECTLIST_EMPTY;
    }

    
if(this.selectList.length<currentList.nodeLevel){
        
return this.SELECTLIST_LENGTH_OUT;
    }

    
if(currentList.size()<=0){        
        
return this.NODELIST_EMPTY;
    }

    
var select=this.selectList[currentList.nodeLevel-1];
    
var defaultValue=paramList[currentList.nodeLevel-1];
    
for(var i=0;i<currentList.size();i++){
        
var nodeInfo=currentList.getElementByIndex(i);
        
var index=select.options.length;
        select.options.length
=index+1;
        select.options[index].value
=nodeInfo.key;
        select.options[index].text
=nodeInfo.value;
        
if(defaultValue!=null && defaultValue==nodeInfo.key){
            select.options[index].selected
=true;
            
if(nodeInfo.childNodeList.size()<=0){
                
for(var j=currentList.nodeLevel;j<this.selectList.length;j++){
                    
var sel=this.selectList[j];
                    
var n=sel.options.length;
                    sel.options.length
=n+1;                    
                    sel.options[n].value
=nodeInfo.key;
                    sel.options[n].text
=nodeInfo.value;
                    sel.options[n].selected
=true;
                }

            }
else{
                
this.init(paramList,nodeInfo.childNodeList);
            }

        }

    }

    
return select.options.length;
}


/**
 * 下拉列表联动
 * @author BluesLee
 * @lastModif BluesLee
 * @createDate 2007-10-13
 * @lastModifDate 2007-10-13
 * @param event 事件源下拉对象
 * @version 1.0
 
*/

BlueCasadedSelect.prototype.changeSelect
=function(event){
    
if(event==null){
        
return this.EVENT_NULL;
    }

    
if(this.selectList==null){
        
return this.SELECTLIST_NULL;
    }

    
if(this.selectList.constructor!=Array){
        
return this.SELECTLIST_TYPE_NOT_ARRAY;
    }

    
if(this.selectList.length<=0){
        
return this.SELECTLIST_EMPTY;
    }

    
if(this.nodeList.size()<=0){
        
return this.NODELIST_EMPTY;
    }

    
var nextList=this.nodeList;
    
var nextSelect=event;
    
var flag=false;
    
var n=0;
    
for(var i=0;i<this.selectList.length;i++){
        
var select=this.selectList[i];
        
if(flag){
            
this.selectList[i].options.length=1;
        }
else{
            
if(nextList.getElementByKey(select.value)!=null){
                nextList
=nextList.getElementByKey(select.value).childNodeList;
            }
else{
                nextList
=new ChildNodeList();
            }

        }

        
if(select==event){
            nextSelect
=this.selectList[i+1];
            flag
=true;
            n
=i;
        }

    }

    
if(nextList.size()<=0 && event.value!=this.defaultValue){
        
for(var i=n+1;i<this.selectList.length;i++){
            nextSelect
=this.selectList[i];
            
var index=nextSelect.options.length;
            nextSelect.options.length
=index+1;
            nextSelect.options[index].value
=event.value;
            nextSelect.options[index].text
=event.options[event.selectedIndex].text;
            nextSelect.options[index].selected
=true;
        }

        
return nextSelect.options.length;
    }

    
for(var i=0;i<nextList.size();i++){
        
var nodeInfo=nextList.getElementByIndex(i);
        
var index=nextSelect.options.length;
        nextSelect.options.length
=index+1;
        nextSelect.options[index].value
=nodeInfo.key;
        nextSelect.options[index].text
=nodeInfo.value;
    }

    
return nextSelect.options.length;
}

 

4.创建测试页面cascaded_select.html

<!--深蓝忧郁级联下拉框-->
<script src="BlueParseXML.js">
//加载XML
</script>
<script src="BlueCasadedSelect.js">
//生成级联下拉
</script>
<body>
</body>
<script>
    
function finish(){
        alert(
"加载完成");
    }

    
var myxml=new BlueParseXML();
    
//添加xml加载完成事件响应
    myxml.loadFinish=finish;
    myxml.loadXML(
"cascaded_select.xml");
    
var level=myxml.parseXML();

    
//多级级联下拉
    var blueCasadedSelect=new BlueCasadedSelect(myxml.nodeList);
    
//生成下拉列表,下拉列表name属性为xml节点名
    blueCasadedSelect.createSelect(document.body);
    
//如果下拉列表提前已有,则不需生成,需要设置下拉列表集合为已有下拉集合,并添加onchange事件响应内容
    //blueCasadedSelect.selectList=sels;
    //blueCasadedSelect.addOnChangeEvent();
    blueCasadedSelect.init(new Array("sx","xa"));

        
//简单的树结构遍历测试
    //====================================
    document.write("<br>");
    
function iterator(list){
        
if(list.size()<=0){
            
return;
        }

        
for(var i=0;i<list.size();i++){
            
var obj=list.getElementByIndex(i);
            
for(var j=1;j<list.nodeLevel;j++){
                document.write(
"——");
            }

            document.write(
"<a href='"+obj.key+"'>"+obj.nodeLevel+obj.value+"</a><br>");
            iterator(obj.childNodeList);
        }

    }

    iterator(myxml.nodeList);
    
//====================================
</script>

 

 

 

js解析XML文件,并将城市显示在下拉列表,选中城市后出现城市介绍

在群上看到有人问问题,就闲着没事做了一下
  • u011193139
  • u011193139
  • 2014年07月29日 12:25
  • 935

js自定义多级联动下拉菜单,实用方便

工作中经常使用这个js自定义多级联动下拉菜单,实用方便 尤其当需要把将数据库中的层级数据转换为树形结构时,还有就是根据条件动态添加减少菜单时 test.html js自定义多...
  • nuli888
  • nuli888
  • 2016年07月09日 19:55
  • 6895

下拉菜单三级级联的效果实现(jsp、js、Java、mysql)

三级级联的下拉菜单效果实现 1、效果图 2、jsp代码 类别 全部 ...
  • bjlf_1989
  • bjlf_1989
  • 2015年08月21日 09:35
  • 6029

下拉菜单的两种实现方式:CSS和JS

下拉菜单的简单介绍、源代码以及可能出现相关问题
  • cho_jun
  • cho_jun
  • 2017年05月28日 10:15
  • 1264

JS多级联动下拉列表(不限级数)

JS多级联动下拉列表,可用于省、市、区三级联动,或多级分类联动选择等。 不限级数,兼容浏览器,使用方法请看下面的HTML示例。 示例效果如下图所示: 图1 图2 ...
  • oukunqing
  • oukunqing
  • 2015年02月02日 11:44
  • 3403

js动态生成级联下拉列表

级联选择器练习 window.onload = function(){ var ojson=[{'province':'河北省...
  • lhb_11
  • lhb_11
  • 2017年04月19日 15:19
  • 1064

JQuery和ASP.NET分别实现级联下拉框效果

在学习Javascript之前知道下拉框的级联效果
  • wangyajin333
  • wangyajin333
  • 2014年07月03日 10:13
  • 3519

HTML+CSS+JavaScript实现简易下拉菜单

html lang="en"> head> meta charset="UTF-8"> title>下拉列表title> link rel="stylesheet" href=...
  • darongzi1314
  • darongzi1314
  • 2016年09月14日 16:17
  • 837

级联下拉菜单的实现

最近在项目中用到了级联菜单,在网上查过资料后,大概有两种实现思路: 1.下拉列表中的数据从数据库中自动获取 2.下拉列表中的每一个选项都写在代码中     相信我们都会选择第一种方法,这样不仅增...
  • yiwangxiblog
  • yiwangxiblog
  • 2016年07月28日 10:24
  • 579

利用jquery、json实现前台无刷新的多级联动下拉菜单

这两天我都在做一个项目,s2sh的一个项目,里面有一个模块需要
  • u011687037
  • u011687037
  • 2014年07月20日 19:24
  • 4220
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:JavaScript解析XML实现多级级联下拉列表
举报原因:
原因补充:

(最多只允许输入30个字)