Transforming Microsoft Access XML Files into HTML with XSLT

This content is no longer actively maintained. It is provided as is, for anyone who may still be using these technologies, with no warranties or claims of accuracy with regard to the most recent product version or service release.

 

Frank C. Rice
Microsoft Corporation

July 2001

Applies to:
     Microsoft® Access 2002
     Microsoft Internet Explorer 5.0 (and later)
     Microsoft XML Parser 3.0
     Microsoft Visual Basic® Scripting Edition

Summary: This article explains what XSLT is and how it can be used to transform XML data from one format to another. These examples lead the reader through an XSLT style sheet to transform a Microsoft Access 2002 database file into HTML. The code also demonstrates how to use XSLT to display data in two distinct formats by using VBScript. (27 printed pages)

Download ODC_Acc2XSLT.exe.

Contents

Introduction
An Overview of the Transformation Process
An Example of an XSLT Style Sheet
Transforming an XML data file
XML/XSL Processors
Using Multiple Style Sheets with VB Script
Error Handling and XSLT
Conclusion
Additional Resources
Glossary

Introduction

One of the advantages of using the Extensible Markup Language (XML) as a way to move data between different applications is the ease of transforming XML data into other formats and structures. For example, you may need to transform the information on an inventory of new ski clothing and accessories—currently stored in a flat file as XML—into a Hypertext Markup Language (HTML) file for use on your company's Sales Web site. Or, you may need to restructure the XML-based financial data in your organization so that the same data can be used in other markup languages, such as the Financial Products Markup Language (FPML) and the Financial Markup Language (finML), for tax accounting and international money transactions. Microsoft Access 2002 provides such support for XML by allowing you to export and import data to XML files. The "mechanism" used to accomplish these transformations is an XML-based language called XSL Transformations (XSLT).

XSLT is a subset of another XML-based markup language, the Extensible Stylesheet Language (XSL). Whereas XSL is primarily used to define the formatting and presentation of XML documents, XSLT style sheets consist of a series of template rules and commands used to select and manipulate the structure of the data. The combination of XSL and XSLT provides a display template for an XML document.

This article explains the steps for using XSLT to transform XML data from one format to another. It explains how to convert a sample Access 2002 XML data file to HTML using an XSLT style sheet. It also demonstrates how to display the same XML data in different ways by using multiple XSLT style sheets with a scripting language.

This article assumes that you have a basic understanding of XML and the terms used to describe XML-related files. A glossary of common XSLT-related terms is provided at the end of this article. In addition, the Microsoft Online XML Developer Center provides a great resource for information on XML.

An Overview of the Transformation Process

To understand how XSLT works, we need to look at how XML-enabled browsers such as Microsoft Internet Explorer 5.0 or later handle XML data. When you open an XML data file in an XML-enabled Web browser, the browser uses a built-in parser, such as the Microsoft XML Parser (MSXML), to parse the elements of the XML document into a tree-like structure. For example, let's look at a fragment of a sample XML document created by exporting the "Employees" table from Access 2002. (Instructions for exporting data from Access 2002 to an XML file are described later in this article; in addition, all of the sample code described in this article is available in the accompanying download.)

<?xml version="1.0" encoding="UTF-8" ?>
<dataroot>
    <Employees>
        <EmployeeID>1</EmployeeID>
        <LastName>Davolio</LastName>
        <FirstName>Nancy</FirstName>
        <Title>Sales Representative</Title>
    ...

This document fragment would be parsed into a tree structure as illustrated in Figure 1:

Aa139949.odc_acc2xslt(en-us,office.10).gif

Figure 1. Example of Employees data as a tree structure

Notice that it isn't the data but the elements containing the data that are being manipulated by the parser. It's also worth noting that the parsing and transformation are being done in memory and not in the input file. Thus the physical input file remains untouched by the transformation, enabling you to use the same input data for any number of transformations.

Once the input data has been parsed, stored in memory, and then restructured, the browser looks for a reference to an XSLT file. If the input file contains either a reference to an XSLT document or a scripting command to load an XSLT document, the browser parses the XSLT file into memory, also as a tree structure. The browser then uses a built-in processor to apply the XSLT tree structure to the XML data tree structure to perform the transformation. So in addition to its functions as a browser and an XML parser, an XML-enabled browser such as Internet Explorer also contains an XSL processor.

If no XSL/XSLT (or other style sheet) reference exists in the input XML data file, the data is displayed as raw XML or in another default structure, depending on the browser used. As you'll see, Internet Explorer 5.0 and later have a default XSL style sheet that displays XML files as an expandable tree-like structure when no XSL/XSLT file is specified.

During the transformation, the XSL processor cycles through the XSLT tree, attempting to match patterns within the XSLT commands to specific elements (also called nodes) in the XML input tree. When a pattern match is found, the browser then searches the XSLT tree for matching template rules, which it applies to the XML element or to descendants or children of the element. The result is an output tree that contains a series of elements, data, and any HTML tags or instructions necessary to format the data. An XSLT style sheet provides a template or "blueprint" of the output structure that will result from transforming the data. The content and presentation of this output is based on the input data and the style sheet (if one is used), which provides a series of commands to manipulate the structure of the elements and HTML tags to format the data.

