Performing the XSL Transformation on menu.xml

As described in Loading XML and XSL Files for Transformation, menu.asp calls the transformNode method on the oXML object that contains the XML file to be transformed by XSL, and passes it the oXSL object containing the XSL file. The following line of code uses the Write method on the ASP Response object to return the result, an HTML stream, to the browser:

Response.Write oXML.transformNode(oXSL)

With this line, program execution leaves menu.asp and continues as the XSL processor generates output by performing transformations on emenu.xml, as specified by menu.xsl.

By definition, an XSL stylesheet is an XML document and must have a single document element at its root. The root of the stylesheet is <xsl:stylesheet>, an intrinsic element in the XSL specification, which the xmlns:xsl attribute references. This makes all elements in the XSL specification available to menu.xsl. The prefix "xsl" indicates to any element in this file that the file follows the referenced specification.

The XSL language provides an XML processor with information on how to transform an XML document from one structure to another. XSL can transform XML into structures other than HTML, including structures that are not yet defined. The menu.xsl file transforms *menu.xml to HTML 3.2, which enables browsers other than Internet Explorer 5 to interpret the output. (The PT Admin application requires the native support for the XML DSO in Internet Explorer 5; the application's menu bar, however, can be reused in downlevel browsers because it performs the XSL processing on the server.)

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">

XSL stylesheets consist of templates that contain patterns. The template is indicated by the <xsl:template> element, and the match attribute indicates the context to which the template is applied. The child operator (/) appearing at the beginning of a pattern indicates that child elements should be selected from the document's root node.

Before the pattern match is specified, however, the code needs to indicate in the <META> tag which character set which will be used by the resulting HTML file. The following uses the <xsl:attribute> element to obtain the character set from the emenu.xml file.

<xsl:template match="/">
<HEAD>
<META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0" />
<META HTTP-EQUIV="content-type">
<xsl:attribute name="CONTENT">text/html ; charset=<xsl:value-of select="//uielement/@charset" /></xsl:attribute>
</META>
<LINK href="../forms.css" rel="stylesheet" type="text/css"/>
</HEAD>

The pattern, written in HTML, follows. This pattern creates a <DIV> element containing a table that holds each menu.

 <!-- BUILD MENUBAR -->
 <DIV ID="divMenuBar">
 <TABLE ID="tblMenuBar" BORDER="0">

Building the Row of Menu Names

The tblMenuBar table contains a single row that results from the execution of a pattern query contained in the <xsl:for-each> element. The code specifies that the XSL processor find each element named menu that has child elements named menuitem. When the processor finds these elements, it uses an <xsl:if> element to ensure that it has not reached the last menu that has menuitems. If the XSL processor has not reached the last menu, it inserts the name of the menu into a <TD> element. The <xsl:attribute> element adds an ID attribute that concatenates the string "tdMenu" with the value of the name attribute in each <menu> element in the *menu.xml tree. The CLASS attribute in the <TD> element, which controls the appearance of the cell containing the menu name, references the cascading style sheet that gate.asp associates with every HTML page it returns to the browser. The following code fragment illustrates this process:

 <TR>
 <xsl:for-each select="//menu[menuitem]">
  <xsl:if test="context()[not(end())]"> 
     <TD CLASS="clsMenuBarItem">
         <xsl:attribute name="ID">tdMenu<xsl:value-of select="@name" /></xsl:attribute>

For the XML element <menu name = "Forms" url = "global">, the following line of HTML results:

<TD CLASS="clsMenuBarItem" ID="tdMenuForms">

The code then attaches <A> tags to each menu item. The ONCLICK attribute that is added next references an ActiveX® Popup control that will contain menu items. The <xsl:eval> element evaluates a script expression to generate a string. The default script language for this element is JavaScript (ECMA 262), but the element's language attribute accepts the same script languages as the HTML <SCRIPT> element. The childNumber function is an XSL helper function. The return value is an integer that indicates the index values for every child node that has the same name. This index is decremented to create an offset index for each Popup control. The ONCLICK event calls the PopUp method of the topNavigator control.

The result is that the value of the ONCLICK attribute for the first <A> element is "topNavigator0.PopUp()".

Finally, the code calls the decode function, which is in a global script block at the end of menu.xsl, to convert the ASCII text of the menu name to its Unicode value. The following code fragment illustrates this process:

         <A TARGET="_new">
            <xsl:attribute name="ONCLICK">topNavigator<xsl:eval>childNumber(this)-1</xsl:eval>.PopUp()</xsl:attribute>
         <xsl:eval>decode(this,'l_name')</xsl:eval>
             <!--<xsl:value-of select="@l_name" />-->
         </A>
     </TD>

<TD>|</TD>
  </xsl:if>

For more information, see Converting Text from Unicode to Character Data with the decode Function.

Note  Throughout the code, you will see the this pointer, which points to the current node being processed in the XML source. Calling DOM methods on the this object allows you to access the node's type, attributes, or child nodes, and to inspect the values of the node and its child nodes.

The next block of code runs if the expression in the nested <xsl:if> element evaluates to TRUE. This code works the same way as the preceding code, except that the last menu shown (from left to right) in each form is a link to the PT application's home page or an online Help file; thus, the <A> tag contains a URL.

  <xsl:if test="context()[end()]"> 
   <TD CLASS="clsMenuBarItem">
         <xsl:attribute name="ID">tdMenu<xsl:value-of select="@name" /></xsl:attribute>
         <A TARGET="_top">
             <xsl:attribute name="HREF"><xsl:value-of select="//topmenu/@rooturl" /><xsl:value-of select="@url" /></xsl:attribute>
             <xsl:eval>decode(this,'l_name')</xsl:eval>
         </A>
   </TD> 
  </xsl:if>
 </xsl:for-each>
 </TR>
 </TABLE>
 </DIV>

Next, the XSL transformation adds items to the Popup object to implement the menus.