AspAlliance.com LogoASPAlliance: Articles, reviews, and samples for .NET Developers
URL:
http://aspalliance.com/articleViewer.aspx?aId=1067&pId=-1
Creating a Menu Using XSLT, XML, and JavaScript
page
by Haissam Abdul Malak
Feedback
Average Rating: 
Views (Total / Last 10 Days): 33884/ 65

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.


Product Spotlight
Product Spotlight 

©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-25 3:33:02 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search