To complete the process, the browser parses the output tree—again using the XML parser—and displays it either as an HTML document or as whatever format was specified during the transformation. Thus, at its lowest level, XSLT is used to convert one tree structure into another tree structure. The XSLT processor does this by storing and manipulating three different tree structures: the input XML and data, the XSLT style sheet, and the output XML and data.

Steps To Transform an Access 2002 XML Data File to Another Format

The steps necessary to transform an existing XML data file, such as XML data exported from Access 2002, into another format by using XSLT can be described as follows:

  1. Export the data from Access 2002 to an XML document by using the Export XML dialog box available from the Export option on the File menu.

  2. Create an XSLT file (with an .xsl file extension) by using a text editor such as Microsoft® Notepad. In this file, add processing instructions to convert and restructure the data as desired. You will need a processing instruction for each element or group of elements you want in the output.

    Note   In addition to creating an XSLT file by using a text processor, the Access 2002 Export XML dialog box also provides an option to save the format of your Access data to an XSL file. Although it doesn't contain any XSLT-specific command or instructions, the XSL (.xsl) file created by Access 2002 can be used as a starting point for creating your own XSLT transformation file. More information about creating an XSLT file as well as a sample file will be presented later in this article.

  3. Insert a processing tag in the XML data file (.xml file) that points to the XSLT file or add a scripting command such as the Load method of the Microsoft XML Document Object Model (XML DOM). Both options will be discussed later in this article.

  4. Use an XSLT processor, available in Internet Explorer or as a stand-alone application, to apply the XSLT style sheet to the XML data file to produce the resultant output file.

    Note   To run the examples described in this article, you will need to have the MSXML 3.0 processor installed on your system. More information on where to find and install MSXML 3.0 is provided later in this article.

An Example of an XSLT Style Sheet

XSLT uses a combination of HTML tags and templates rules—which are triggered when a particular node or branch of nodes in the input XML data file is encountered—to restructure and reformat the output file. Templates within the XSLT style sheet contain instructions on how to use to XPath expressions to locate parent and child elements. The style sheet also specifies how to process the input. Much of the template body consists of HTML tags and elements for output. The instructions tell the processor what part of the data to output; they are usually placed in the order that the data is to be output, regardless of the actual order of the elements in the input XML data file. Conditional programming instructions allow you to further filter and process the data.

To illustrate the transformation process further, let's look at the following example of an XSLT style sheet file that we will use later in this article.

<?xml version="1.0" encoding="utf-8"?>
<!-- This style sheet is used with the Employees.xml file
    exported from Microsoft Access 2002 to produce a listing
    of employee names, addresses, and phone numbers as an HTML
    file for display in a browser.

    Used with:
        Employees.xml

    Output:
        HTML
-->

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

<!-- Output as an HTML file. -->
<xsl:output method="html"/>
<xsl:template match="/">
    <HTML>
    <HEAD>
        <TITLE>Employees List</TITLE>
    </HEAD>
    <BODY>
        <H4>Sorted list of employees</H4>

        <!-- Create a table with headings then search for
            children of the Employees element. Once processing
            is completed, sort the table by the LastName field.
        -->
        <TABLE>
            <TR>
                <TH>Name</TH>
                <TH>Address</TH>
                <TH>Home Phone</TH>
            </TR>
            <xsl:apply-templates select="dataroot/Employees">
                <xsl:sort select="LastName" order="ascending"/>
            </xsl:apply-templates>
        </TABLE>
    </BODY>
    </HTML>
</xsl:template>

<!-- Process and output the child elements of
    the Employees element.
-->
<xsl:template match="dataroot/Employees">
    <TR>
        <TD>
            <xsl:value-of select="FirstName" />
            <xsl:text> </xsl:text>
            <xsl:value-of select="LastName" />
        </TD>
        <TD>
            <xsl:value-of select="Address" />
            <br/>
            <xsl:value-of select="City" />
            <xsl:text>, </xsl:text>
            <xsl:value-of select="Region"/>
            <xsl:text> </xsl:text>
            <xsl:value-of select="PostalCode"/>
        </TD>
        <TD>
            <xsl:value-of select="HomePhone" />

            <!-- Test whether the phone number
                has an extension. If no, skip the
                template instruction.
             -->
            <xsl:if test="string-length(Extension)&gt;0">
                <xsl:text> Ext </xsl:text>
                <xsl:value-of select="Extension" />
            </xsl:if>
        </TD>
    </TR>
</xsl:template>
</xsl:stylesheet>

Prologue

As stated earlier, XSL and XSLT are XML-based languages, so it follows that their style sheets (or transformation files) must follow the rules for XML. Accordingly, the first statement in the Prologue section of the style sheet contains a standard XML declaration statement including the encoding format and version number.

<?xml version="1.0" encoding="utf-8"?>

Comments are inserted throughout the document; they begin with the <!-- characters and end with the --> characters. Next, the <xsl:stylesheet> instruction identifies this as a style sheet to the processor.

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

The "xmlns:xsl" attribute defines a namespace prefix for use by the objects in the stylesheet. Namespaces provide a context for elements in an XML document. For example, by using a namespace, you can tell the processor that one use of the <Table> element signifies a data structure with rows and columns while another instance of the <Table> element refers to a piece of furniture. Namespaces also help to differentiate between items having the same name. Like XML documents, XSL/XSLT style sheets are required to have a version number as seen in the attribute in the <xsl:stylesheet> instruction.

