Creating a Menu Using XSLT, XML, and JavaScript
 
Published: 27 Nov 2006
Abstract
In this article you will be introduced to XSL technology and its direct effect on your web applications. Integrating JavaScript with XSL will give you the ability to control your application on the client side without making your users wait until the page is processed on the server.
by Haissam Abdul Malak
Feedback
Average Rating: 
Views (Total / Last 10 Days): 52192/ 117

Introduction

Extensible Stylesheet language (XSL) is a language used to express style sheets.  You use XSL to define how data should be displayed, styled and laid out.  It was developed with the need of creating XML based Stylesheet language.

XSL is based on three concepts as described below.

·         Extensible Stylesheet Language Transformation (XSLT) is a language to transform the xml document into html, text or even another xml file.

·         XPath is a language to navigate through elements, attributes and elements' values in xml documents.

·         Extensible Stylesheet Language Formatting (XSL:FO) is a language for formatting xml documents.

This article assumes that you have a minimum understanding of the XSL functionality in order to keep up with this demonstration.  For more information please visit http://www.w3schools.com/xsl/xsl_intro.asp.

In this article we will create a horizontal menu.  This menu contains main items.  Once any item is clicked, sub items will be shown or hidden beneath the item clicked.  All the items and sub items are being read from an XML document which makes modifying the menu an easy job to do.

To create this menu we have to complete the following steps.

·         Create an XML document containing the items and sub items to be shown in the menu.

·         Create an XSL file which will navigate through the XML document.

Add C# code that will transform the XSL and the XML into an HTML document or use the XML server control found in ASP.NET.

XML Document

In this section we will create an XML document (Menu.xml) with "MenuItems" as the root element.  Place the items you want to show in the menu under the root element then create under each item its proper sub items. (In this example we will have four items as main menu items and each one will have three sub items.)  Here is how the XML document will look when it is finished.

Listing 1

<?xml version="1.0" encoding="utf-8" ?> 
<MenuItems>
<Item1>
<SubItem>FirstSubItem1</SubItem>
<SubItem>FirstSubItem2</SubItem>
<SubItem>FirstSubItem3</SubItem>
</Item1>
<Item2>
<SubItem>SecondSubItem1</SubItem>
<SubItem>SecondSubItem2</SubItem>
<SubItem>SecondSubItem3</SubItem>
</Item2>
<Item3>
<SubItem>ThirdSubItem1</SubItem>
<SubItem>ThirdSubItem2</SubItem>
<SubItem>ThirdSubItem3</SubItem>
</Item3>
<Item4>
<SubItem>ForthSubItem1</SubItem>
<SubItem>ForthSubItem2</SubItem>
<SubItem>ForthSubItem3</SubItem>
</Item4>
</MenuItems>
XSL Document

We will create an XSL document (Menu.xsl) containing the code to navigate through the XML document (using XPath) already created in the above step, read the element values, and apply the necessary formats.

First of all, we will read the main nodes without their corresponding child element and then for each main node we will place the children elements in a DIV Layer just beneath its position.  By default, the entire sub children elements will be hidden and we will show them only when they are requested using JavaScript

Below is the XSL document which will be explained step by step later on in this article.

Listing 2

<?xml version="1.0" encoding="iso-8859-1"?> 
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:asp="http://www.microsoft.com"> 
<xsl:output method="html" indent="yes" encoding="iso-8859-1"/> 
<xsl:template match="MenuItems/*">
<xsl:variable name="NodeName">
<xsl:value-of select="name(current())"/>
</xsl:variable>   
/xsl:template>
</xsl:stylesheet>

The code in bold will create a variable that holds the name of the root element children without its sub children elements (Item1, Item2, Item3).

Listing 3

<xsl:variable name=”NodeName”></xsl:variable> 

In the above line of code we are defining a variable with a name “NodeName” so that we can reference it later when it is needed.

Listing 4

