Wattle Software - producers of XMLwriter XML editor
 Home | Site Map 
 About Latest Version
 Awards & Reviews
 User Comments
 Download XMLwriter
 Download Plug-ins
 Download Help Manual
 Downloading FAQ
 Buy XMLwriter
 Sales Support
 Sales FAQ
 Sales Support
 Technical Support
 Submit a Bug Report
 Feedback & Requests
 Technical FAQ
 XML Links
 XML Training
 XMLwriter User Tools
 The XML Guide
 XML Book Samples
Wattle Software
 About Us
 Contact Details
Professional Visual Basic 6 XML

Buy this book

Back Contents Next

Variables and Parameters

Once you have read this section, you will have found out that its title is a bit deceptive. You, as a programmer, have certain expectations about a new programming language when you start learning it. One of them is that you expect it to be possible to store values in variables, change them and retrieve them later. Although XSLT has an element called variable, you actually cannot do much with it. This may sound unbelievable, but it is a result of the way XSLT works that you cannot have variables. This is a thing that beginning XSLT programmers have many difficulties grasping.


A variable in XSLT is really not what we would call a variable in VB, but more like a constant. The syntax for declaring a variable is like this:


<xsl:variable name="x" select="2"/>


Or you can declare it like this:


<xsl:variable name="x">2</xsl:variable>


These syntaxes are equivalent, but note that the first example uses an XPath expression and the second one uses an included fragment of XML. This causes the first variable to hold the numeric value 2 and the second one the string value '2'.


The value of a variable can be used in expressions and attribute value templates. The reference to a variable's value is done with $variablename, for example:


<xsl:variable name="x" value="2"/>


<xsl:value-of select="item[$x]"/>


<xsl:variable name="author">Teun Duynstee</xsl:variable>


<xsl:copy-of select="$author"/>


The copy-of element is a convenient way to insert the value of a variable into the output document.


A variable can be used both as a top-level element (child of the stylesheet element) and at template level (descendant of a template element). As a top-level element, the variable can be used from any place in the document. Within the template, the variable can be seen by all elements following the declaration (and their descendants).


In conclusion, the variable element doesn't really live up to its name, because it cannot change. There is no way to change the content. This is done by design. The XSLT specification does not want to specify any order for the evaluation of different nodes. By introducing changing values, it would become relevant for the result whether a certain action is performed before or after the change.


The param element works very much like the variable element. The param element has a name attribute and a select attribute, but the select attribute on the param element is only a default value. If a value is passed, this replaces the value in the select attribute.

Passing a Parameter to a Template

If a template has a parameter defined, a value can be passed when the template is executed (by apply-templates or call-template). Suppose you have this template:


<xsl:template name="numbered-item">

<xsl:param name="format" select="1. "/>

  <xsl:number format="{$format}"/>




If you call it using call-template, its index number would be formatted numerically (1. ). But we could also have the same template output the number in another format using the parameter format (which is used in the attribute value template in the number element):


<xsl:template match="OL/LI">

<xsl:call-template name="numbered-item">

  <xsl:if test="@count = 'alpha'">

    <xsl:with-param name="format" select="'a. '"/>





This template will match on LI elements that have an OL parent. The transformation of these elements is implemented in the template 'numbered-item'. Only if the matched element has a count attribute with value 'alpha' does the template get called with a passed parameter value. This will cause the called template to output the number of the element in another format.


The with-param element can be used as a child of call-template and apply-templates. The name must be specified; the value can also be specified with the content of the element (just like the variable and param elements can).

Passing a Parameter to a Stylesheet

Although the XSLT specification defines a way to declare global parameters, nothing is mentioned about passing a parameter to the stylesheet. This depends on the implementation of the library you use. The SAXON and XT implementations both allow passing parameters on the command line. In the developer's preview of MSXML, you can set a parameter to a stylesheet only by using the special XMLDOMXSLProcessor object. This object is new in the MSXML library and is intended to cache compiled stylesheets to improve performance for repeated transforms with the same stylesheet. If your stylesheet contains a parameter called $x, the following code could be used to make the transformation:


Dim oDoc as new MSXML2.DOMDocument

Dim oXSLT as new MSXML2.DOMDocument

Dim oResult as new MSXML2.DOMDocument

Dim oTemplate as new MSXML2.XSLTemplate

Dim oXMLDOMXSLProcessor as new MSXML2.XMLDOMXSLProcessor


oDoc.async = false

oXSLT.async = false


oDoc.load "http://www.comp.com/sourceDocument.xml"

oXSLT.load "http://www.comp.com/stylesheet.xsl"