Next comes the <xsl:output> instruction, which is used to help the processor identify and control the format of the output.

<xsl:output method="html"/>

Although this element is recommended, it is optional. If the element is omitted, the processor will attempt to use a "best guess" to determine the format of the output from such indicators as HTML tags. The <xsl:output> instruction also has options for XML, text, and namespace-prefixed custom file format designations.

Template Instructions

Next we come to the first in a series of template instructions.

<xsl:template match="/">

Each XSL template rule is triggered when a particular part of the source document is encountered. In this case, the <template> element contains an attribute called "match=". The value of this attribute is a pattern that matches the particular node or element in the input tree that the template rule should be applied to. This specific attribute contains the value "/", which matches the root node (also known as the document node in the XML DOM) of the input file. The root node is the top-most node in a tree and normally contains just one child element representing the document element. The document element (not to be confused with the document node) is the outermost element in an XML document; it contains all of the other elements in the document. In an Access 2002 XML file, the document element is the <dataroot> element and contains all of the other elements in the file. Similar to root directories defined in some operating systems such as UNIX, root nodes in XML documents are denoted by the forward slash (/) symbol. And as we'll see later in this article, the "/" symbol also provides a mean of navigating through the nodes in a tree by using another markup language called XPath.

Xpath can be used for numerical calculations and string manipulations but is primarily used to navigate and select items in an XML document (actually, in a tree). While a detailed discussion of XPath is beyond the scope of this article, additional information can be found at the Microsoft Online XML Developer Center. Suffice it to say that XPath expressions are used mainly to identify and navigate the elements and items in a tree, allowing us to process them with XSL/XSLT instructions.

HTML Document Tags

Next comes a series of HTML tags that will be output to the target document in order to define the basic parts of an HTML document, as well as to create a table that we will use to store our data.

<HTML>
    <HEAD>
        <TITLE>Employees List</TITLE>
    </HEAD>
    <BODY>
        <H4>Sorted list of employees</H4>
        ....
        <TABLE>
            <TR>
                <TH>Name</TH>
                <TH>Address</TH>
                <TH>Home Phone</TH>
            </TR>
             ....
        </TABLE>
    </BODY>
</HTML>

The next statements are XSL instructions that provide a beginning point for identifying and processing the remaining elements in our input document.

<xsl:apply-templates select="dataroot/Employees">
    <xsl:sort select="LastName" order="ascending"/>
</xsl:apply-templates>

Generally speaking, the <xsl:apply-templates> instruction defines a set of elements or nodes to process and causes the system to process them by selecting matching template rules. Looking closer at the instruction, the "select=" attribute has a value of "dataroot/Employees" which is an XPath expression that provides a means of navigating through the elements in the input tree. The "dataroot/Employees" expression could also have been shortened to "//Employees". The two forward slashes in the expression are XPath shorthand representing the root and succeeding levels, in this case, the level containing the dataroot element. So what exactly does <xsl:apply-templates select="dataroot/Employees"> mean? It means "from the current location (the root node based on the previous instruction <xsl:template match="/">), select the elements that are descendants of the dataroot/Employees node, and for each one, find the matching template rule in the style sheet and process it." The specific template rules will be discussed shortly.

At this point, you may be asking what happens if <xsl:apply-templates> is invoked to process a node, and there is no template rule that matches the node? In many cases, if a template rule is missing from an XSLT stylesheet and the processor doesn't know how to proceed, a default template is invoked. Which default template rule gets invoked when depends on the node type being processed. For example, the default template rule for an element-type node tells the processor "in the absence of another matching template rule, process all of the children of the current node and copy their data value to the output." So in the instruction <xsl:apply-templates select="dataroot/Employees">, if a definitive template rule is missing, then all of the descendants of the <Employees> node would be processed. This means the instructions for the elements <LastName>, <FirstName>, and <Address> would be processed and any data they contain would be copied to the output.

Continuing with our example, we see the next statement, which is used to specify a sort key, in this case, the <LastName> element.

<xsl:sort select="LastName" order="ascending"/>

Notice that we have also included an 'order="ascending"' attribute to explicitly define the sort order (this is also the default sort order). Following the sort instruction are several lines of closing HTML tags.

Template Rules

Then comes a template rule, which matches the pattern from the <xsl:apply-templates select="dataroot/Employees"> statement discussed earlier.

<xsl:template match="dataroot/Employees">

Again, the pattern determines which nodes in the input tree the template rule will process. In this case, all the child nodes of the <Employees> node are processed.

What happens if more than one rule matches the node pattern? In that case, XSLT has a conflict resolution policy that it invokes. For example, rules have a priority value assigned to them, either by the user assigning a "priority" attribute in the <xsl:template> element, or from a system default value. For system defined priorities, the more specific the pattern is, the higher the rule value will be. In our example, the pattern "dataroot/Employees" would receive a higher priority value than "*", which represents any element in the current location.

Since the template rule matches the pattern in our <xsl:apply-templates> statement, we start processing the body of the template. First, we output some HTML tags pertaining to our table and then process a series of instructions.

<xsl:value-of select="FirstName" />
<xsl:text> </xsl:text>
<xsl:value-of select="LastName" />

