Make your own free website on Tripod.com

Interesting facts about XSLT

In this page, I am compiling some interesting facts that I discovered during the course of my learning the XSLT language.

1. Behavior of XSLT variables

This I believe is the most misunderstood aspect about XSLT for a beginner. One of the first thing that anybody deals with, when learning a new programming language is variables.

Variables can be defined in XSLT like this -
<xsl:variable name="varname" select="varvalue" /> , or
<xsl:variable name="varname">value<xsl:variable>

The above two ways of defining variables are for different purpose. The first way binds a variable name to an XPath expression. Strictly speaking, select attribute has a value of type expression, and the value of the variable is the object that results from evaluating the expression. An expression must match the XPath production Expr. The XPath expression in select attribute, determines a node-set. Therefore we can say that, a variable name is bound to a node-set. Whereas a node-set can be thought of as a container for various kinds of nodes(like element nodes, text nodes, attribute nodes etc). The first way can also have a form like <xsl:variable name="varname" select="'string'" /> or <xsl:variable name="varname" select="0" /> . This will bind the variable name to a 'string literal' or a 'numeric value'.

The 2nd way binds a variable name to a Result Tree Fragment (RTF). This may sound confusing for a beginner. The  Result Tree Fragment is a technical term which is referred in the XSLT specification. The 2nd form of variable definition can have multiple forms like:

[1] <xsl:variable name="varname">mukul</xsl:variable> , or

[2] <xsl:variable name="varname">
        <temp>
          <a>1</a>
          <b>2</b>     
        </temp>
      </xsl:variable>

The form [1] binds a variable name to a simple (simplest!) RTF. This form is similar to declaration : <xsl:variable name="varname" select="'mukul'" /> . The form [2] binds a variable name to a tree fragment (XML fragment). So we can see, variables can contain complex structures (like XML fragments) other than primitive values (like strings or integers). The form [1] should not be preferred, when it can be written as <xsl:variable name="varname" select="'mukul'" /> ; as it is inefficient and has the wrong behavior when coerced to boolean.

How do XSLT variables compare with variables in other popular languages like Java or C?
The behavior is quite different. The most striking difference is that variables in Java or C can maintain state during program execution. That means, we can increment them, assign their value to other variables and so on. But variables in XSLT cannot change state. That means we cannot increment them or do things with them that are possible in Java or C. Many beginners to XSLT programming who come from procedural programming background (I did!), often find this characteristic of variables in XSLT quite strange (I also felt so initially. Until I found that this is actually a great thing!). Beginners are not easily able to adjust to this change. They think, if variables can be allowed to increment, or could do similar things as in Java or C, then it would make programming quite easy. From my experience, I can say it is not so! Now I cannot find any situation, where this "different behavior of variables" is a handicap to XSLT programmers.  The main purpose of XSLT language is to transform XML documents from one form to another form. This nature of variables I feel is a great innovative idea which XSLT designers incorporated into the language, keeping in mind the purpose (i.e. XML transformation). 

Michael Kay in his article: What kind of language is XSLT? notes - "XSLT is based on the concepts of functional programming in the tradition of languages such as Lisp, Haskell, and Scheme. A style sheet is made up of templates that are essentially pure functions -- each template defines a fragment of the output tree as a function of a fragment of the input tree, and produces no side effects. The no-side-effects rule is applied quite strictly (with the exception of escapes into external code written in languages such as Java). The XSLT language allows variables to be defined, but does not allow an existing variable to change its value -- there is no assignment statement. The reason for this policy, which many new users find bewildering, is to allow style sheets to be applied incrementally. The theory is that if the language is free of side-effects, then when a small change is made to an input document it should be possible to compute the resulting change to the output document without performing the entire transformation from scratch. It has to be said that for the moment, this remains a theoretical possibility, it is not something that any existing XSLT processor achieves."

This behavior of XSLT variables has many advantages. First it eliminates many side effects which are present in imperative programming. A program written in "side effect present" languages (like Java or C) are generally difficult to maintain. If a variable changes state in one part of the program, it may effect other parts of the program. Also if a variable can change state, it forces a particular order of execution. This is not desirable in XSLT. For e.g. if a variable is declared in one template, and if its state can change in another template, then this usually implies that templates have to execute in a particular order. If this is allowed, then XSLT will not be effective. This also allows many kinds of optimization by the XSLT processor. For e.g. XSLT processor may execute XSLT templates in parallel threads, which will not be possible if we force strict order of execution. If we see another example: Assume there is a function f(x). Let y := f(x) + f(x) i.e. we are adding the function result with itself. If variables cannot change state (i.e. there is no side effect), then XSLT processor may optimize the execution, by evaluating function f(x) only once, and multiply its result by 2 to get the final result; which will not be possible if variable values can be changed. To understand this, lets assume f(x) depends on a global variable which is declared outside the function. If f(x) modifies the global variable, then the 2nd f(x) call must be a new call. The XSLT processor cannot reuse the result from 1st call. 

XSLT variables can be declared like:
<xsl:variable name="varname">
   Result Tree Fragment   
</xsl:variable>

or, interestingly like (i.e. variables may contain a complete for loop!):
<xsl:variable name="varname">
   <xsl:for-each select="expr">
   </xsl:for-each>   
