XML

DTD

Schemas

XSL

DOM

XHTML

 

An Extensible Stylesheet Language (XSL) Tutorial

This tutorial covers the basics of XSL. Before reading this tutorial you should already be familiar with XML. You may want to read my XML tutorial. Click the above link to do so.

What is XSL?

XSL stands for Extensible Stylesheet Language.

XSL is similar to Cascading Style Sheet (CSS) language in that it lets you format the display of XML data. This, however, is were the similarities stop. To view an XML file with and without CSS click here.

With CSS, the structure of the XML data must be identical to the structure of its display. CSS associates formatting properties with XML tags and is said to "decorate the XML tree". Thus, forethought must be used when designing XML data so you can display it properly. This violates XML's goal of separation of data.

XSL lets you transform the XML tree into a new tree without changing the XML source data. Then, the XML can be displayed differently just by switching style sheets.

XSL standards are defined by the World Wide Web Consortium (W3C). The W3C site provides a comprehensive reference concerning XLS.

However, discussions contained herein focus on Microsoft's implementation of XSL. All samples require their Internet Explorer, version 5.0 or later, browser which includes their Msxml parser. All references to the Msxml parser, assume Msxml V2.5 or later. For more information or to download Microsoft's XML products, visit their site.

XSL as a Programming Language

Since XSL is a language, it enables you to use conditional formatting and looping constructs, apply selection criteria, sort and filter the XML data, and transform the XML tree structure. Unlike CSS, you can also describe irregular, non-repetative data.

Creating and Filling an HTML Template

With XSL you can combine XML data with an HTML template for display purposes. The following XML data is repetitive -- the stock element is repeated several times with the same subelements.


XML Sample 1

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="stock.xsl"?>
<portfolio xmlns:dt="urn:schemas-microsoft-com:datatypes">

  <stock exchange="nyse">
    <name>zacx corp</name>
    <symbol>ZCXM</symbol>
    <price dt:dt="number">28.875</price>
  </stock>

  <stock exchange="nasdaq">
    <name>zaffymat inc</name>
    <symbol>ZFFX</symbol>
    <price dt:dt="number">92.250</price>
  </stock>

  <stock exchange="nasdaq">
    <name>zysmergy inc</name>
    <symbol>ZYSZ</symbol>
    <price dt:dt="number">20.313</price>
  </stock>

</portfolio>


Here is a complete XSL style sheet which uses an HTML template to create a separate row for each stock.


XSL Sample 1

<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<HTML>
<BODY>
<TABLE border="2">
<TR>
<TD>Symbol</TD>
<TD>Name</TD>
<TD>Price</TD>
</TR>
<xsl:for-each select="portfolio/stock">
<TR>
<TD><xsl:value-of select="symbol"/></TD>
<TD><xsl:value-of select="name"/></TD>
<TD><xsl:value-of select="price"/></TD>
</TR>
</xsl:for-each>
</TABLE>
</BODY>
</HTML>
</xsl:template>
</xsl:stylesheet>

The <xsl:for-each> element locates a set of elements in the XML data ("stock" elements inside the "portfolio" element) and repeats a portion of the template for each one. This sample contains three stock elements so three rows will be created in the table.

The Select attribute tells how to find a set of elements. The syntax for this attribute is called an XSL pattern. Patterns work like navigating a file system tree where a slash (/) selects subdirectories relative to the current directory.

In an XSL style sheet, navigation starts at the current node and drills down into the XML data hierarchy, selecting all nodes matching the pattern. Here, the pattern portfolio/stock starts at the root and drills down through the "portfolio" element to select the three "stock" children.

XSL patterns can be complex and are described in more detail later.

Within the <xsl:for-each> element, you can further drill down to select children of each "stock" element. The <xsl:value-of> element selects a specific child then inserts that child's text into the template. The patterns inside the <xsl:value-of> element's select attribute do not start at the root. They are relative to the element selected in the <xsl:for-each> element.

Because XSL style sheets are XML files, they begin with an XML declaration. Also, both they and the HTML template must be well formed.