The first instruction evaluates the XPath expression select="FirstName" and writes its data to the output based on the <xsl:value-of> instruction. The next instruction <xsl:text> </xsl:text> is used to output literal text to the result tree, in this case a space between the <FirstName> node and the <LastName> node. Another way to copy literal text to the output is to include it in line with the instructions. For example, in the following code fragment, the text "Ext" would be copied to the output between the text of the <PhoneNumber> element and the <Extension> element.

<xsl:value-of select="PhoneNumber" />
Ext
<xsl:value-of select="Extension" />

The advantage of using the <xsl:text> element comes when you need to include white space, such as blanks, around the text or as the output.

The following XSLT instructions perform essentially the same function as described earlier.

<xsl:value-of select="Address" />
<br/>
<xsl:value-of select="City" />
<xsl:text>, </xsl:text>
<xsl:value-of select="Region"/>
<xsl:text> </xsl:text>
<xsl:value-of select="PostalCode"/>

The various child elements of the <Employees> node are selected and their values are copied to the output tree. In the case of the <Address> node, we reformatted the output by using the HTML <br> tag and through the physical placement of the nodes in the style sheet.

Conditional Looping

Next we see an <xsl:if> instruction used to test whether the employee has a phone extension and, if not, bypass the instruction processing the <Extension> node.

<xsl:if test="string-length(Extension)>0">
    <xsl:text> Ext </xsl:text>
    <xsl:value-of select="Extension" />
</xsl:if>

An <xsl:if> instruction works just like the typical "if-end if" control statement found in many programming languages: it processes the instructions encapsulated in its loop only if the condition specified in the "test=" attribute is true. In this case, we used a built-in function called string-length to determine whether the <Extension> node contained any characters. If the expression passed to the function was empty, it returns a zero. If "test=" is zero, the test evaluates as false and the loop is bypassed.

To summarize the use of XSLT in the transformation process:

  • XSLT uses a combination of HTML tags and template instructions to restructure and reformat the output file.
  • Template rules contain XPath expressions used to locate parent and child elements. Template instructions specify how to process the input. Much of the template body consists of HTML tags and elements for the output.
  • Instructions are usually placed in the order that the data is to be output, regardless of the actual order of the elements in the input XML data file.
  • Conditional programming instructions allow you to further filter and process the data.

Transforming an XML Data File

To see how an actual transformation is done, we'll follow an example of converting an XML data file, consisting of employee data from a Microsoft Access 2002 database, into a formatted HTML (.htm) file for display in a Web browser. The example will use the XSLT style sheet described above and reinforce some of the techniques we have discussed already.

Note  It is highly recommended that you use some type of security/encryption technology such the Secure Sockets Layer (SSL) to protect your sensitive data during transmission over the Web. More information about data encryption and SSL can be found in the article Secure Sockets Layer: Protect Your E-Commerce Web Site with SSL and Digital Certificates on the Microsoft Developer Network.

First, we'll create the Employees.xml file and then look at a default style sheet in action by using Internet Explorer to display our results with no explicit style sheet specified.

  1. Open the Northwind sample database. The Northwind database is typically installed with Microsoft Office and is usually located at C:\Program Files\Microsoft Office\Office10\Samples.
  2. Export the Employees table as an XML document by pointing to Export from the File menu and selecting XML Documents from the Save as type drop-down list. Keep the default file name "Employees.xml". For more information on exporting as XML, see "Export Access data as XML" in Access Help.
  3. Locate the Employees.xml file and double-click to open.
  4. Assuming your default browser is Internet Explorer 5.0 (or later), the file will be displayed as a tree structure with expandable branches of elements. This tree structure is created from the default XSLT style sheet used by Internet Explorer to transform the data.

The following code shows the default XML output from Internet Explorer.

<?xml version="1.0" encoding="UTF-8" ?>
- <dataroot>
-   <Employees>
      <EmployeeID>1</EmployeeID>
      <LastName>Davolio</LastName>
      <FirstName>Nancy</FirstName>
      <Title>Sales Representative</Title>
      <TitleOfCourtesy>Ms.</TitleOfCourtesy>
      <BirthDate>1968-12-08T00:00:00</BirthDate>
      <HireDate>1992-05-01T00:00:00</HireDate>
      <Address>507 - 20th Ave. E. Apt. 2A</Address>
      <City>Seattle</City>
      <Region>WA</Region>
      <PostalCode>98122</PostalCode>
      <Country>USA</Country>
      <HomePhone>(206) 555-9857</HomePhone>
      ....

Now let's apply the XSLT style sheet that we discussed earlier to the Employees.xml data file. Remember, you will need to have the MSXML 3.0 processor installed on your system to get the results described below.

To create and test your XSLT file:

  1. Open a text editor such as Notepad.

  2. Copy and paste the XSLT style sheet file included in the download for this article into a blank document or use the SortNames.xsl file in the download provided with this article. Note that this is the same style sheet that we described in detail earlier.

  3. Save the file to the same location as the Employees.xml file. Name the file "SortNames.xsl". Be sure to include the .xsl extension.

  4. Open the Employees.xml data file with a text editor.

  5. Create a blank line after the first line in the document. Copy the following line of text and paste it into the blank line:

    <?xml-stylesheet type="text/xsl" href="SortNames.xsl"?>
    

    This line tells the browser to apply the SortNames.xsl style sheet when the Employees.xml file is opened.

  6. Save your changes to Employee.xml.

  7. Double-click Employee.xml to open it. It should open in your browser and display a list of employees sorted by last name.