</xsl:variable>

This allows many interesting operations in a XSLT stylesheet.

So the variable construct in XSLT behaves quite differently than in imperative languages.

So, Why are they called variables? (Quoted from Michael Kay's book)
Some people have asked, why call it a variable if you can't vary it? The answer lies in the traditional mathematical use of the word variable: a variable is a symbol that can be used to denote different values on different occasions.

According to Colin Paul Adams (his quote on XSL-List, and a very accurate description):
You can't assign values to variables in XSLT. Variables in XSLT are like variables in mathematics - they are definitions of values, not memory locations.

References:
1) What kind of language is XSLT? - by Michael Kay
2) The Functional Programming Language XSLT - A proof through examples - by  Dimitre Novatchev
3) XSLT Programmer's Reference, 2nd Edition - by Michael Kay

(Thanks to Dimitre Novatchev and David Carlisle who helped to correct some mistakes.)

2.
xsl:apply-templates vs. xsl:for-each

This is a frequently asked question:
>It seems xsl:apply-templates and xsl:for-each do exact the same thing, I can't find anything one can do and the other can't. So which one should I use >at what occasion? Or is it just a personal preference?

When we write xsl:apply-templates instruction, it is actually an instruction to "find  template rules which match specific nodes from source tree". Technically, the nodes (for which template rules are being searched) may exist anywhere in the XML  document (which is a tree structure in memory), with respect to the context node. The template rules may be  written explicitly by the stylesheet writer. If it is not explicitly provided, a built in template rule is selected. If no template rule is found anywhere, or there is ambiguity in selecting the correct template rule, the XSLT processor will usually give an error. 

Whereas, the processing of xsl:for-each instruction takes place in different style. For e.g., lets say we are at a particular context node in the source tree (constructed from the XML document). The "select" attribute of xsl:for-each instruction represents a node-set (it is constructed with respect to the context node; or may be not). The body of xsl:for-each is applied for each node in the node-set (formed by the "select" attribute). Technically, the body of xsl:for-each creates part of the result tree (which later contributes to the final result tree).

There are many occasions, when we can use these two techniques interchangeably. xsl:for-each looks like a procedural approach (it is sometimes called pull processing) (interestingly, technically it isn't procedural. XSLT spec doesn't specify sequential execution of instructions within xsl:for-each. The instructions within xsl:for-each may execute in parallel or in any order. It is a decision, which can be made by the XSLT processor, possibly to optimize processing).

Whereas, xsl:apply-templates is generally called push processing (the explanation is above).

Dimitre Novatchev explained:

xsl:apply-templates is much richer and deeper in meaning than xsl:for-each, even simply because we don't know what code will be applied on the nodes of the selection -- in the general case this code will be different for different nodes of the node-list. Also, the code that will be applied can be written way after the xsl:apply templates was written and by people that do not know the original author.

See for example the thread:

 "xsl:for-each vs. xsl:apply-templates" in xsl-list from Nov. 2004, at:

http://www.biglist.com/lists/xsl-list/archives/200411/threads.html#00499

I have literally copied my statement from this thread.

3. Sibling axis and as="element()"

Following question was asked on XSL-List, and is related to XSLT 2.0.

Given this XML:

<xsl:variable name="foo" as="element(foo)+">
  <foo/>
  <foo/>
  <foo/>
</xsl:variable>

and this bit of XSLT:

<xsl:for-each select="$foo">
  <xsl:value-of select="count(preceding-sibling::*)"/>
</xsl:for-each>

I get this result:

000

What's the reason that <foo> elements are not siblings?

Michael Kay explained:

It's not a question of being "no longer" siblings. You've simply created three element nodes. You haven't attached them to any parent, therefore they are not siblings, and never were. If you want to make them siblings, use

<xsl:variable name="foo" as="document-node()">
  <xsl:document>
    <foo/><foo/><foo/>
  </xsl:document>
</xsl:variable>

or use the old syntax, which you can regard as an abbreviation for the above:

<xsl:variable name="foo">
  <foo/><foo/><foo/>
</xsl:variable>


4. Attribute Value Templates (AVTs)

I asked following question on XSL-List.

>How did XSLT language designers made a decision, that which attributes (covering the whole of XSLT / XPath language) will be
>attribute value template, and which not? As a XSLT programmer, what rule of thumb should be followed, that which attributes
>are attribute value templates, and which not?

Michael Kay explained:

Firstly, select and test attributes are always XPath expressions; attributes whose value is an XPath expression or a match pattern are never AVTs.

Secondly, attributes of top-level elements (declarations) are never AVTs. There's no absolute reason for that but it was true in 1.0 and we've kept it
that way.

Thirdly, attributes that contain the name of objects defined in the stylesheet are usually not AVTs. Examples, xsl:call-template/@name, xsl:apply-templates/@mode. But there are exceptions, for example xsl:result-document/@format.

Attributes that affect type checking, for example @as, @type, @validation, are not AVTs; similarly other attributes where it's likely that the
information will be useful at compile time, or where it doesn't make sense to change it at run time, for example tunnel=yes|no, required=yes|no.

But there's no absolute logic to it, for example disable-output-escaping=yes|no could have been an AVT, but isn't.