Home

The Extensible Style Sheet Transformations (XSLT)

   

Fundamentals of XSLT

 

Introduction

An extensible style sheet directs the parser as to how to present an XML document to a user. The extensible style sheet uses a series of instructions destined to "transform" the contents of an XML document into friendlier formats. As a result, the language is called Extensible Style Sheet Transformation or XSLT.

XSLT is defined by the World Wide Web Consortium (W3C) at http://www.w3.org/TR/xslt.html. Besides following the XSLT standards, Microsoft defined its own interpretation of XSLT. The .NET Framework also has its own support of XSLT. In this lesson, we will follow XSLT as it is used in the .NET Framework.

To support XSLT, the .NET Framework provides a class named XslCompiledTransform:

public sealed class XslCompiledTransform

XslCompiledTransform is a sealed class defined in the System.Xml.Xsl namespace. Therefore, to use an XSLT file in your application, add that namespace and declare a variable based on that class. Here is an example:

using System;
using System.Xml.Xsl;

public class Exercise
{
    public static int Main()
    {
        XslCompiledTransform xctVideos = new XslCompiledTransform();

        return 0;
    }
}

Starting an XSLT Document

As seen for XML, if you double-click an XSLT file in a Windows Explorer or another file utility or manager, it would be opened in a Web browser (or in the default browser if you have more than one Web browser).

Before creating a style sheet, you may want to create, or at least start, your XML document first. This allows you to create or start creating the elements (and attributes) you will need. Also, this allows you to define or name your elements. Here is an example of an XML document saved as Videos2.xml:

<?xml version="1.0" encoding="utf-8" ?>
<videos>
  <DocumentTitle>Video collection</DocumentTitle>
  <video>
    <title>Her Alibi</title>
    <director>Bruce Beresford</director>
    <length>94</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
  <video>
    <title>The Distinguished Gentleman</title>
    <director>Jonathan Lynn</director>
    <length>112</length>
    <format>DVD</format>
    <rating>R</rating>
    <year-released>1992</year-released>
  </video>
  <video>
    <title>Duplex</title>
    <director>Danny DeVito</director>
  </video>
  <video>
    <title>The Day After Tomorrow</title>
    <director>Roland Emmerich</director>
    <length>124</length>
    <format>BD</format>
    <rating>PG-13</rating>
  </video>
  <video>
    <title>Other People's Money</title>
    <director>Alan Brunstein</director>
    <year-released>1991</year-released>
  </video>
</videos>

To present an XML document in a friendly way to a user, you have various options. The primary solution is to create a regular XSLT document. To create an XSLT document in Microsoft Visual Studio:

  • On the  main menu, click PROJECT -> Add New Item...
  • In the Solution Explorer, right-click the name of the project -> Add -> New Item...

In the middle list of the Add New Item dialog box, click XSLT File. Give it a name. An extensible style sheet is a file with the .xsl or the .xslt extension. If you don't specify the extension, the dialog ox would add the .xslt extention for you. Click Add.

Like an XML document, an XSLT document starts with a declaration as <?xml version="1.0" encoding="UTF-8"?>. As seen in XML, each element in XSLT must have a name. In XSLT, the name must have been defined in a namespace. The names used in XSLT are defined in a namespace specified in the http://www.w3.org/1999/XSL/Transform document. Therefore, you must reference that namespace in your XSLT document. Like XML, XSLT is defined in versions. The current version is 1.0.

The namespace that defines the names in XSLT documents is called xsl. Therefore, to access one of its names, you must qualify it by preceding it (the name in the namespace) with xsl and the qualifying operator, which is the colon ":".

To let you open an XSLT, the XslCompiledTransform class is equipped with an overloaded method named Load. The simplest version uses the following syntax:

public void Load(string stylesheetUri);

This version takes the name (and path) of the XSLT file. Here is an example:

using System;
using System.Xml.Xsl;

public class Exercise
{
    public static int Main()
    {
        XslCompiledTransform xctVideos = new XslCompiledTransform();

        xctVideos.Load("Videos.xslt");

        return 0;
    }
}

The Document Element

As seen in XML, and as we will see in the next sections, an XSLT document is made of elements. And as mentioned for XML, all elements in an XSLT document must have a common ancester, called the root element, also called the document element. While XML lets you create your own root and give it any name you want, XSLT defines the root element as stylesheet. The syntax of the stylesheet element is:

<xsl:stylesheet
  id = id
  extension-element-prefixes = NCNames
  exclude-result-prefixes = NCNames
  version = number>
</xsl:stylesheet>

The id attribute is optional. It is mostly used if you want to embed one XSLT section (or code) in another. In this case, if you decide to use an id attribute, give it a value that is unique among the other ids. You must define the name of the extension-element-prefixes attribute. The attribute is used to specify the namespace that holds the names of the elements that will be used in the XSLT document. As a result:

  • Because the names of elements used in an XSLT document are defined in http://www.w3.org/1999/XSL/Transform, the value of the extension-element-prefixes attribute is that namespace
  • Because http://www.w3.org/1999/XSL/Transform is a namespace, you must reference it as such (a namespace), which is done using the xmlns prefix. Now, because the namespace name defined is xsl, you can use it as the name of the attribute

As a result, an XSLT document starts as follows:

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

By the way, the version attribute can come before or after the namespace:

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

As another way to present an XML document to a user, you can include (or embed) HTML code in your extensible style sheet document, between the start and end tags of the stylesheet element. This can start as follows:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <html>
    <head>
      <title>Video Collection</title>
    </head>
    <body>

    </body>
  </html>
</xsl:stylesheet>

Qualified Names

In XML, each element must have a name. In XSLT too, each element also must have a name but the name must have been defined in a namespace. As mentioned already, the names used in XSLT are defined in the http://www.w3.org/1999/XSL/Transform namespace. After referencing the XSLT namespace, to use a name, you must qualify it by preceding it with xsl.

Transforming an XML Document

In your XML document, you can reference the style sheet, which is done after the XML declaration. The basic formula to reference the extensible style sheet is:

<?xml-stylesheet href="Path or FileName.xsl" type="text/xsl"?>

Replace FileName with the name of the style sheet. Here is an example:

 <?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="Videos.xsl" type="text/xsl" ?>
<videos>
  <DocumentTitle>Video Collection</DocumentTitle>
  <Introduction>Washington, DC Metropolitan Area</Introduction>
</videos>

This is referred to as transforming an XML document. To provide a simpler and more effective solution, the XslCompiledTransform class is equipped with an overloaded method named Transform. The simplest version uses the following syntax:

public void Transform(string inputUri, string resultsFile);

The first argument of this method is the name (and path) of the XML file that will be transformed. The second argument is the name (and path) of the HTML file that will present the results in a browser. Here is an example of calling the Load() method:

using System;
using System.Xml.Xsl;

public class Exercise
{
    public static int Main()
    {
        XslCompiledTransform xctVideos = new XslCompiledTransform();

        // Open the XSLT document
        xctVideos.Load("Videos.xslt");
        // Transform an XML file and save its results in an HTML document
        xctVideos.Transform("Videos.xml", "Videos.htm");

        return 0;
    }
}

When this method executes, it takes the XML document, transforms it, and stores the results in the HTML file of the second argument.

XSL Templates

Besides specifying the names of elements, the XSLT standard also defines how the elements of an XML document are accessed. This definition is carried by an element named template. The syntax of the template element is:

<xsl:template
  name= Qname
  match = Pattern
  priority = number
  mode = QName
</xsl:template>

The name attribute holds a common name, a namespace name in which case it would be preceded by a prefix, or a Web address. If you pass:

  • A regular name, the parser would try to find it in the XML document. If that name is not found, the parser would ignore it (no error would be produced). If the parser finds that name, it would use it
  • If you pass a name from a namespace, you must precede it with a prefix. In this case, the parser would look for that name in the namespace specified in the declaration. If the parser finds that name, it would use it for whatever you are trying to do. If that name is not found in the namespace, the parser would ignore it and would not produce an error

The match attribute specifies how, or from where, the parser should start building a complete name (like a file path in Windows Explorer) for an element. For example, if you specify its value as / or as the name of the root, the parser would start from the root element. You can also specify the name of another element, depending on what you are trying to do. The template element must have either a name or a match attribute or both. Here is an example:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match=...>
    <html>
      <head>
      <title>Video Collection</title>
      </head>
      <body>
   
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

Raw Text