The following table shows the output from the Employees.xml file based on the SortNames.xsl style sheet.

Name Address Home Phone
Steven Buchanan 14 Garrett Hill
London, SW1 8JR
(71) 555-4848 Ext 3453
Laura Callahan 4726 - 11th Ave. N.E.
Seattle, WA 98105
(206) 555-1189 Ext 2344
Nancy Davolio 507 - 20th Ave. E. Apt. 2A
Seattle, WA 98122
(206) 555-9857 Ext 5467
Anne Dodsworth 7 Houndstooth Rd.
London, WG2 7LT
(71) 555-4444 Ext 452
Andrew Fuller 908 W. Capital Way
Tacoma, WA 98401
(206) 555-9482
Robert King Edgeham Hollow Winchester Way
London, RG1 9SP
(71) 555-5598 Ext 465
Janet Leverling 722 Moss Bay Blvd.
Kirkland, WA 98033
(206) 555-3412 Ext 3355
Margaret Peacock 4110 Old Redmond Rd.
Redmond, WA 98052
(206) 555-8122 Ext 5176
Michael Suyama Coventry House Miner Rd.
London, EC2 7JR
(71) 555-7773 Ext 428

XML/XSL Processors

There are several XSLT processors available, including the Microsoft MSXML 3.0 processor which can be downloaded from the Microsoft Online XML Developer Center. The MSXML 3.0 processor can also be installed with Microsoft Office XP and Microsoft Windows® XP.

The MSXML 3.0 parser supports both the XML DOM and the Simple API for XML (SAX2). The XML DOM is a tree-based application programming interface (API) that presents a standardized interpretation of an XML document to applications and scripts. The XML DOM implementation in MSXML allows you to load or create a document; gather errors, if any; access and manipulate the information and structures contained within the document; and save the document back out to an XML file, if necessary. Where the XML DOM defines the logical structure of an XML document in memory, the SAX2 provides an event-based API, which allows developers to hook directly into the document parsing process using event interfaces that serve up the document's information items as they are parsed. In other words, the XML DOM interfaces are made available to the application after the document has been parsed and loaded. The SAX2 interfaces are available to the application as the document is being parsed.

The XSLT processor is a Component Object Model (COM) object, so it can be invoked by any language that can create a COM object, including Microsoft Visual Basic® Scripting Edition (VBScript), Microsoft JScript®, Microsoft Visual Basic, Microsoft Visual Basic for Applications, or Microsoft Visual C++®.

How to Redistribute the Microsoft XML Parser

To run the following examples, you will need to have the MSXML 3.0 processor installed on your system. MSXML 3.0 should be installed in "replace" mode as described in the above Knowledge Base article.

Using Multiple Style Sheets with VB Script

Let's look at how to use multiple XSLT style sheets to format the same XML data in two different styles by using VBScript.

The sample we'll look at (also included in the download available with this article) uses data from the Employees table in the Northwind sample database. This time, we have included four employee records in an XML data file. The sample is to be used as part of a bid to sell our services to a prospective client. We want to emphasize the employment longevity of the team of employees we are pitching to the client as well as the structure of the team. To do this, we want to include such information as the hire dates, job titles, and the compensation scheme we use so that the client understands the context of our bid. We also want to provide the information to our client in two formats: a simple list format that the client can use to circulate to the internal managers who may have to manage our services, and a catalog format for presentations to upper management.

Upon opening the Default.htm file in a browser, the client will be presented with a simple listing containing the information we want them to know about our employees. The client will also see two buttons that will allow the selection of either the simple information listing or a catalog type display of employee information. This is a relatively simple application, but it will help you see how you can use script and multiple style sheets to make your data more dynamic.

In our sample, several different components work together to function as an effective presentation package (these files are available in the download included with this article):

  • **Employee_data.xml file
    **This file contains selected information on four employees from the Employees table in the Northwind sample database.
  • **List_style.xsl file
    **This file contains the XSLT style sheet that is used to display the Employee_data.xml file in a format that lists the relevant information. We'll describe this file in a little more detail later.
  • **Catalog_style.xsl file
    **This file contains the XSLT style sheet that is used to display the Employee_data.xml file in a format similar to a catalog. We'll also discuss this file in more detail.
  • **Default.htm file
    **This file pulls the whole package together. It loads the list style XSLT file when initially opened in the browser. It contains two command buttons, which allow the user to select a particular display format. It also contains the VBScript procedure, which swaps out the XSLT style sheets used, based on the user selection.

Looking at this sample in a little more detail, the Employee_data.xml data file contains information on four employees. As with any XML file, it starts with an XML processing instruction indicating that this is an XML file, gives the version number, and specifies an encoding format. The file contains an <Employees> document element, which contains a series of <Employee> elements. There is one set of <Employee> elements for each employee. These elements, in turn, contain a series of child elements that encapsulate the employee information we are interested in providing to the client.

The following is a fragment of the Employee_data.xml data file.

<?xml version="1.0" encoding="utf-8"?>
<employees>
 <employee>
   <name>Nancy Davolio</name>
   <photo>EMPID1</photo>
   <hiredate>01-May-1992</hiredate>
   <title type="Commission+">Sales Representative</title>
   <region>WA</region>
 </employee>
 <employee>
   <name>Andrew Fuller</name>
   <photo>EMPID2</photo>
   <hiredate>14-Aug-1992</hiredate>
   <title type="Salaried">Vice President, Sales</title>
   <region>WA</region>
 </employee>
 ...

