tags:

views:

193

answers:

3

What is the best resource to learn the principles by which XSLT applies template rules?

Questions like this seem like they should be relatively easy to answer, and certainly so after some study. I'm almost embarrassed to post them. But I have looked at Kay's XSLT Programmer's Reference, the XSLT Cookbook, and Learning XSLT, and I still cannot find a clear explanation of how a node and its children will be processed by a set of rules. Maybe I'm an idiot, but I haven't found Python, Linux, Apache, MySQL, or bash to be anything like XSLT for sheer frustration.

UPDATE Thank you for your answers. I won't be able to pick this up again for several days, but I do appreciate the help.

+2  A: 

This section in the specification on XSLT Template Rules is fairly straight-forward, and gives examples.

Don't think of XSLT as acting on your XML.

Think of your XML as flowing through XSLT.

XSLT starts at the root template, with an imaginary cursor at the root level of your document tree:

<xsl:template match="/">
    ...stuff in here...
</xsl:template>

In the middle, XSLT will start executing statements. If you have an <xsl:apply-templates select="...something..."/>, then it will find everything at the cursor that matches the XPath in the select=, and look for templates with a <xsl:template match="...something...">. The first one it finds, according to the precedence rules, it will execute.

While executing that new template, the same things apply, except the context is now the node that matched.

Those are the basics. So for example, if you have this XSLT program, then no matter what the input, you'll get <hello world="!"/> as the output:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:template match="/">
        <hello world="!"/>
    </xsl:template>
</xsl:stylesheet>

But if you have input like this:

<people>
    <name>Paige</name>
    <name>Hayley</name>
    <name>Hamlet</name>
</people>

and use this as a transform:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:template match="/">
        <html>
            <body>
                <table>
                    <xsl:apply-templates select="/people/name[substring(., 1, 1) = 'H']"/>
                </table>
            </body>
        </html>
    </xsl:template>
    <xsl:template match="name">
        <tr>
            <td>
                <xsl:value-of select="."/>
            </td>
        </tr>
    </xsl:template>
</xsl:stylesheet>

It will first set up an HTML file. It will then find all of the 'name' elements under the 'people' elements under the root element, and if they start with the letter 'H' a template will be searched for that matches 'name'. Since we have one, it will write out a table row with the name. It will execute that rule twice, and then the HTML elements will be closed, and the script will end.

Does this help?

lavinio
I get that. I still can't get to a reliable set of principles that anticipate how that flow will be directed.
chernevik
It always starts at the root template; from then on, what matters is the context. When you execute <xsl:apply-templates select="..."/>, essentially a list of all nodes that match the select= is made, and those are then each matched, in sequence, against all templates. The match will be made on the node (element, @attribute, text(), comment(), processing-instruction(), or * or @* wildcards) that matches most closely. "Closely" is defined in the spec as the one with the most specificity.
lavinio
@lavinio - "Think of your XML as flowing through XSLT" - nice way of looking at it.
Nic Gibson
A: 

If you have some money to spend on training, Ken Holman has an excellent set of XML/XSLT/XPATH/XSL-FO training courses.

http://www.cranesoftwrights.com/training/ptux/ptux-video.htm He links to some sample videos.

I have attended his training sessions in-person. He is very thorough and explains the processing model, functions, and aspects of XML/XSLT/XPATH. It is important to understand how the node trees are processed and how an XSLT engine "walks the tree". Then XSLT templates and the distinction between "push" and "pull" really make sense.

XSLT requires a different way of looking at things. Many programmers have a hard time adjusting or understanding XSLT because they keep thinking of things in terms of procedural code, rather than a more functional manner.

Mads Hansen
+1  A: 

The answers above all do a good job of explaining what happens if you have templates defined but it's very important to understand the built-in behaviour of XSLT as well.

Template processing is driven by the XSLT engine itself not (in general) by your code. In that way, it's very different to the procedural languages you've mentioned. If you have any background in functional programming that will help a great deal.

The initial behaviour of XSLT is to match the document node. The document node is an 'imaginary' node that acts as the parent of your xml document's root node. It represents the entire document. The built-in behaviour is effectively an xsl:apply-templates that looks like:

<xsl:apply-templates select='/|*'/>

The xpath statement matches the documentnode or any other element. It matches the root node and then traverses your document. Think of the document as a tree. At each element node it will execute exactly the same statement. XSLT traverses nodes in a left to right order (so if your root element has two children it will hit the first one in the document before the second). Since it's executing the select above it will then progress to the children of that node and do the same. This is a depth-first left-to-right traversal of the tree.

Now, at each element node the XSLT engine hits it will look for a matching template. The rules are relatively simple - it will choose to execute the most specific template. The built-in template is always the least specific. A template matching a full path is very specific:

<xsl:template match='/some/path/to/a/node'>...</xsl:template>.

A template matching just a node name is less specific:

<xsl:template match='node'>...</xsl:template>

If you have defined a template that the engine selects (any template you defined is going to get used in preference to a built-in), the default traversal above stops. It executes your template and stops unless your template starts a traversal again:

<xsl:template match='node'>
    <p><xsl:value-of select='@text'/></p>
    <xsl:apply-templates/>
</xsl:template>

That apply-templates above restarts our traversal (btw, apply-templates with no select attribute is the same as using select=''*.

I hope that helps. This is one of those situations where a diagram is the best possible approach.

Nic Gibson
I have found that working explicitly with the built-in templates does help. Still, I can't find a good mapping of what XSLT can do to how it actually does do. And I've spent about three or four weeks on it over the past year. Of the tools I've studied, this is easily the most frustrating.
chernevik
I've found that having a background in procedural programming can be an issue in itself when trying to understand xslt - it doesn't work the way programmers expect. I've found that when I teach this stuff that the non-programmers (or the occasional functional programmer) have fewer issues with the idea of how it all works.
Nic Gibson
Would studying functional programming help? What resources would you suggest?
chernevik