Set oTemplate.stylesheet = oXSLT.documentElement


Set oXMLDOMXSLProcessor = oTemplate.createProcessor

Set oXMLDOMXSLProcessor.input = oDoc

Set oXMLDOMXSLProcessor.output = oResult


oXMLDOMXSLProcessor.addParameter("x", "Value we want to pass in")



There are quite a lot of objects that we need here, three DOMDocument objects for starters. One of them may be empty. It is the target for the transform (oResult). The second one contains the source document (oDoc) and the third one contains the stylesheet (oXSLT). oXSLT is used to build the right template object. This template is used to create an XMLDOMXSLProcessor object. We inform the processor about the input and output documents, and then finally add our parameter value and let it transform. As this library is by no means stable at the time of writing – it is only a preview after all – it is very possible (so indicates the preliminary documentation) that the syntax will be different in the final release. In any case, the functionality of passing parameters will be included in that release.

Top Level Settings

The top-level settings are a set of elements that can only be used at the top level of an XSLT document, and hold settings that specify how the stylesheet should be used. They specify the behavior of the processor on a few points.


The output element is a bag of attributes that indicate settings about the style of output that is generated. The main setting is defined in the method attribute. The possible values are xml, html and text.


If the method is set to xml, the output document will be an XML document. What this means depends largely on the other attributes of the output element:


The version attribute specifies which version of XML should be used – we only have version 1.0 now, but that will probably change in the future. This number will also appear in the XML declaration if one is generated. The default version is 1.0.

The encoding attribute sets the preferred encoding for the destination document. If it is not specified, XSLT processors will use UTF-8 or UTF-16. If an XML declaration is generated, this will contain the encoding string specified.

The indent attribute can be set to yes to allow the processor to include additional white space in the destination document. This can improve readability. The default setting is no.

The attribute cdata-section-elements tells the processor when to use CDATA sections in the destination and when to escape illegal characters by using entity references. The value can hold a white space separated list of element names. Text nodes that have a parent node in this list will be output as CDATA sections. All others will be escaped (characters like < will be replaced by entities like &lt;).

omit-xml-declaration can be set to yes to leave out the XML declaration. By default, XSLT will include one, reflecting the settings of encoding and version. Also, if the standalone attribute has any value, this value will show up in the XML declaration.

With the doctype-system and doctype-public attributes, the validation rules for the destination document can be set. If you use only doctype-system, the processor will include a <!DOCTYPE fragment just before the first element. The doctype will be the name of the root element. The system identifier (URL of the DTD) is the value of the doctype-system attribute. If you also specify a doctype-public attribute, the output will contain a doctype declaration referring a public DOCTYPE, with the value of doctype-system as its URL. If only doctype-public is used, it will be ignored.

Finally, the media-type attribute can be used to specify a MIME-type for the result. By default this is text/xml, but some XML-based document types may have their own MIME types installed.


If the method attribute on the output element is set to html, the results of some of the other attributes change a bit compared to the xml method.


The version attribute now refers to the version of HTML, with a default value of 4.0. The processor will try to make the output conform to the HTML specification.

Empty elements in the destination document will be outputted without a closing tag. Think of HTML elements like BR, HR, IMG, INPUT, LINK, META and PARAM.

Textual content of the script and style elements will not be escaped. So if the XSLT document contains this literal fragment:


<script>if (a &gt; b) doSomething()</script>


This will be output as:


<script>if (a > b) doSomething()</script>