Next, the List_style.xsl file is an XSLT style sheet file that contains the template rules, instructions, and HTML tags necessary to display our XML data as a simple list of employee characteristics.

The following code shows the List_style.xsl XSLT style sheet file.

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

<!-- This XSLT style sheet is used to transform the employee_data.xml 
file to a simple list like format. It is passed as an argument to the      
VBScript transformFile procedure in the default.htm file.
 -->

<xsl:output method="html"/>
<xsl:template match="/">
 <html>
   <head>
     <title>The XSLT list style sheet</title>
   </head>
   <body>
     <table border="0" cellpadding="10">
      <tr>
       <th align="left">Name</th>
       <th align="left">Region</th>
       <th align="left">Hire Date</th>
       <th align="left">Compensation</th>
       <th align="left">Title</th>
      </tr>
      <xsl:apply-templates select="/employees/employee">
       <xsl:sort select="name"/>
      </xsl:apply-templates>
    </table><p />
   </body>
 </html>
</xsl:template>

<!-- Outputs the child elements of the employees element. -->
<xsl:template match="employee">
   <tr>
    <td><xsl:value-of select="name"/></td>
    <td><xsl:value-of select="region"/></td>
    <td><xsl:value-of select="hiredate"/></td>
    <td><xsl:value-of select="title/@type"/></td>
    <td><xsl:value-of select="title"/></td>
   </tr>
</xsl:template>
</xsl:stylesheet>

Much of the first half of this file consists of items similar to those discussed in the previous example: the declaration and processing instructions for XML files, and the standard items needed to populate an HTML file such as the <HTML> and <BODY> tags.

Both of the XSLT style sheets used in this sample use an HTML table to contain the employee information. However, by using different template rules, instructions, and HTML formatting tags, we can achieve very different displays.

Continuing with our discussion, we see the first template instruction, which matches the root node of the document and is used to ensure that we process all of the elements in the document.

<xsl:template match="/">

Remember that the root node is synonymous with the document node in the XML DOM and represents the entire source document. It should not be confused with the document node, the <Employees> node in our example, which contains all of the remaining nodes in our document. Next in our sample comes a series of HTML tags to create a table with heading items.

Then the <xsl:apply-template> element directs the XSLT processor to find a template matching the value of the XPath expression "employees/employee" and if found, process each of its descendants, again looking for a matching template.

<xsl:apply-templates select="/employees/employee">
    <xsl:sort select="name"/>
</xsl:apply-templates>

The position of this instruction in the page we are constructing is where the employee information will be written. Further down in our file, we see a template match for the <employee> element.

<xsl:template match="employee">
    <tr>
        <td><xsl:value-of select="name"/></td>
        <td><xsl:value-of select="region"/></td>
        <td><xsl:value-of select="hiredate"/></td>
        <td><xsl:value-of select="title/@type"/></td>
        <td><xsl:value-of select="title"/></td>
    </tr>

This template contains a repetitive list of instructions to handle the children of the <employee> element. The first instruction, <td><xsl:value-of select="name"/></td>, tells the processor to write the contents of the <name> element into our table. This instruction is then repeated for each of the remaining children of the <employee> element. One exception is the <td><xsl:value-of select="title/@type" /></td> element, which directs the processor to write out the value of the "type" attribute contained within the <title> element. In our scenario, this value represents the compensation information for each employee.

We will only look at the items of the next XSLT style sheet file, Catalog_style.xsl, which differ from the previous style sheet or that may provide some interesting observations. This file contains the template rules, instructions, and HTML tags to display our XML data in a catalog style. The following is a fragment of the Catalog_style.xsl file.

<?xml version="1.0" encoding="utf-8" ?>
...
     <xsl:apply-templates select="/employees/employee">
       <xsl:sort select="name"/>
     </xsl:apply-templates>
...

<xsl:template match="employee">
 <table border="0" cellpadding="10" bgcolor="lightyellow">
   <tr>
    <td>
      <img src="{photo}.jpg" alt="{name}"/>
    </td>
    <td>
     <div>
      <b>Name: </b><xsl:value-of select="name"/>
     </div><p/>
     <div>
      <b>Title: </b><xsl:value-of select="title" />
      <br><b>Region: </b><xsl:value-of select="region"/></br>
      <br><b>Compensation:</b>
          <xsl:value-of select="title/@type"/> </br>
      </div><p/>
     <div><font color="GREEN"><b>Northwind Traders</b>
          <img src="NWLOGO.gif" alt="Northwind Traders"/></font></div>
     </td>
   </tr>
 </table>
</xsl:template>
</xsl:stylesheet>

The primary XSLT element of interest in this file is the <xsl:apply-template> element which, like its predecessor in the previous file, directs the XSLT processor to find a template matching the value of the XPath expression "employees/employee", the <xsl:template match="employee"> element in this example, and process each of its descendants. Looking further down the file, the template that matches this instruction contains a series of HTML tags that create table rows with special background coloring and other formatting attributes. Another row of data will contain a .gif file representing a picture of each employee. The remaining template instructions instruct the processor to output the value of each specific element into our table and then we see a group of closing XSLT and HTML tags.

