Introduction to XSLT

As a tool for text and database computing

2 Basics

Universitetet i Bergen

18-19 June 2002

C. M. Sperberg-McQueen

Tone Merete Bruvik

Vemund Olstad



I. Tuesday morning 2: Basics

I.1. Overview

  1. Tuesday a.m.: introductions
  2. Tuesday a.m.: basics (simple transformations, if, choose, selection by attribute values)
  3. Tuesday p.m.: modes (e.g. tables of contents)
  4. Tuesday p.m.: XPath
  5. Wednesday a.m.: functions, numbering
  6. Wednesday a.m.: near-identity transformations)
  7. Wednesday p.m.: named templates, recursion
  8. Wednesday p.m.: sorting and grouping

I.2. Tuesday a.m.: basics

  • overview of syntax
  • linking to document, batch processing
  • exercise: hello, world
  • generating output: literal text, literal elements, element and attribute constructors
  • flow of control (apply-templates, if, choose)
  • exercise: greetings
  • debugging: messages, default rule for unrecognized elements
  • further exercises

I.3. What is XSLT?

  • a solution to a ‘high-level formatting’ problem
  • an XML language for specifying transformations
    • into XSL formatting objects
    • into arbitrary XML
    • into HTML
    • into non-XML formats
    with
    • data replication
    • data movement
    • data insertion and deletion

I.4. Syntax of XSLT

XSLT is an XML vocabulary.
Key elements:
  • xsl:stylesheet
  • xsl:output
  • xsl:template match="..." mode="..."
  • xsl:value-of select="..."
  • xsl:apply-templates select="..."

I.5. Running XSLT

Some ways to run XSLT:
  • built into browser (link via xml-stylesheet processing instruction or other means)
  • from program library through API
  • via command-line interface
  • via GUI interface
  • ...
XSLT is a language, not a user interface.

I.6. Hello, world

A very simple example: XML document (hello-world.xml), XSLT.
Examine both files.
Process in batch mode.
Link using <?xsl-stylesheet type="text/xsl" href="../xslt-exx/hello-world.xsl"?> and examine in browser.

I.7. Greetings example

