4.4.构造显示树型结构的XSL模版 在上面的demotree.xml,是不能单独显示出如图一一样的树结构的,需要把XML文件用XSL模版来转换。 在这里实际上需要把XML文档用模版格式为以下样式: <ul> <li></li> <li></li> <ul> <li></li> <li></li> </ul> </ul> 每一个li表示一个子节点,ul表示其上的li为一树杈,其下的li为其子节点,可能为树杈,可能为叶子,取决于该子节点是否具有ul。 XSL模版功能定义着如何转化嵌套的node节点为嵌套的ul和li表示。 模版转化的关键代码: <xsl:template match="node"> <xsl:for-each select=".[number(layer) $eq$ 0 ]"><!—对于每一个节点,如果他的layer值为0,进行下面的代码变化--> <xsl:if test=".[href $eq$ '']"><!—如果节点的href域为空,说明其为树杈,需要检索其下面的嵌套node--> <xsl:element name ="li"><!—对于li标签,不仅仅是指定其id为goldheader,还指定其序号no为该节点的id值--> <xsl:attribute name="id">foldheader</xsl:attribute> <xsl:attribute name="no"><xsl:value-of select="id"/></xsl:attribute> <xsl:value-of select="value"/> </xsl:element> …… </xsl:if> <xsl:if test=".[href $ne$ '']"> <!—如果节点的href域不为空,说明其为叶子,转换为li格式,并把链接,目标框架,显示字符串的值以超链接的形式显示出来--> <li><xsl:element name ="a"> <xsl:attribute name="HREF"> <xsl:value-of select="href"/> </xsl:attribute> <xsl:attribute name="TARGET"> <xsl:value-of select="target"/></xsl:attribute> <xsl:value-of select="value"/> </xsl:element> </li> </xsl:if> </xsl:for-each> </xsl:template> 因为浏览器对XSL支持的不同,所以在目前的浏览器使用比例上言,MSIE是可以作为默认浏览器标准来定义的,在不安装MSXSL3的情况下,MSIE只是支持XSL2,对XSL变量等不支持,所以,在这里的实现过程中以嵌套的代码来实现替换变量实现的效果。整体的代码比较冗长,但易于读写和修改。不对代码进行重复,具体请参见treefunc.xsl文件中从<xsl:template match="node">开始到</xsl:template>结束的中间的代码实现。 树状显示还依赖于js的支持,js定义着点击树杈时树的显示变化,例如,当当前点击树杈节点为收缩状态时,点击的效果是展开该树杈,显示树杈的下级节点,反之亦然。 首先对ul和li进行类的标识,对于树杈的li,定义其元素的id为’ foldheader’,对于其下跟随的ul定义其元素的id为’ foldinglist’,style.display为’none’或者’’,然后定义一个change函数,功能为点击树杈节点后的界面变化。 同时因为树结构的层次可能会比较深,需要考虑到客户浏览时,在刷新页面或者重新开启同一页面时应该保存住客户最后浏览的树的层次,在这里实现的方式是用cookie保持每个树杈的是否展开的布尔值, 对cookie的操作函数和对点击事件的操作函数都在treefunc.xsl文件中,下面是javascript编写的对XML生成树进行HTML动作处理的方法, /*说明是在载入页面时就要发生的动作*/ var temp_str = 'thexmltreecookie';/*定义一个字符串,用于在cookie中查找节点展开状态*/ var fl_n = 0; temp_str = temp_str + "="; for (i=0;i<foldinglist.length;i++){/*把所有的树杈都预设为未展开,并统计个数*/ temp_str=temp_str+"0:"; } temp_str = temp_str.substring(0,temp_str.length-1); fl_n = temp_str.length -17 ; if ((document.cookie == '')||(WM_readCookie('thexmltreecookie').length != fl_n)){/*当cookie不为空,而且cookie中有正确对应的树杈个数,读取cookie中保存的树杈状态*/ document.cookie = temp_str;/*检验cookie中值不为正确,则赋予新值*/ } else { /*cookie中保存的树杈状态形如”1:0:0:0:1”,这表示第一和第五节点是展开的,第二,三,四节点是收缩的,这种形式并没有保存树的层次属性,所以,这里的节点展开没有一一反应到树的表现上来,例如:如果第五节点是第四节点的子节点,那么尽管第五节点是展开的,但因为父节点未展开,所以在查看树时,是不可能看到第五节点的,只有当第五节点的父节点,祖父节点,直到顶层节点都为展开状态,第五节点才为可视的展开状态.这里用函数WM_readCookie()方法取得树杈状态字符串,并把它按’:’分开,放入数组temp_s中*/ var temp_s = WM_readCookie("thexmltreecookie").split(":"); /*从第一个树杈开始,根据树杈字符串相应位置的取值,设置该树杈节点的显示属性*/ for (i=0;i<foldinglist.length;i++){ if (temp_s[i] == 0){ var tb =0; for (j=0;tb < 1;j++){ if (document.all[j] == foldinglist[i]){ tb = 1; document.all[j-1].style.listStyleImage="url(/images/fold.gif)"; } } foldinglist[i].style.display="none"; } else { var tb =0; for (j=0;tb < 1;j++){ if (document.all[j] == foldinglist[i]){ tb = 1; document.all[j-1].style.listStyleImage="url(/images/open.gif)"; } } foldinglist[i].style.display=""; } } }
/*函数changge()是点击页面时触发的动作,*/ function change(){ /*点击的对象是页面上的元素动作才继续*/ if(!document.all) return; /*由temp_ss数组得到树杈节点的展开属性*/ var temp_ss =WM_readCookie("thexmltreecookie").split(":"); var temp_s = 'thexmltreecookie'; temp_s = temp_s + '='; /*如果点击元素是树杈,则继续动作,这里判断是否树杈是通过判断点击对象的id是否为foldheader*/ if (event.srcElement.id=="foldheader") { /*srcIndex赋值为点击HTML元素的在HTML文档中的序号*/ var srcIndex = event.srcElement.sourceIndex; /*nested赋值为点击元素的下一个元素,是<ul>元素,树杈节点的控制元素,通过控制该元素的属性可以控制该树杈是否显示和显示的图片*/ var nested = document.all[srcIndex+1]; /*遍历树杈节点,作用是当点击的对象是遍历到的HTML元素时,做相应的变化,如,更改cookie中树杈状态字符串,使点击的节点展开或缩回其子节点,在cookie中保存当前点击节点的Id值*/ for (i=0;i<foldinglist.length;i++){ if (foldinglist[i] == nested){ /*定义变量ClickId,保存点击对象的no属性,no属性是指该节点在XML中取得的id属性值*/ var ClickId; ClickId = "ClickId="+event.srcElement.no; document.cookie =ClickId; if (temp_ss[i]==0){ temp_ss[i]=1; } else { temp_ss[i]=0; } } } for (i=0;i<foldinglist.length;i++){ temp_s =temp_s+temp_ss[i]+':'; } temp_s = temp_s.substring(0,temp_s.length-1); document.cookie = temp_s; /*更换相应的图片*/ if (nested.style.display=="none") { nested.style.display='' event.srcElement.style.listStyleImage="url(/images/open.gif)" } else { nested.style.display="none" event.srcElement.style.listStyleImage="url(/images/fold.gif)" } /*刷新其他的页面*/ top.topFrame.location.reload(); } } /*指定在页面中点击事件的处理函数为change()*/ document.onclick=change; /*函数WM_readCookie(name)用来调用WM_getCookieValue(name)取得在cookie中以name为名称的cookie串的值*/ function WM_readCookie(name){ //如果没有cookie则返回false或者取得值并返回该值 if(document.cookie == ''){ return false; } else { return unescape(WM_getCookieValue(name)); } }
|