<xsl:value–of select=”name(current())”></xsl:variable>

The above statement will store the name of the current node in the variable.

Now, we will create one table containing the nodes’ name in the NodeName variable.  We will display each node name in a row.  The code in bold in the listening below will demonstrate how to do this task.

To get the values in a variable you have to add the "$" sign before variable name.

Listing 5

<html>
<body>
<table border="1" width="150px" >
<tr>
<td align="Center"><xsl:value-of select="$NodeName"/></td>
</tr>
</table>
</body>
</html>

Figure 1: Table holding main menu items


The above figure shows the table with four rows containing the values of the variable.

Now we will create for each node a table containing its children element.  We will insert this table inside a div layer which will be hidden by default.

Listing 6

<div style="OVERFLOW:AUTO; width=150px;height=100px; display:none" runat="server" id="{$NodeName}" >
<xsl:for-each select="node()">
<table>
<xsl:variable name="ChildNodeName">
<xsl:value-of select="./child::node()"/>
</xsl:variable>
<td width="150px" align="center"><xsl:value-of select="$ChildNodeName"/></td>
</table>
</xsl:for-each>
</div>

The code in bold will loop through each node in the XML document, store its child elements inside a new variable named "ChildNodeName" and display each element in a row of the second table.

Listing 7

<xsl:value-of select="./child::node()"/> 

The above statement uses XPath (./child::node()) whose purpose is to get the child nodes of a specific node.

Note, for each div layer we are assigning a different id; this id will be the same as the node name.

After completing the above steps, we have to integrate JavaScript to show or hide the div layer containing the children elements when the user clicks on a specified node.

Listing 8

<script lang="javascript" type="text/javascript" >
 function HideShowDiv(divid)
 {
      var divlayer = document.getElementById(divid);
      if(divlayer.style.display == "block")
      {
      divlayer.style.display = "none";
      }
      else
      divlayer.style.display = "block"
 }
  function ChangeBg(tdid)
  {
  var td = document.getElementById(tdid);
  td.style.background = "#3399ff";
  td.style.color= "white";
  }
  function ReturnBg(tdid)
  {
  var td = document.getElementById(tdid);
  td.style.background = "white";
  td.style.color = "black";
  }
  </script>

The HideShowDiv(divid) function checks whether the div layer is hidden and shows it and vice versa.  It accepts as parameter the div layer id which stored in the NodeName variable.

The ChangeBg(tdid) function will change the background and text color onmouseover event of the <td> in the second table.

The ReturnBg(tdid) function will bring the background and text color back to their original values onmouseleave event.

Those functions take as parameter the id which will always be stored in the ChildNodeName variable.

Modify the <td> tag of the second table to look like the same as the code below.

Listing 9

<td onmouseover="ChangeBg('{$ChildNodeName}')" id="{$ChildNodeName}"
 onmouseleave="ReturnBg('{$ChildNodeName}')" width="150px"
 align="center"><xsl:value-of select="$ChildNodeName"/></td>

This is how the XSL Document should look:

Listing 10

<?xml version="1.0" encoding="iso-8859-1"?> 
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:asp="http://www.microsoft.com"> 
<xsl:output method="html" indent="yes" encoding="iso-8859-1"/> 
<xsl:template match="MenuItems/*">
<xsl:variable name="NodeName">
<xsl:value-of select="name(current())"/>
</xsl:variable>
<html>
<head>
<script lang="javascript" type="text/javascript" >
 function HideShowDiv(divid)
 {
      var divlayer = document.getElementById(divid);
      if(divlayer.style.display == "block")
      {
      divlayer.style.display = "none";
      }
      else
      divlayer.style.display = "block"
 }
  function ChangeBg(tdid)
  {
  var td = document.getElementById(tdid);
  td.style.background = "#3399ff";
  td.style.color= "white";
  }
  function ReturnBg(tdid)
  {
  var td = document.getElementById(tdid);
  td.style.background = "white";
  td.style.color = "black";
  }
  </script>