If any non-ASCII characters are used, the processor should try to use HTML escaping in the output (&euml; instead of &#0235;).

If an encoding is specified, the processor will try to add a META element to the HEAD of the document. This will also contain the value for media-type (default is text/html).



<META http-equiv="Content-Type" content="text/html; charset=EUC-JP">



If the method attribute is set to text, the output will be restricted to only the string value of every node. The media-type defaults to text/plain, but you can use other MIME types. Think of generating RTF documents from an XML source document. These have no XML mark up, so the most appropriate method is text, with media-type set to application/msword. The encoding attribute can still be used, but the default value is system dependent (on most Windows PCs it will be ISO-8859-1).


Let's have a look at an example. The following stylesheet is used:


<?xml version="1.0" encoding="ISO-8859-1"?>

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

<xsl:output method="text" indent="yes"/>

<xsl:template match="/">



      This is literal text with an ëxtended character



        <TR><TD>Cell data</TD>

        <TD>Second cell</TD></TR>







We use this stylesheet on an arbitrary, valid XML document. Note that the output will always be the same literal XML tree. We will now only change the output method and have a look at the result. First the result for the xml method:


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



<TEST>This is literal text with an ëxtended character




<TD>Cell data</TD>

<TD>Second cell</TD>







Note that every element starts on a new line. This is the result of the indent="yes" attribute. If this had not been specified, all content would be concatenated on one line. This XSLT processor has defaulted its output to encoding UTF-8. UTF-8 supports the extended character ë, so this is not escaped.


Setting the method to html would generate:




<TEST>This is literal text with an &euml;xtended character




<TD>Cell data</TD><TD>Second cell</TD>







Note that the XML declaration has disappeared and the processor appears to have decided on a slightly different formatting around the TD elements. The processor has been assigned to indenting the resulting document, but in html mode, this may only be done in places that cannot influence the appearance of the document in a browser. Also, the ë character cannot be used in HTML, so it is escaped using the preferred HTML entity &euml; (not the numeric XML entity).


Using the text method, the result would be:


This is literal text with an ëxtended character

    Cell dataSecond cell


Only the string values of the nodes have been printed. The specified encoding is used, so the special character is no problem. Note that no white space appears between the values of the two TD elements. We will see more on white space in the next sections.

strip-space and preserve-space

What exactly happens to the white space in a document and in the XSLT document itself? This is one of the subjects that often puzzle XML developers. Spaces, tabs and linefeeds seem to emerge and disappear at random. And then there are the XSLT elements to influence them: strip-space, preserve-space and the indent attribute on the output element. Let's take a closer look.


During a transformation, there are basically two moments when white space can appear or vanish:


When parsing the source and stylesheet documents and constructing a tree.

Encoding a generated XML tree to the destination document.


Before any processing occurs, the XSLT processor loads the source and stylesheet into memory and starts to strip unnecessary white space. The parser removes all text nodes that:


consist entirely of white space characters.

have no ancestor node with the xml:space attribute set to preserve.

are not children of a white space-preserving element.


For the stylesheet, the only white space preserving parent element is xsl:text. For the source element, the list of white space preserving elements can be set using the strip-space and preserve-space elements from the stylesheet. By default, all elements in the source document preserve white space. With the elements attribute of strip-space, you can specify which elements should not preserve white space. Adding elements to the list of elements that have their white space preserved is done with preserve-space. The elements attributes accept a list of XPath expressions. If an element in the source matches multiple expressions, the conflict is resolved following the rules for conflicts between matching templates.


So if a stylesheet contained these white space elements:


<xsl:strip-space elements="*"/>

<xsl:preserve-space elements="PRE CODE"/>


The processor would strip all text nodes in the source document, except for those inside a PRE element or a CODE element.


After stripping space from the source and stylesheet documents, the processing occurs. The generated tree of nodes is then persisted to a string or file. By default, no new white space is added to the result document, except if the output element has its indent attribute set to yes.


On document level, it is possible to define certain groups of attributes that you need to include in many elements together. By grouping them, the XSLT document can be smaller and easier to maintain:


<xsl:template match="chapter/heading">

  <font xsl:use-attribute-sets="title-style">





<xsl:attribute-set name="title-style">

  <xsl:attribute name="size">3</xsl:attribute>

  <xsl:attribute name="face">Arial</xsl:attribute>



Here the attribute-set element defines a group of two attributes that are often used together. In the template for chapter headings, the attribute-set is applied to a literal element, but use-attribute-set can also be used on element, copy and attribute-set elements. Be careful not to use use-attribute-set by itself (directly or indirectly), as this would generate an error.


The namespace-alias element is used in very special cases, especially when transforming a source document to an XSLT document. In this case, you want the destination document to hold the XSLT namespace and lots of literal XSLT elements, but you don't want these to interfere with the transformation process. See the problem? You are shooting yourself in the foot there.


Using namespace-alias, you can use another namespace in the stylesheet, but have the declaration for that namespace show up in the destination document with another URI:


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


<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>


<xsl:template match="/">








Instead of declaring the literal XSLT output elements in their real namespace, they have a fake namespace in this document. In the destination document, the same prefixes will be used, but they will refer to another URI:


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

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




The key element is a very special one. It will take a little time to discover its full potential. It is more or less analogous to creating an index on a table in a relational database. It allows you to access a set of nodes in a document directly with the key() function, using an identifier of that node that you specify. Let's describe an example. We could, using the key element, define that the key person-by-name gives us access to PERSON elements by passing the value of their name attribute. If the key is set up correctly, we would use key('person-by-name', 'Teun') to get a result set of PERSON elements that have their name attribute set to 'Teun'.


To set this key, you would have used the element like this:


<xsl:key name="person-by-name" match="PERSON" use="@name"/>


Try to see what each of the attributes name, match and use specifies. The name attribute is simple: it just serves to refer to a specific key of which there may be many. The match attribute holds a pattern that nodes must match to be indexed by this key; this pattern is identical to the template match attribute. It is not a problem if the same node is indexed by multiple keys. For each node in the selected set, the XPath expression in the use attribute is evaluated. The string value of the result of this expression is used to retrieve the indexed node. Multiple nodes can have the same result when evaluating use in their context. When the key function is called with this value, it will return a result set holding all nodes that had this result. The result can be a node set. In this case, each of the nodes will be converted to a string and each of these strings can be used to retrieve the selected node.


Don't worry if you can't see the point of this yet. We will do an extensive example on this. Suppose we have this XML document:


<?xml version="1.0"?>






  <PERSON name="Peter">


      <PERSON name="Peter"/>

      <PERSON name="Archie"/>





You are transforming the XML source with an XSLT document that starts like this:


<?xml version="1.0" encoding="ISO-8859-1"?>

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


<xsl:key name="all-names" match="PERSON" use="@name"/>

<xsl:key name="parents-names" match="PERSON[CHILDREN/PERSON]" use="@name"/>



If you now use the key() function, your results will be:


Expression Used in key()


key('all-names', 'Peter')

Both PERSON elements with name="Peter"

key('parent-names', 'Peter')

Only the Peter that has children


Both Peters, because Peter is one of the traditional names in the family


Now what are the cases where using a key is a good idea? Think of situations where XML elements often refer to each other using some sort of ID, but without using the validation rules for IDs (because these are sometimes too rigid). The key construct can:


keep your code more readable.

depending on the implementation, which may help performance. The XSLT processor can keep a hash-table structure in memory of all key references in the source document. If these references are often used, performance gains can be substantial.

Built-in Functions

XSLT has defined a set of built-in functions that can be used in expressions. These are complementary to the functions already available through XPath. These XPath functions include string functions like starts-with(), numeric functions like sum() and others like id(). These have been covered earlier in this chapter. We will not describe all available XSLT functions here; we will just select a few. You can find all functions in Appendix D.

format-number(number, string, string)

The format-number function converts the numeric first argument to a string. To do this, it uses the second argument as a format specifier and the third (optional) argument as a reference to a decimal-format element. First, we will look how the function behaves if we do not specify our own decimal formats. Say we leave the third parameter out. The format that we can pass to the second parameter can hold two formats at a time: one for positive numbers, one for negative numbers. They are separated by the semicolon. The format is built up from these special characters:







digit, hides leading and trailing zeroes


decimal separator


grouping separator


negative prefix


multiply by 100 and show as percentage

multiply by 1000 and show per mille


any other character can serve as prefix or suffix


So using this function would give the following results:


Numeric Value


Result String


DM .00

DM 2.00


DM ##.00

DM 2.00














Different countries use different characters for separating the decimal part of a floating-point number from the integer part and for grouping the digits. That's why XSLT allows you to change the special characters to other symbols. This can be done by including an xsl:decimal-format element as a top level element in your document. The format-number function can refer to this decimal format by name. Consider this example:



  name = qname

  decimal-separator = char

  grouping-separator = char

  infinity = string

  minus-sign = char

  NaN = string

  percent = char

  per-mille = char

  zero-digit = char

  digit = char

  pattern-separator = char />


The name attribute is for referring to the format from a format-number function. All other attributes are for overruling the default character. This new character must be used in specifying the format string and will also be the output character:


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


<xsl:decimal-format name="numfrmt" decimal-separator="," grouping-separator="." />


<xsl:template match="/">

<xsl:value-of select="format-number(1567.8, '#.###,00', 'numfrmt')"/>





The output of this stylesheet will be 1.567,80.


The current() function returns the current context. This can be very useful inside subqueries in XPath expressions. It allows you to make constructs in an XPath expression that are similar to SQL inner joins, combining and comparing values from different contexts. Suppose we have this XML document:


<?xml version="1.0"?>



    <title>Dancing in the street</title>

    <artist>David Bowie</artist>

    <artist>Mick Jagger</artist>



    <title>State of shock</title>

    <artist>Michael Jackson</artist>

    <artist>Mick Jagger</artist>




We want to generate a list of all songs in the collection with their artists, but for every artist we want to include a link to the other songs in the collection that the artist performs. We will make the list in HTML, creating links from the artist's songs to the entry of that song. To do this, we use a template for the artist element like this:


<xsl:template match="artist">


    select="//Song[artist/text() = current()/text()]

           [title != current()/ancestor::Song/title]



      <xsl:attribute name="href">#Song<xsl:number/></xsl:attribute>

      <xsl:value-of select="title"/>





It generates a piece of XML looking like this:


<a href="#Song3">Under pressure</a>


<a href="#Song4">Knock on wood</a>



The essential part here is the XPath expression in the for-each element. It selects the set of all song elements and filters the set by introducing two predicates.


The first predicate: [artist/text() = current()/text()] checks if the text of the artist element (relative to the selected song element) is equal to the text of the current context. The current context is the context of the for-each element, not the context of the predicate. This will select those song elements that have an artist element with the same name as the current artist. This will include the current song (which obviously has the same title as the current song).


The second predicate: [title != current()/ancestor::Song/title] checks if the title of the predicate's context (a song element) is equal to the title of our current context's song ancestor. The element is included in the filtered set if the titles are not equal. The function of this predicate is to remove the song itself from the list of references to other songs. The complete stylesheet, called artist.xsl, can be downloaded from the Wrox web site.

document(object, node-set)

The document() function is specified to combine information from several documents into one destination document. Suppose you have a directory with a load of articles in XML format. All have references to other documents in the same directory. The part that defines the references to other articles look like:




    <Author>Teun Duynstee </Author>


  <Title>An interesting article </Title>

  <Intro> ... </Intro>

  <Body> ... </Body>


    <Item type="URL" loc="http://www.asptoday.com/art2">Some other article</Item>

    <Item type="local" loc="2"/>




As you can see, there are two kinds of references; references by URL and local references. The local references point to other articles of the same format in the same directory. The files are called art1.xml, art2.xml, etc… The local reference in the example refers to art2.xml (indicated by loc="2").

What we would like to do now is to generate HTML documents that display a styled version of the XML article. The referenced articles are particularly tricky. We want them to appear like this:


Some other article [external]

A great article (by: James Britt)


Note how the first article is displayed using only content from within the source document, while the second reference displays data about the referenced document that is not available in the source (the title and author). How is this done?


<xsl:template match="Item">

  <xsl:if test="@type='URL'">

    <a href="{@loc}"><xsl:value-of select="."/></a>


  <xsl:if test="@type='local'">

    <a href="art{@loc}.xml"><xsl:value-of select="document(concat('art', @loc, 


    (by: <xsl:apply-templates select="document(concat('art', @loc,






The template for Item elements is split into two parts. The first part is executed if an Item has type='URL'. This generated an HTML link with the loc attribute as its href attribute and the contained text as its title. This is simple – we've done this before. Note the use of an attribute value template in the literal element a.


The second part of the template is more interesting. If the type of the reference is local, then the href is constructed in a specific way, concatenating a string together. Now for the title of the referred document: from the select attribute of a value-of element, we call the document function, passing it the relative URL and a small XPath expression, indicating the fragment that is referred to. The result is that the value-of action is executed on the title of the referred document, effectively outputting the content of the title element. After that, you see the apply-templates being used with a remote fragment.


In this example, we used only one parameter, a string value. It is also possible to pass in a node set. If you do so, the document() function will convert all nodes to their string values and use these as URIs. The document() function then returns a node set of external documents. The second, optional, parameter indicates the base URI to use for relative URI references.


The generate-id() function does just what you would expect: it generates a unique identifier. The identifier is always a string of alphanumeric characters, making sure that it can be used as an XML qualified name (think of filling an ID type attribute). The identifier depends on the first element in the passed node set. If no node set is passed, the context node is used. The implementation is free to choose any convenient way to generate a unique string, as long as it is always the same string for the same node.

Simplified Syntax

For very simple stylesheets that consist of only one template matching the root, a special simplified syntax is specified. In this simplified syntax, the whole document is the content of the template. The stylesheets that can use this simplified syntax are often doing transformations, mostly consisting of literals defining a template document. Only a few values from the source document are entered in specific locations.


The XML documents defining an article's content could be transformed by this stylesheet:


<HTML xmlns:xsl="http://www.w3.org/1999/XSL/Transform”>


<H1><xsl:value-of select="/Article/Title"/></H1>

<p><b><xsl:value-of select="/Article/Intro"/></b></p>

<p><xsl:value-of select="/Article/Body"/></p>



©1999 Wrox Press Limited, US and UK.

Buy this book

Select a Book

Beginning XML
Beginning XHTML
Professional XML
Professional ASP XML
Professional XML Design...
Professional XSLT...
Professional VB6 XML
Designing Distributed...
Professional Java XML...
Professional WAP

© Wattle Software 1998-2019. All rights reserved.