The <xsl:stylesheet> element denotes this is a style sheet file and specifies an XSL namespace URL. The <xsl:template match="/"> statement indicates the template corresponds to the root (/) of the XML source document.

In the XML file, a processing instruction was added so the parser knows to use the XSL style sheet.

Try it!       View the XSL style sheet        View the formatted XML file.

Attributes

To access an attribute in the XML source precede its name with the "@" symbol. As shown below, the value of the "exchange" attribute on stock elements is inserted it into the output.

Attributes can be added to an element when the data is displayed using the <xsl:attribute> element. The attribute's value is generated from the XML source data.



<xsl:for-each select="portfolio/stock">
  <TR>
    <xsl:attribute name="title"><xsl:value-of select="symbol"/>
      is listed on the <xsl:value-of select="@exchange"/>
      stock exchange.</xsl:attribute>
    <TD><xsl:value-of select="symbol"/></TD>
    <TD><xsl:value-of select="name"/></TD>
    <TD><xsl:value-of select="price"/></TD>
  </TR>
</xsl:for-each>

The name attribute specifies the name of the attribute that will be added to the output. Its value is determined by evaluating its tag.

In this example, a title attribute is added to the <TR> element to display a ToolTip. The ToolTip's text is created by mixing text with element and attribute values from the source XML document.

Attributes can be added to elements that already have attributes specified on them in the XML source. However, you can't add an attribute to an element that already has an attribute with the same name. Also, attributes added with <xsl:attribute> must appear before children are added to the element.

Sorting

The <xsl:for-each> element displays repetitive data in the order it appears in the XML document. The order-by attribute lets you to sort the data within a specified node, price in the this case.


<xsl:for-each select="portfolio/stock" order-by="price">

A minus sign (-) preceding a sort key causes the sort to occur in descending order. A plus sign (+), which is implied, can optionally be used to explicitly indicate an ascending sort.

You can sort by multiple keys. Just separate them with semicolons. If multiple stocks have the same price, they will then be sorted by name. Notice that the price data is first converted to a numeric data type to insure proper sorting.


order-by="- number(PRICE); NAME"



Conditional Logic

Conditional logic in XSL lets you display XML data in your HTML based on certain conditions being met in the XML source. Conditional templates are defined using the <xsl:if> and <xsl:choose> elements.

If Logic
The XML data in sample 1 above has an "exchange" attribute associated with the "stock" element. Suppose you want to output an asterisk "*" when the exchange is "nasdaq". This can easily be done using the <xsl:if> element after the select="symbol" line of XSL Sample 1.


<xsl:value-of select="symbol"/>
<xsl:if test="@exchange[.='nasdaq']">*</xsl:if>

Instead of displaying text, an asterisk in this case, we could have displayed elements and attributes as well.

The test attribute uses a pattern. If the query associated with the pattern selects one or more nodes, the <xsl:if> template is inserted. The above query looks to see if the stock element has an "exchange" attribute. Then it checks if the exchange attribute's value equals "nasdaq".

Try it!       View the XSL style sheet        View the resulting XML file


Choose Logic
The Choose element functions like Visual Basic's Select Case statement. It allows you to specify a series of conditions. When one is satisfied, the corresponding HTML template is output.


<TR>
  <xsl:attribute name="STYLE">color:
    <xsl:choose>
      <xsl:when test="price[. $le$ 25]">green</xsl:when>
      <xsl:when test="price[. $le$ 50]">blue</xsl:when>
      <xsl:otherwise>red</xsl:otherwise>
    </xsl:choose>
  </xsl:attribute>
  <TD>
  ...


Transforming XML

A Data Island is an XML document that exists within an HTML page. Since XSL is an XML grammar itself, data islands allow you to easily load style sheets.

This example uses two data islands. One to load the XML data and one to load the XSL style sheet. The transformNode method is used on the data islands to create the HTML to be inserted into the page.