</head>
<body>
<table border="1" width="150px" >
<tr>
<td onmousedown="HideShowDiv('{$NodeName}')" align="Center"><xsl:value-of select="$NodeName"/></td>
</tr>
</table>
<div style="OVERFLOW:AUTO; width=150px;height=100px; display:none" runat="server" id="{$NodeName}" >
<xsl:for-each select="node()">
<table>
<xsl:variable name="ChildNodeName">
<xsl:value-of select="./child::node()"/>
</xsl:variable>
<td onmouseover="ChangeBg('{$ChildNodeName}')"
 id="{$ChildNodeName}" onmouseleave="ReturnBg('{$ChildNodeName}')"
 width="150px" align="center"><xsl:value-of select="$ChildNodeName"/></td>
</table>
</xsl:for-each>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

Code Behind

You have two ways to achieve the transformation.

A. By adding code to the code behind page

Include the namespaces below to be able to use the classes for XML and XSL:

Listing 11

using System.Xml;
using System.Xml.Xsl;

The code below will create an instance of the XmlDocument class and load the already created XML document, create an instance of the XslTransform class, load the already created XSL document and use the XmlTextWriter class to write the output into HTML.

Use the Transform method of the XslTransform class to make the transformation.

Add to the Page_Load event the code below:

Listing 12

// Create an instance of the XmlDocument class and load the xml file already created
  XmlDocument xmlDoc = new XmlDocument(); 
  xmlDoc.Load(Server.MapPath("./Menu.xml"));
      
// Create an instance of the XslTranform class and load the xsl file already created
  XslTransform xslTran = new XslTransform();
  xslTran.Load(Server.MapPath("./Menu.Xsl"));
// Write the transformation into a new html 
  XmlTextWriter htmlWriter = 
new XmlTextWriter(Server.MapPath("./output.html"),   
System.Text.Encoding.UTF8);
htmlWriter.Close();
// the XslTransform class contains a method Transform to transform the xml into html.
xslTran.Transform(xmlDoc, null, Response.OutputStream);

B. By using XML server control

If you want to use the XML server control without adding code to the page behind, drag and drop the XML server control from the toolbox under the WebForms tab, Right click it and select properties, click on the DocumentSource and add the XML document, click on the TransformSource and add the XSL file then run your project.

Below is a snapshot of what your menu will look like after completing all the stages mentioned above.

Figure 2: Shows the child elements of the first node in the XML document

         

To customize your menu, just modify the XML file elements and run the project.

Conclusion

In this article you saw how easy it is for a developer to apply transformation for an XML document by taking advantage of the XSL technology, which is becoming a must in a world where XML is becoming a necessity in all applications.



User Comments