The final file we'll examine in our sample is the Default.htm Web page file, which does most of the actual work in this application. The first thing to notice is that this is not an XML file so there's no XML declaration. Now let's jump into the file contents.

<html>
<head>
<script language="VBScript">
<!--

Public sub transformFiles(strStylesheetName)

  'This procedure transforms an XML data file by using an XSLT
  ' style sheet that is passed to it. It then stores the results
  ' of the transformation in a DIV tag on this page.
  '
  '  Accepts:
  '     strStylesheetName   The name of the XSLT style sheet.
  '

  Dim objResults  'object that holds the HTML results
  Dim objXML      'object to hold XML data
  Dim objXSL      'object to hold style sheet


  On Error Resume Next

  '   The DIV element will store the results.
      set objResults = Document.all("divResults")

  '   Create a new document instance for the data file and style sheet.
      set objXML = CreateObject("MSXML2.DOMDocument.3.0")
      set objXSL = CreateObject("MSXML2.DOMDocument.3.0")

  '   Set the property to valid the file when its parsed.
      objXML.validateOnParse = true
      objXSL.validateOnParse = true

  '   Load the files
      objXML.load("employee_data.xml")
      objXSL.load(strStylesheetName)

  '   All must be OK so perform transformation
      strResult = objXML.transformNode(objXSL)

  '   Display the results in the DIV tag
      objResults.innerHtml = strResult

  '   Implement error handling
      If Err.Number <> 0 Then
        y = Err.description
        Response.Write y
      End if

End Sub
//-->
</script>

</head>

<!-- Call transformFiles procedure to load the simple list view when 
the page is opened -->
<body onload="transformFiles('list_style.xsl')">

<H2><font color="maroon">The Winning <font 
color="green">Northwind</font> Sales Team!</font></H2>

<!-- Create the command buttons that pass the style sheet argument to 
the transformFiles procedure.  -->

  <p>We are proud to present the information on
     our team in a &nbsp;<button  
onclick="transformFiles('catalog_style.xsl')">Catalog</button>&nbsp;
  format or as a &nbsp; <button 
onclick="transformFiles('list_style.xsl')">Simple List</button>

  <hr />

  <!-- Insert the results of the XSLT transformation -->
  <div id="divResults"></html></div>

</body>
</html>

After the standard <HTML> and <BODY> HTML tags comes the script section of the file. The procedure transformFiles receives a string containing the name of the XSLT style sheet that will be used to transform the XML data. Next we create a reference to the <DIV> tag in the .htm page, which will contain the results of the transformation.

set objResults = Document.all("divResults")

We then create an instance of the XML DOM Document object for both the XML data and the XSLT style sheet so we can get at the properties and methods for these objects.

set objXML = CreateObject("MSXML2.DOMDocument.3.0")
set objXSL = CreateObject("MSXML2.DOMDocument.3.0")

The validateOnParse property tells the browser that we want it to validate the XML data and XSLT files as they are parsed.

objXML.validateOnParse = true
objXSL.validateOnParse = true

XML-based files are said to be "well-formed" if they conform to specific rules for XML documents such as each opening tag has a closing tag, there must be a single outermost element that encloses the others, tags must be nested inside of each other and not overlap, and so forth. XML documents can also conform to a stricter level of "correctness" if they are "valid". Valid XML documents are well-formed documents that meet two additional criteria: they must refer to a document type definition (DTD) document (such as an XSL file) remember that XSLT is a subset of XSL so it also counts) that describes the structure of the XML data; and the structure of the XML data must conform to the DTD document. If you are transforming unstructured (non-XML) data, you would want to set objXML.ValidateOnParse=False instead of objXML.ValidateOnParse=True.

After loading the XML data and XSLT style sheet into memory, we call the transformNode method.

strResult = objXML.transformNode(objXSL)

This method performs the actual transformation by running the XSLT style sheet against the XML data and returning HTML data. The result of this call is fed into the <DIV> element for display using the innerHTML property.

objResults.innerHtml = strResult

After the script section, we come to the tags comprising the Web page.

<body onload="transformFiles('list_style.xsl')">

The file List_style.xsl is passed to the transformFiles procedure when default.htm is initially opened in the browser.

Command buttons are then displayed to provide the user with the choices of style sheets.

<button onclick="transformFiles('catalog_style.xsl')">Catalog</button>
<button onclick="transformFiles('list_style.xsl')">Simple List</button>

And finally we see the <DIV> tag, which contains the results of the transformation.

<div id="divResults"></html></div>

So you can see that this application is actually relatively simple in execution.

To summarize, when the default.htm file is opened in the browser, the transformFiles procedure is called with the List_style.xsl style, which displays a simple list of employee characteristics. The transformFiles procedure passes the style sheet to the transformNode method of the XML data object to accomplish the transformation. The results of the transformation are stored as HTML in a <DIV> tag in the Web page. The user is also presented with two buttons that provide a way for them to switch between the different views of the data. Selecting the Catalog button causes the transformFiles procedure to be called with the Catalog_style.xsl style sheet argument, providing a slightly more graphic view of the data. Selecting the Simple_List button returns the user back to the simple list.

Error Handling and XSLT