<HTML>
  <HEAD>
    <title>Simple demo of Microsoft XSL Processor</title>
  </HEAD>
  <XML id="source" src="menuxml.xml"></XML>
  <XML id="style" src="menuxsl.xsl"></XML>

  <SCRIPT FOR="window" EVENT="onload">
    xslTarget.innerHTML = source.transformNode(style.XMLDocument);
  </SCRIPT>

  <BODY>
    <P STYLE="font-size:10pt; font-family:Verdana; color:gray">
      <B>This demo shows the use of data islands for loading XML source and
      XSL style sheets and inserting the transformed result into the Web page.</B>
    </P>
    <DIV id="xslTarget"></DIV>
  </BODY>
</HTML>

Here's what happens. When the page is completely loaded, including the data islands, its onload event fires and calls the transformNode method on the XML source data.

TransformNode takes the DOM node representing the XSL style sheet as a parameter. The result is XML text. Since the menuxsl.xsl style sheet produces well-formed HTML, its output can be fed into the xslTarget DIV element for display using the innerHTML property.

Note that the XMLDocument property is used on the "style" data island. Without this, the ID of the data island is thought to be an HTML element, in this case the <XML> element.

We could have just used XMLDocument instead of style.XMLDocument. However, specifying the full name makes it clear that we are operating on the contents of the data island and not the <XML> element representing the data island.

What happens if nothing happens?

Errors can occur during the parsing of the XML and XSL documents and during the transformation. It is possible to trap and display these errors. This is explained in detail in the XML Software Development Kit available on their site.

XSL Patterns

XSL Patterns provide a query language for identifying nodes in an XML document. Nodes can be identified by their type, name, value, and relationship to other nodes in the document. A pattern describes a path through the XML hierarchy with a slash-separated list of child element names.

The following query finds 'author' elements with a 'period' attribute whose value is 'classical' and that are contained in the 'authors' element at the document root.


"/authors/author[@period='classical']".

XML documents represent a hierarchy of nodes, similar to the hierarchy of folders and files in a file system. Here are some similarities between the two.

File System

XSL Patterns

Hierarchy of folders and files

Hierarchy of elements and other nodes in an XML document

Files at each level have unique names

Element names at each level might not be unique. XSL Patterns identify all the matching elements

URLs are evaluated relative to the "current folder"

XSL Patterns are evaluated relative to a particular node called the context for the query.

Let's use this XML data and illustrate some of the basic queries using XSL Patterns.


<authors>
<author>
<name>Victor Hugo</name>
<nationality>French</nationality>
</author>
<author period="classical">
<name>Sophocles</name>
<nationality>Greek</nationality>
</author>
<author>
<name>Leo Tolstoy</name>
<nationality>Russian</nationality>
</author>
<author>
<name>Alexander Pushkin</name>
<nationality>Russian</nationality>
</author>
<author period="classical">
<name>Plato</name>
<nationality>Greek</nationality>
</author>
</authors>

XSL Patterns can use any node in the XML document as the context (starting point) for a query. In an XSL style sheet, the context for a query is the source node being currently processed by an <xsl:template> or <xsl:for-each> element.

The following pattern starts from the XML document's root and traverses down the hierarchy to the "name" elements. It identifies all elements that match the path.


authors/author/name

Patterns can also use wildcards. Here, we can find any name element regardless of whether it is a child of the author element. We can also find both name and nationality elements under author elements.


authors/*/name
authors/author/*

We can specify branches on the path by using square brackets. The branch on the author element indicates only author elements with nationality children should be considered. In the second statement, only the names of Russian authors are returned.


authors/author[nationality]/name
authors/author[nationality='Russian']/name

To use attributes in a query, precede their name with "@". The attribute can be tested as a branch off the main path, or the query can identify attribute nodes.

This first example returns authors from the classical period. The second returns just the two period attributes themselves.

authors/author[@period="classical"]
authors/author/@period

The above samples are only the tip of the iceberg when it comes to patterns. The best reference on patterns is the XML Software Development Kit available from Microsoft.





About TheScarms
About TheScarms


Sample code
version info

If you use this code, please mention "www.TheScarms.com"

Email this page


© Copyright 2024 TheScarms
Goto top of page