ASP + XML + JavaScript 实现动态无限级联动菜单

结合ASP来完成对数据库值的读取,然后写入XML文件,再用JavaScript读出来并且控制它的联动。

这儿的关键是把数据库内的N层数据类读出来:

我的数据库表结构是这样的:

'tbl_Class

列名 数据类型 长度 说明

ClassID int 4 类ID

ModuleID int 4 模块ID

GroupID int 2 标识一个组

ClassName nvarchar 50 类别名称

ParentID int 2 连接到组(0表示是父类)

'##################我的ASP代码如下####################

'我把连接数据库的代码忽略。

'函数名字:OpenXml(FileName)

'入口参数: filename 需要连接或打开的xml文件名

'返回值 :XmlDoc就是一个成功装载XML文档的对象了。

' 有错误则打印错误信息strError

'------------------------------------------------

function OpenXml(filename)

dim strSourceFile ,XmlDoc,strError

strSourceFile = filename

Set XmlDoc = Server.CreateObject("Microsoft.XMLDOM") '创建XMLDOM实例

XmlDoc.async = false

XmlDoc.load(strSourceFile)

OpenXml=XmlDoc.parseerror.errorcode

if XmlDoc.parseerror.errorcode<>0 then

strError="<h2>error"&XmlDoc.parseerror.errorcode&"</h2>"

strError=strError&XmlDoc.parseerror.reason&"<br>"

strError=strError&XmlDoc.parseerror.url&"<br>"

strError=strError&XmlDoc.parseerror.line&"<br>"

strError=strError&XmlDoc.parseerror.filepos&"<br>"

strError=strError&XmlDoc.parseerror.srcText&"<br>"

response.write strError '输出错误

else

set OpenXml=XmlDoc '返回实例

end if

end function

'------------------------------------------------

'函数名字:CloseXml()

'参数: XmlDoc XML组件实例

'------------------------------------------------

function CloseXml(XmlDoc)

if IsObject(XmlDoc) then

set XmlDoc=nothing

end if

end function

'------------------------------------------------

'函数名字:SelectXmlNode

'参数:XmlDoc XML组件实例

'   e 元素的名字

'返回元素实例

'------------------------------------------------

function SelectXmlNode(XmlDoc,e)

dim n

set n=XmlDoc.selectSingleNode("//" & e )

set selectXmlNode= n

end function

Dim n,np,MaxGroup,root,xmlDoc,nt,filename,s,ss,TorF

filename=server.mappath("demo.xml")

set xmlDoc=openXML(filename)'打开XML

RemoveAllNodes xmlDoc,"Root"'把Root和它下面的子项清除,这样可以多次方便读写

set root= xmlDoc.createElement("Root")

xmlDoc.appendChild root'创建一个顶层元素

sql="select Max(GroupID) from tbl_Class " '读出最大的层次

set rs=cn.execute(sql)

if isnull(rs(0)) then MaxGroup=0 else MaxGroup=rs(0) '如果为null 表示没有数据

s="":ss=""

set nt=xmldoc.createElement("item")

nt.setAttribute "text", "请选择"

root.appendChild nt '创建一个元素

for i=1 to MaxGroup '开始循环

sql="select * from tbl_Class where Group由底层向顶层读取

set rs=cn.execute(sql)

TorF=False '为了每一个层上都创建一个“请选择”的空取。

do while rs.eof =false '开始读取下层的数据

Set n = xmlDoc.createElement("item" & rs("ClassID")) '创建一个命名为item + ID号的标记元素

n.setAttribute "text",rs("ClassName")'把它的属性“text”设置为数据库表内的

ClassName

n.setAttribute "value",rs("ClassID")'把它的属性“value”设置为数据库表内的

ClassID

if rs("ParentID")>0 then '是有上层数据的

set np=selectXmlNode(xmlDoc,"item" & rs("ParentID")) '把它的上层数据元素先读出保存在np

if TorF=false then '如果TorF为False值时

set nt=xmldoc.createElement("item") '创建一个元素保存在nt

nt.setAttribute "text", "请选择"'把它的text属性设置为“请选择”

np.appendChild nt 'np把它加为子元素

end if

TorF=true '设置true

np.appendChild n 'np 把n加为子元素

else

root.appendChild n '如果是第一层数据就把它加入为root下的一个子元素

end if

rs.movenext '下一条指针

loop

ss=ss & "<SELECT & i & " width=1 ></SELECT></span>" '每有一层就创建一个

<select>

s=s & ",'Select" & i & "'" '把每个<select>的id 保存在变量s,它的格式为:id1,id2,id3,id4

next

