65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 XSLT 从 XML 生成多级树形菜单

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.31/5 (9投票s)

2002年3月1日

2分钟阅读

viewsIcon

216496

downloadIcon

1872

一种简单通用的方法,使用 XSLT 从 XML 源生成多级 HTML 树形菜单

Sample Image - TreeFromXMLUsingXSLT.gif

引言

本文将演示一种简单通用的方法,使用 XSLT 从 XML 源生成多级 HTML 树形菜单。JScript 用于展开和折叠菜单项。(这需要至少 Internet Explorer 5。我尚未在任何其他浏览器上进行测试。)

XML 源

这是源 XML 的一个子集(完整的 XML 源在 zip 文件中)。

<menu>
 <entry>
  <text>In-House</text>
  <url>InHouse.htm</url>
  <entry>
   <text>Web Development</text>
   <url>WebDev.htm</url>
  </entry>
 </entry>
</menu>

XSLT

对于每个菜单项,XSLT 处理它,然后向下钻取,直到处理完该项的最后一个子项。

<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
 <xsl:for-each select="//menu/entry">
  <xsl:call-template name="SubMenu">
   <xsl:with-param name="strCSS">Parent IsVisible</xsl:with-param>
  </xsl:call-template>
 </xsl:for-each>
</xsl:template>

<xsl:template name="SubMenu">
 <xsl:param name="strCSS" />
 
 <xsl:variable name="strURL" select="url" />
 
 <div class="{$strCSS}">
  <xsl:choose>
   <xsl:when test="count(entry) > 0">
    <!-- Element has children, it can be expanded -->
    <input type="hidden" id="hidIsExpanded" value="0" />
    <label id="lblExpand" class="Expander" onclick="ExpanderClicked()">+
    </label>
   </xsl:when>
   <xsl:otherwise>
    <label class="Expander">  </label>
   </xsl:otherwise>
  </xsl:choose>
  
  <a href="{$strURL}"><xsl:value-of select="text" /></a>
  <xsl:for-each select="entry">
   <xsl:call-template name="SubMenu">
    <xsl:with-param name="strCSS">NotVisible</xsl:with-param>
   </xsl:call-template>
  </xsl:for-each>
 </div>
</xsl:template>

</xsl:stylesheet>

在服务器上转换 XML

ASP 用于执行 XML 的服务器端转换。

<%
   dim xmlMenu
   dim xslMenu
   
   'Get the source XML
   set xmlMenu = server.CreateObject("Microsoft.XMLDOM")
   xmlMenu.async = false
   xmlMenu.load server.MapPath("TreeFromXMLUsingXSLT.xml")
   
   'Get the XSLT to transform the XML
   set xslMenu = server.CreateObject("Microsoft.XMLDOM")
   xslMenu.async = false
   xslMenu.load server.MapPath("TreeFromXMLUsingXSLT.xsl")
   
   'Transform the source XML using XSLT
   Response.Write xmlMenu.transformNode(xslMenu)
   
   set xmlMenu = nothing
   set xslMenu = nothing
%>

控制菜单项

客户端 JScript 用于首先确定菜单项是已展开还是已折叠,然后调整所选菜单项的样式设置。

<script language="jscript">
function ExpanderClicked()
{
    //Get the element that was clicked
    var ctlExpander = event.srcElement;
    var ctlSelectedEntry = ctlExpander.parentElement;
    //Get all the DIV elements that are direct descendants
    var colChild = ctlSelectedEntry.children.tags("DIV");
    if(colChild.length > 0)
    {
        var strCSS;
        //Get the hidden element that 
        //indicates whether or not entry is expanded
        var ctlHidden = ctlSelectedEntry.all("hidIsExpanded");
      
        if(ctlHidden.value == "1")
        {
            //Entry was expanded and is being contracted
            ctlExpander.innerHTML = "+ ";
            ctlHidden.value = "0";
            strCSS = "NotVisible";
        }
        else
        {
            //Entry is being expanded
            ctlExpander.innerHTML = "- ";
            ctlHidden.value = "1";
            strCSS = "IsVisible";
        }
        //Show all the DIV elements that are direct children
        for(var intCounter = 0; intCounter < colChild.length; intCounter++)
        {
            colChild[intCounter].className = strCSS;
        }
    }
}
</script>

样式设置

CSS 设置用于指定菜单项是应该可见还是隐藏。IsVisible 类将元素设置为显示为块级元素。NotVisible 类将元素设置为隐藏。

body
{
   font-family: Verdana;
   font-size: x-small;
}
.IsVisible
{
   display: block;
}
.NotVisible
{
   display: none;
}
.Expander
{
   cursor: hand;
   font-family: Courier;
}
.Parent DIV
{
   margin-Left: 15px !important;
}

最后一个设置(.Parent DIV)指示只有带有“Parent”类的元素下方的元素才具有边距。这是为了防止根菜单项也具有边距。

使用图像代替 + 和 -

用图像代替每个条目旁边的“+”和“-”非常简单。为此,更改 XSLT 并用 <img> 元素替换链接旁边的 <label> 元素。在 JScript 中,不要设置 ctlExpander 变量的 InnerHTML 属性,而是将 src 属性设置为显示不同的图像。这是一个例子

Sample Image - TreeFromXMLUsingXSLT2.gif

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.