Consider the following XML (greeting.xml):
<!DOCTYPE greetings [
<!ELEMENT greetings (hello+) >
<!ELEMENT hello (#PCDATA) >
<!ATTLIST hello 
          xml:lang CDATA #IMPLIED >
<!ENTITY szlig   "&#223;" >
<!ENTITY uuml    "&#252;" >
]>
<greetings>
<hello lang="en">Hello, world!</hello>
<hello lang="fr">Bon jour, tout le monde!</hello>
<hello lang="no">Goddag!</hello>
<hello lang="de">Guten Tag!</hello>
<hello lang="de-schwaben">Gr&uuml;&szlig; Gott!</hello>
</greetings>

I.8. Debugging aids

Before we develop this stylesheet, two handy tools: xsl:message
<xsl:message>
  Writing file <xsl:value-of select="@file"/> ... 
</xsl:message>
and default rules:
 <xsl:template match='*'>
  <span style="color: red;" title="{name()}">
   &lt;<xsl:value-of select="name()"/>&gt;
   <xsl:apply-templates/>
   &lt;/<xsl:value-of select="name()"/>&gt;
 </xsl:template>

I.9. Greetings v1

XSL stylesheet v1:
<!DOCTYPE xsl:stylesheet 
      PUBLIC 'http://www.w3.org/1999/XSL/Transform'
             '/SGML/Public/W3C/xslt10.dtd' [
<!ENTITY lt "&#38;#60;" ><!--=less-than sign R:-->
<!ENTITY gt ">"         ><!--=greater-than sign R:-->
<!ENTITY nl "&#xA;">
]>
<xsl:stylesheet version="1.0"
		xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>

 <xsl:template match="/">
  <html>
   <head>
    <title>Hello, world! A simple XSLT demo</title>
   </head>
   <body>
    <h1>Hello world!</h1>
   </body>
  </html>
 </xsl:template>

</xsl:stylesheet>

I.10. Greetings v1 framework

Let's look at the details. First, the framework:
<!DOCTYPE xsl:stylesheet 
      PUBLIC 'http://www.w3.org/1999/XSL/Transform'
      '/SGML/Public/W3C/xslt10.dtd' [
<!ENTITY lt     "&#38;#60;" >
<!ENTITY gt     ">"      >
]>
<xsl:stylesheet version="1.0"
  xmlns:xsl=
    "http://www.w3.org/1999/XSL/Transform">

<!--* ... guts of stylesheet here ... *-->

</xsl:stylesheet>

I.11. Greetings v1 body

XSL stylesheet v1:
 <xsl:template match="/">
  <html>
   <head>
    <title>Hello, world! A simple XSLT demo</title>
   </head>
   <body>
    <h1>Hello world!</h1>
   </body>
  </html>
 </xsl:template>

I.12. Greetings v2

Add a default rule:
 <xsl:template match='*'>
  <xsl:element name="span">
   <xsl:attribute name="style">color:red</xsl:attribute>
   <xsl:text>&lt;</xsl:text>
   <xsl:value-of select="name()"/>
   <xsl:text>&gt;</xsl:text>
   <xsl:apply-templates/>
   <xsl:text>&lt;/</xsl:text>
   <xsl:value-of select="name()"/>
   <xsl:text>&gt;</xsl:text>
  </xsl:element>
 </xsl:template>

I.13. Greetings v2

Add apply-templates:
 <xsl:template match="greetings">
  <html>
   <head>
    <title>Hello, world! A simple XSLT demo</title>
   </head>
   <body>
   <xsl:apply-templates/>
   </body>
  </html>
 </xsl:template>

I.14. Greetings v2

Add template for hello:
 <xsl:template match="hello">
  <xsl:element name="h1">
   <xsl:apply-templates/>
  </xsl:element>
 </xsl:template>

I.15. Greetings v3

Change greetings template:
 <xsl:template match="greetings">
  <html>
   <head>
    <title>Hello, world! A simple XSLT demo</title>
   </head>
   <body>
    <h1>Hello, world! A simple XSLT demo</h1>
    <p>A hundred ways to say hello (er, well, 
     <xsl:value-of select="count(//hello)"/>
     ways, anyway).</p>
    <ol><xsl:apply-templates/></ol>
   </body>
  </html>
 </xsl:template>

I.16. Greetings v3

Change hello template:
 <xsl:template match="hello">
  <xsl:element name="li">
   <xsl:apply-templates/>
  </xsl:element>
 </xsl:template>

I.17. Greetings v4

Add new hello templates:
 <xsl:template match="hello[@lang='en']" 
   priority="2">
  <li style="font-family: Palatino Linotype; 
   color: #777;">
   <xsl:apply-templates/>
  </li>
 </xsl:template>

I.18. Resolving conflicts among matches

If we have both match="hello" and match="hello[@lang='en']", both match. Which applies?
  • choose highest priority
  • in case of tie, error
  • error recovery: use the later one
Further refinements in stylesheet import.

I.19. Styling the greetings

For example:
  • for English (en): font-family: Palatino Linotype; color: #777;
  • For Norwegian (no): font-family: Comic Sans MS; color: brown;
  • For French (fr): font-family: Script; color: blue; font-size: larger;
  • For German (de — or more precisely, all the values where the first two letters of the lang attribute are “de”: font-family: Arial Black; color: purple;
  • For Swabian German (de-schwaben): font-family: Arial; color: red;

I.20. Greetings v5

Add text to greetings template:
 <p>In T&uuml;bingen, one way is best:
  <xsl:apply-templates 
    select="hello[@lang='de-schwaben']"/>
 </p>

I.21. Greetings example

  1. hard-coded output
  2. tag each hello element as an h1
  3. provide introductory text with count of hello elements, and embed the hello elements themselves as li elements in an ordered list (ol)
  4. style different languages in different ways, using the style attribute on the output li elements:
    • for English (en): style="font-family: Palatino Linotype; color: #777;"
    • For Norwegian (no): style="font-family: Comic Sans MS; color: brown;"
    • For French (fr): style="font-family: Script; color: blue; font-size: larger;"
    • For German (de — or more precisely, all the values where the first two letters of the lang attribute are “de”: style="font-family: Arial Black; color: purple;"
    • For Swabian German (de-schwaben): style="font-family: Arial; color: red;"
  5. Select just one greeting to display (e.g. de-schwaben)

I.22. Flow of control

Several ways to affect sequence of processing:
  • <xsl:template match="...">...</xsl:template>
  • <xsl:apply-templates/>
  • <xsl:apply-templates select="..."/>
  • <xsl:apply-templates mode="..."/>
  • <xsl:if test="..."> ... </xsl:if>
  • <xsl:choose>
      <xsl:when test="..."> ... </xsl:when>
      <xsl:when test="..."> ... </xsl:when>
      <xsl:otherwise> ... </xsl:otherwise>
    </xsl:choose>
  • <xsl:for-each select="..."> ... </xsl:for-each>

I.23. Flow of control using match

 <xsl:template match="hello[@lang='no']" priority="2">
  <li style="font-family: Comic Sans MS; color: brown;">
   <xsl:apply-templates/>
  </li>
 </xsl:template>

 <xsl:template match="hello[@lang='fr']" priority="2">
  <li style="font-family: Script; color: blue; 
             font-size: larger;">
   <xsl:apply-templates/>
  </li>
 </xsl:template>

I.24. Flow of control using select

<p>In T&uuml;bingen:
 <xsl:apply-templates 
  select="hello[@lang='de-schwaben']"/>
</p>

I.25. Flow of control using choose

 <xsl:template match="hello" priority="1">
  <xsl:element name="li">
   <xsl:choose>
    <xsl:when test="@lang='en'">
     <xsl:attribute name="style">
      font-family: Palatino Linotype; color: #777;
     </xsl:attribute>
    </xsl:when>
    <xsl:when test="@lang='no'">
     <xsl:attribute name="style">
      font-family: Comic Sans MS; color: brown;
     </xsl:attribute>
    </xsl:when>
    <xsl:when test="@lang='fr'">
     <xsl:attribute name="style">
      font-family: Script; color: blue; font-size: larger;
     </xsl:attribute>
    </xsl:when>
    <xsl:when test="substring(@lang,1,2)='de'">
     <xsl:attribute name="style">
      font-family: Arial Black; color: purple;
     </xsl:attribute>
    </xsl:when>
    <xsl:when test="@lang='de-schwaben'">
     <xsl:attribute name="style">
      font-family: Arial; color: red;
     </xsl:attribute>
    </xsl:when>
   </xsl:choose>
   <xsl:apply-templates/>
  </xsl:element>
 </xsl:template>

I.26. Independent exercises

See the page of exercises (../slides/exercises.xml)