The extensible style sheet language allows you to add basic text to its document. To do this, create an element named text and set its value as the text you want. Here is an example:

 <?xml version="1.0" encoding="UTF-8"?>"
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="/">
    <html>
    <head>
    <title>Video Collection</title>
    </head>
    <body>
      <div align="center">
        <p><xsl:text>This document allows me to keep track of my personal collection</xsl:text></p>
      </div>
    </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

This would produce:

Raw Text

 
 
 

Transforming an XML Element

 

Introduction

The purpose of an extensible style sheet is to better display the values of an XML document. The primary object that holds a value in an XML document is an XML element. This means that you must "transform" an element to display its value. In the XSLT document, specify what value to display and when. To do this, in the body section, create an element named value-of. The syntax of the value-of element is:

<xsl:value-of
  select = Expression
  disable-output-escaping = "yes" | "no" 
</xsl:value-of>

The element must have an attribute named select that holds an expression that the parser must follow to identify an element. If you specify the match value of the template element as the name of the root, the value of the select attribute of the value-of element can be the name of an element that is a child of the root. Here is an example:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="videos">
    <html>
    <head>
    <title>Video Collection</title>
    </head>
    <body>
      <div align="center">
        <h2><xsl:value-of select="DocumentTitle" /></h2>
      </div>
    </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

This would produce:

Transforming an XML Element

If you specify the match value of the template element as "/", if you want to access an element that is a child of the root, precede its name with the name of the root for the value of the select attribute of the value-of element. The above document is the same as:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <html>
      <head>
      <title>Real Estate - Properties Listing</title>
      </head>
      <body>
        <div align="center">

          <h2><xsl:value-of select="videos/introduction" /></h2>
  
        </div>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

This would produce the same result as previously. In the same way, you can select other values from the XML document. Here are examples:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <html>
    <head>
    <title>Video Collection</title>
    </head>
    <body>
      <div align="center">
        <h2><xsl:value-of select="videos/DocumentTitle" /></h2>
        <h3><xsl:value-of select="videos/introduction" /></h3>
      </div>
    </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

This would produce:

Transforming an XML Element

Applying Templates

Another technique consists of creating one or a series of templates and applying them in the desired section(s). In this case, create a template for each element. In the area where you want to use the format(s), create an XSLT element named apply-templates. The syntax of the apply-templates element is:

<xsl:apply-templates
  select = Expression
  mode = QName
</xsl:apply-templates>

Both attributes are optional. Here is an example:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
       xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:template match="/videos">
    <html>
    <head>
    <title>Video Collection</title>
    </head>
    <body>
          <div align="center">
            <xsl:apply-templates />
          </div>
    </body>
    </html>
  </xsl:template>
  <xsl:template match="DocumentTitle">
     <h2><xsl:value-of select="." /></h2>
  </xsl:template>
  <xsl:template match="introduction">
     <h3><xsl:value-of select="." /></h3>
  </xsl:template>
</xsl:stylesheet>

If you want to provide the nodes that the parser must consider, pass them in the select attribute. The mode is used by the parser to process an element multiple times. In this case, pass the name of the element to this attribute.

Transforming a Set of XML Elements

Instead of transforming one element at a time, you may have a series of elements and it would not be flexible to visit each element. In fact. it may be impossible to visit each element if the list of elements can grow or shrink any time. If the elements are child nodes, you can apply a loop to their parent and visit each child node. To support this operation, XSLT provides an element named for-each. The formula to use the for-each element is:

<xsl:for-each
  select = Expression
</xsl:for-each>

As done for the elements so far, the select attribute allows you to specify the element to use.

This is a typical list to which new elements (new houses in this case) can be added any time and undesired elements (such as sold houses) can be deleted any time. So it is not practical to visit each node. In fact, elements on the same level may not have the same child nodes and child nodes may not be arranged in the same order in each element. You can first create an XSLT file or section with a placeholder for each element. Here is an example:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <html>
    <head>
    <title>Video Collection</title>
    </head>
    <body>
      <h2>Video Collection</h2>
 
    <table>
      <tr>
        <td><b>Title</b></td>
        <td><b>Director</b></td>
        <td><b>Format</b></td>
        <td><b>Rating</b></td>
      </tr>
      <tr>
        <td>Placeholder for title</td>
        <td>Placeholder for director</td>
        <td>Placeholder for format</td>
        <td>Placeholder for rating</td>
      </tr>
    </table>
    </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