As we saw earlier, the call to the transformNode function invokes the XSLT processor, and the resulting HTML is inserted into the .htm page. So what happens if you open the .htm file in Internet Explorer and the page is blank? Assuming that the browser reported no other errors, a likely source of trouble could be the problems encountered during the parsing of the XML data or the XSLT style sheet. XSLT run-time errors occurring inside calls to the transformNode function are another possibility, although run-time errors will normally be reported to the user through an Internet Explorer 5.0 (or later) error dialog box.

If nothing is displayed, your best bet is to check the parseError object to see if there was a parsing error when loading either the XML file or style sheet. The Document object of the XML DOM exposes a parseError object, which can be examined to tell if an error occurred. If an error did occur, you can retrieve the cause or display an error message in the page.

The parseError object provides seven properties that can be checked to reveal more information about the error. The following table describes the properties of the parseError object.

Property Description
errorCode Error number of the error that occurred.
filepos Character position within the file where the error occurred.
line Line number where the error occurred.
linepos Character position within the line where the error occurred.
reason Text description of the error.
srcText The source (text) of the line where the error occurred.
url URL or path of the file that was loaded.

For example, you could use the following fragment of VBScript in your code to detect and display error details:

' Detect the error while loading
If document.parseError.errorCode <> 0 Then

   ' Create the error message
   Dim strError
   strError = "Invalid XML file! " & vbCrLf _
           & "File URL: " & document.parseError.url & vbCrLf _
           & "Line No.: " & document.parseError.line & vbCrLf _
           & "Character: " & document.parseError.linepos & vbCrLf _
           & "File Position: " & document.parseError.filepos & vbCrLf _
           & "Source Text: " & document.parseError.srcText & vbCrLf _
           & "Error Code: " & document.parseError.errorCode & vbCrLf _
           & "Description: " & document.parseError.reason
   ' Display the error message
   MsgBox strError
Else
    ' The document loaded without a problem
End If

This code fragment can be used to determine if any errors occurred while parsing an XML document. Of course, you'll also want use normal error handling such as placing the On Error Resume Next statement at the top of your VBScript script to force script execution to continue when an error is raised. To handle any errors that might occur, you'll want to query the Err object at certain points in the script to test for error conditions that might exist.

More information about the parseError object can be found on the Microsoft Online XML Developer Center.

Conclusion

In this article, we introduced the XSLT markup language and described its file structures and a few processing instructions. We discussed its use in transforming XML data files from one format to another. We also looked at the output of the default XSLT style sheet used in Internet Explorer and one of our own custom XSLT files. We also presented an application to demonstrate how XSLT can be used with VBScript to present different views of the same data. Hopefully, these concepts will provide a starting point for building your own XSLT files and using them in your applications.

Additional Resources

For a more in-depth discussion of the concepts presented in this article, see the Microsoft Online XML Developer Center or the W3C Extensible Markup Language (XML) Web site.

For more information about XSL and XSLT, see the XSL Developer's Guide on MSDN or the W3C Extensible StyleSheet Language (XSL) Web site.

Glossary

This glossary defines some of the technical terms presented in this article. For more information on any of these terms, see the links in the Additional Resources section of this article.

  • **Attribute
    **A name=value pair appearing in an element's start tag such as

    match="//employees".
    
  • **Comment
    **An item in an XSLT style sheet that contains extraneous information. Written between the delimiters <!-- and -->.

  • **Document Element
    **The outermost element of a document. The Document Element contains all of the other elements. Contrasted with the root node.

  • **Element
    **A logical element within an XSLT style sheet delimited by start and end tags such as <Title>Sales Representative</Title>.

  • **Expression
    **An XPath construct that can be evaluated to a string, number, Boolean, or set of nodes. Expressions are used in many contexts such as the select attribute of the <xsl:templates> element.

  • **Namespace
    **A named collection of names. A namespace is named by using a URI, to ensure uniqueness, and utilizes a preface to provide context for elements and attributes.

  • **Node
    **An object of a tree structure.

  • **Output Method
    **XSLT defines three output methods: XML, HTML, and text.

  • **Pattern
    **A construct that defines a condition that every node either satisfies or does not satisfy. Used as XPath expressions in XSLT elements such as <xsl:template>.

  • **Processing Instruction Nodes
    **Nodes containing processing instructions. Processing instructions carry instructions to the software that receives the XML document and processes it. Written between the delimiters <? and ?> such as the <?xml version="1.0" encoding="UTF-8" ?> declaration in an XML document.

  • **Result Tree
    **The output of a style sheet. A style sheet defines a transformation from a source tree structure to a result tree structure.

  • **Root Node
    **The top-most node in a tree structure. If the tree structure represents a well-formed XML document, the root node will have exactly one element node, representing the document element, and no child nodes. It may also contain comment nodes and processing instructions nodes as children.

  • **Template Body
    **A sequence of XSLT instructions, HTML tags, and text forming the contents of an <xsl:template> element.

  • **Template Rule
    **An <xsl:template> element with a match= attribute. A template rule may be invoked by using the <xsl:apply-templates> instruction.

  • **Tree Structure
    **An abstract data structure representing the information content of an XML document. The tree structure always has a single root.

  • **URI
    **Uniform Resource Identifier: a generalization of the URLs (Uniform Resource Locators) used to uniquely identify resources such as addresses on the Internet.

  • **Well-formed
    **A document is well-formed if it follows the syntax rules in the XML specification. These include such rules as there must be a single outermost element that encloses all other elements and all start tags must have closing tags.