xmlDoc.save filename '正式保存Xml文件

CloseXml xmlDoc '关闭Xml文件

response.write ss '直接把<select>输出到文档

s=mid(s,2)

//在HTM文件内调用xmlselect.js

<SCRIPT language=JavaScript src="xmlselect.js"></SCRIPT>

<SCRIPT language=JavaScript>

<!--//** power by fason

function init() {

var Sel = [<%=s%>];

attachSelect("demo.xml", Sel,["论坛导航"]);

};//-->

</SCRIPT>

init();

//#########我把它的JS代码贴出来,作者叫:蒲佛信,http://fason.nease.net/samples/xmlselect/这儿有示例和代码。

//-----------------------------xmlselect.js文件开始-------------------------------

//-----------------------------------------------------/

// NichName :fason

// Autho :Forbes Pu(蒲佛信)

// Email :fason_pfx@hotmail.com

// HomePage :http://fason.nease.net

// Blog :http://blog.mvpcn.net/fason/

// http://blog.csdn.net/fason/

//

// function :attachSelect(sXMLSrc, aSel[, sStore])

// param1 :sXMLSrc(URL of XML data source)

// param2 :aSel(array of SELECT controls's ID)

// param3 :array of default value when display

//-----------------------------------------------------/

function attachSelect(sXMLSrc, aSel, sStore) {

var oXML = CreateXmlDocument();

var oDocument = null;

var store = sStore ? sStore : [];

var Sel = new Array();

for (var i=0; i<aSel.length; i++)

Sel[i] = document.getElementById(aSel[i]);

if (!oXML){ throw new Error('Not support!\nplease install a XML parser');return; }

oXML.onreadystatechange = function () {

if (oXML.readyState == 4) {

attachXML();

}

};

oXML.load(sXMLSrc);

function CreateXmlDocument() {

if (document.implementation && document.implementation.createDocument) {

var doc = document.implementation.createDocument("", "", null);

if (doc.readyState == null) {

doc.readyState = 1;

doc.addEventListener("load", function () {

doc.readyState = 4;

if (typeof doc.onreadystatechange == "function")

doc.onreadystatechange();

}, false);

}

return doc;

}

else if (window.ActiveXObject) {

var prefix = ["MSXML3","MSXML2","MSXML","Microsoft"];

for (var i=0;i<prefix.length;i++) {

try {

var doc = new ActiveXObject(prefix[i] +

".DomDocument");

doc.setProperty("SelectionLanguage","XPath");

return doc;

} catch (e) {}

}

}

return null;

};

function attachXML() {

oDocument = oXML.documentElement;

if (!oDocument) { throw new Error('No XML data!'); return; }

for (var i=0;i<aSel.length-1;i++){

addEvent(Sel[i], "onchange", function(x) {

return function () { doChange(x); }

}(i+1));

}

doChange(0);

};

function selectXMLNode(x) {

var sPath = "/*";

var oDoc = oDocument;

for (var i=0;i<x;i++)

sPath += "/*[" + (Sel[i].selectedIndex+1) + "]";

if (typeof(oDoc.selectSingleNode)!='undefined') return

oDoc.selectSingleNode(sPath);

else {

var doc=oDoc.nodeType==9?oDoc:oDoc.ownerDocument;

var res = doc.createNSResolver(oDoc.nodeType==9?

oDoc.documentElement:oDoc);

return doc.evaluate(sPath,oDoc, res, 9, null).singleNodeValue;

}

};

function addEvent(el, sHandler, fnc) {

if (el.attachEvent) {

el.attachEvent(sHandler, fnc);

} else if (el.addEventListener) {

el.addEventListener(sHandler.replace(/on/i, ''), fnc, false);

} else {

el[sHandler] = fnc;

}

};

function doChange(n) {

var el = selectXMLNode(n);

var nodes = el ? el.childNodes :[];

var s = Sel[n];

var f = 0;

if (nodes.length>0) {

with (s){

length = 0;

for (var i = 0,j = 0;i<nodes.length;i++) {

if (nodes[i].nodeType!=1)continue;

var t = nodes[i].getAttribute("text");

var v = nodes[i].getAttribute("value") ? nodes

[i].getAttribute("value") : t;

if (v == store[n]) f = j;

options[j++] = new Option(t, v);

}

options[f].selected = true;

}

if (++n<Sel.length) doChange(n);

} else {

for (var i=n; i<Sel.length; i++) {

with (Sel[i]) {

length = 0;

options[0] = new Option('--');

options[0].selected = true;

}

}

}

};

};

//-----------------------------xmlselect.js文件结束-------------------------------