Title: something   
Name: else
Date: 2012-12-17 5:55:34 PM
Comment:
yay its a comment
Title: 2012 NFL jerseys   
Name: NIKE NFL jerseys
Date: 2012-05-20 11:32:31 PM
Comment:
[/pre]Cheap NFL,NBA,MLB,NHL
[url=http://www.jersey2shop.com/]Jerseys From China[/url]
[url=http://www.jersey2shop.com/]2012 nike nfl Jerseys[/url]
[url=http://www.jersey2shop.com/]cheap China Jerseys[/url]
[url=http://www.jersey2shop.com/]Sports Jerseys China[/url]
[url=http://www.jersey2shop.com/NFL-Jerseys-c68/]NFL Jerseys China[/url]
[url=http://www.jersey2shop.com/NBA-Jerseys-c77/]NBA Jerseys China[/url]
NHL Jerseys China
[url=http://www.jersey2shop.com/MLB-Jerseys-c94/]MLB Jerseys China[/url]NFL jerseys For Sale online.All Our Jerseys Are Sewn On and Directly From Chinese Jerseys Factory
[/pre]
[pre]We Are Professional China jerseys Wholesaler
[url=http://www.cheapjersey2store.com/]Wholesale cheap jerseys[/url]Cheap mlb jerseys
[url= http://www.cheapjersey2store.com/]2012 mlb all atar jerseys[/url]
[url= http://www.cheapjersey2store.com/ [/url]Cheap China Wholesael[/url]
[url= http://www.cheapjersey2store.com/]Wholesale jerseys From China[/url]
[url=http://www.cheapjersey2store.com/]2012 nike nfl Jerseys[/url]Free Shipping,Cheap Price,7 Days Deliver
[/pre]
[/pre]
We are professional jerseys manufacturer from china,wholesal
sports [url= http://www.cheapjersey2store.com/]Jerseys From China[/url]
[url=http://www.cheapjersey2store.com/NFL-Jerseys-c68]NFL jerseys China[/url]
[url=http://www.cheapjersey2store.com/NHL-Jerseys-c96/]NHL Jerseys China[/url]
[url=http://www.cheapjersey2store.com/NBA-Jerseys-c77/]NBA Jerseys China[/url]
[url=http://www.cheapjersey2store.com/MLB-Jerseys-c94/]MLB Jerseys China[/url]
[url= http://www.cheapjersey2store.com/]China Jerseys[/url],Free Shipping
[/pre]
[/pre]
We are professional jerseys manufacturer from china,wholesal
sports [url= http://www.jerseycaptain.com/]cheap jerseys sale online [/url]
[url= http://www.jerseycaptain.com/]2012 nike nfl Jerseys[/url]
[url=http://www.jerseycaptain.com/NFL-Jerseys-c68]cheap NFL jerseys China[/url]
[url=http://www.jerseycaptain.com/NHL-Jerseys-c96/]NHL Jerseys C
Title: hyperlink   
Name: pl
Date: 2009-11-12 3:21:59 AM
Comment:
Hi,

I would like to know how to make hyperlink for each items.

Could you show it to me?

Thank you.
Title: XSLT   
Name: Maheswari
Date: 2009-06-18 5:44:39 AM
Comment:
The Articles is very usefull to understand the concept but i want to store the xslt into the cache for further usage.Those details are not available in this.Can u pls provide the details??
Title: Menu items   
Name: deepali
Date: 2009-05-12 1:52:19 AM
Comment:
hey,
it's really a nice code. But want to know that how can i fatch a perticular item in menu from XML
Title: Menu items   
Name: Milind
Date: 2008-12-16 6:52:40 AM
Comment:
Hii actualyy i wanted to create a dynamic menu using xml & make templates of dat menu(sort of reusability or for flexibility) how can i do dat(like we do using .resx file in .net) pls help me.
Title: Nellre   
Name: Nuthan
Date: 2008-07-26 5:12:47 AM
Comment:
Glad to inform you

Thakns
Nuthan
Title: ComboBox   
Name: XSL_KID
Date: 2008-07-03 9:51:56 AM
Comment:
Hi WANT TO DO THE SAME THING THE AUTHOR HAS EXPLAINED. But I want to use combo box instead building menu. Can some one point to right source for help. The completely new to creating xsl documents and this article is great. Easy to follow and understant what he is doing. Any help is greatly appreciated.
Title: SSL   
Name: Rafi
Date: 2008-01-10 2:41:46 PM
Comment:
How to apply SLL in Asp.Net 2.0 Projects.

I want complete solution.


Thanks and Regard
Title: Thank you   
Name: Haissam Abdul Malak
Date: 2007-11-09 3:56:35 AM
Comment:
Glad to hear that it helped you :)
Title: a   
Name: a
Date: 2007-11-09 2:53:13 AM
Comment:
Thank you
Title: Nice! it help me   
Name: Aswattha
Date: 2007-07-12 4:51:23 AM
Comment:
Nice topic,
Thank you
Title: Creating a Menu Using XSLT, XML, and JavaScript   
Name: Fred
Date: 2007-05-25 1:36:36 AM
Comment:
Excellent article!
Even though it was written awhile ago and little things have changed, it's still the best explanation I've found on the web. You should expand & update this one (like XslCompiledTransform should now be used instead of XslTransform). Thanks again for a great article!
Title: how to display horizontal menu uisng XML,XSL and JavaScript   
Name: ASHA
Date: 2007-03-12 2:25:44 AM
Comment:
Please Give article on building horizontal menu using XML,XSL and JavaScript
Title: nice article   
Name: jonathan parker
Date: 2007-02-28 4:51:30 PM
Comment:
Haissam, great article, thanks for taking the time to share some of your knowledge! keep up the good work. -- jp
Title: Fine   
Name: Justin Check
Date: 2007-02-09 5:02:24 AM
Comment:
It is very nice
Title: Nice   
Name: Joydip
Date: 2007-01-04 12:40:25 AM
Comment:
Excellant article. Please find my articles at http://aspalliance.com/author.aspx?uId=58780
Title: Re:resulting HTML is Dirty with many HEAD Body ,Script file   
Name: Haissam Abdul Malak
Date: 2006-12-08 5:32:39 PM
Comment:
Thank u patil for your notice, i was busy these days anyway i took a quick look over the project and i saw the dirty html. As soon as i can, i will solve this and get back to u.

Best Regards
Title: resulting HTML is Dirty with many HEAD Body ,Script file   
Name: patil
Date: 2006-12-07 2:20:33 AM
Comment:
See the view source of the resulting HTML which is Dirty with many HEAD Body ,Script section repeated many times
Title: Thank U   
Name: Haissam Abdul Malak
Date: 2006-12-03 6:44:24 AM
Comment:
i would like to let you know that all your comments are appreciated.

Best Regards,
Title: Congrats   
Name: Nehme Gedeon
Date: 2006-12-03 3:52:42 AM
Comment:
Great article man, Clear and very easy to understand.

Congrats,

Nehme
Title: Great Idea   
Name: Rana D
Date: 2006-12-01 1:29:18 PM
Comment:
What you have just turned the light on is one of the problems we always face and try to solve. It is a great way of Solving or analyzing it this way and I want to congratulate you. We faced this problem and i suggested your idea, and we used both: your way when the xml is not a big file and user control as Keyvan Nayyeri said it is large.
Thus, I would like to thank you ;) and keep your efforts on, we will need them one day.
Best Wishes!
Title: Lecturer   
Name: Kumar
Date: 2006-11-30 5:17:44 AM
Comment:
It is very useful
Title: Thank you   
Name: Haissam Abdul Malak
Date: 2006-11-29 9:21:00 AM
Comment:
Thank u guys for your comments, i hope this article was informative.

Best Regards,
Title: Congratulations   
Name: Bilal Hadiar [MVP]
Date: 2006-11-27 6:05:10 AM
Comment:
Congratulations for your first article Haissam!!

It is nice to see the interaction between XSLT + JavaScript!!

Good luck and looking for more articles ;)

Regards
Title: Re:Caching   
Name: Haissam Abdul Malak
Date: 2006-11-27 1:44:00 AM
Comment:
Dear,
the purpose of this article was to show a demonstration about XSLT capabilites eventhough you are right.

Thank you for your comment.
Title: Caching   
Name: Keyvan Nayyeri
Date: 2006-11-27 12:34:45 AM
Comment:
Haissam,

Don't forget an important point here. Using XSL Transforms to build a menu can have a performance cost (especially for large XML files and complicated transforms) so it's absolutely better to apply this in a user control and use cache on server to improve performance.

Good article :-)

Product Spotlight
Product Spotlight 





Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2018 ASPAlliance.com  |  Page Processed at 2018-12-12 1:21:29 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search