A solution is to use a for-each element to visit each child node. This can be done as follows:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <html>
    <head>
    <title>Video Collection</title>
    </head>
    <body>
      <div align="center">
      <h2>Video Collection</h2>
        <table>
          <tr style="background-color: #B8B8B8">
            <td>
              <b>Title</b>
            </td>
            <td>
              <b>Director</b>
            </td>
            <td>
              <b>Format</b>
            </td>
            <td>
              <b>Rating</b>
            </td>
          </tr>
          <xsl:for-each select ="videos/video">
            <tr style="background-color: #E2E2E2">
              <td>
                <xsl:value-of select="title" />
              </td>
              <td>
                <xsl:value-of select="director" />
              </td>
              <td>
                <xsl:value-of select="format" />
              </td>
              <td>
                <xsl:value-of select="rating" />
              </td>
            </tr>
          </xsl:for-each>
        </table>
      </div>
    </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

This would produce:

Transforming an XML Element

Transforming XML Attributes

As you may know already, an XML atribute is a child element created inside of the start tag of a node. Here is an example of an XML document with attributes:

<?xml version="1.0" encoding="utf-8" ?>
<videos common-name="Video Collection" purpose="To keep track of personal/home videos">
  <video shelf-number="PLT24857">
    <title France="Monsieur le D&#233;put&#233;"
           Italy="Il Distinto Gentiluomo"
           Spain="Su Distinguida Se&#241;or&#237;a"
           Croatia="Ugledni gospodin">The Distinguished Gentleman</title>
    <director>Jonathan Lynn</director>
    <length>112</length>
    <format screen="Wide Screen">DVD</format>
    <rating>R</rating>
    <year-released date-released="4 December 1992">1992</year-released>
  </video>
  <video shelf-number="SCF13948">
    <title Spain="El D&#237;a de Ma&#241;ana"
           Croatia="Dan Poslije Sutra"
           Portugal="O Dia Depois de Amanh&#227;"
           France="Le jour d&#039;apr&#232;s">The Day After Tomorrow</title>
    <director>Roland Emmerich</director>
    <length>124</length>
    <format>BD</format>
    <rating>PG-13</rating>
  </video>
</videos>

Because an attribute is related to its parent element, to access an attribute in an extensible style sheet, precede its name with the @ sign, but you must indicate its parent element. This can be done in the template element where you would provide the name of its parent element. Here is an example:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="video">
    <html>
    <head>
    <title>Video Collection</title>
    </head>
    <body>
      <div align="center">
        <xsl:value-of select="@shelf-number" />
      </div>
    </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

This wiykd produce:

Transforming XML Attributes

In the same way, you can transform other XML attributes from your style sheet. Also you can format the values of the attributes any way you want. Here is an example:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="title">
    <html>
    <head>
    <title>Video Collection</title>
    </head>
    <body>
      <p>Spanish Title: <xsl:value-of select="@Spain" /></p>
    </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

This would produce:

Transforming XML Attributes

If you have different elements that have attributes, you can specify the value of the match attribute of the template as the root or an ancestor. To access an attribute, use the following formula:

ParentElement/@AttributeName

Here are example:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="video">
    <html>
    <head>
    <title>Video Collection</title>
    </head>
    <h2>Video Collection</h2>
    <body>
      <p>Spanish Title: <xsl:value-of select="title/@Spain" /></p>
      <p>French Title: <xsl:value-of select="title/@France" /></p>
      <p>Portuguese Title: <xsl:value-of select="title/@Portugal" /></p>
    </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

This would produce:

Transforming XML Attributes

In the same, you can visit the attributes in an element using for-each and accessing each of them using the @ sign. Here are examples:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <html>
    <head>
    <title>Video Collection</title>
    </head>
    <h2>Video Collection</h2>
    <body>
      <xsl:for-each select="videos/video">
        <span>Video Title: <xsl:value-of select="title/@Spain" /><br /></span>
      </xsl:for-each>
    </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

This would produce:

Transforming XML Attributes

In the XSLT standards, the formula to transform an attribute is:

<xsl:attribute
  name = "attribute-name"  
  namespace = "uri-reference">
</xsl:attribute>

The name attribute is required. It can be a qualified or a local name. The namespace attribute is the address that defines where the transformating attribute was defined.

 
 
   
 

Home Copyright © 2014, FunctionX