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






4.31/5 (9投票s)
2002年3月1日
2分钟阅读

216496

1872
一种简单通用的方法,
引言
本文将演示一种简单通用的方法,使用 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
属性设置为显示不同的图像。这是一个例子
许可证
本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。
作者可能使用的许可证列表可以在此处找到。