Some things that will make understanding the answers you get easier:
First and foremost, nodes and elements are not the same thing. Elements are nodes, but nodes aren't necessarily elements. You often find people using the terms interchangeably. There are actually four kinds of nodes in XML: elements, text nodes, processing instructions, and comments. (Attributes aren't really nodes, which I'll get to in a second.)
In XSLT, the root of an XML document isn't its top-level element; the root is an abstraction that doesn't really exist. The top-level element is a child of the root. For instance, here's a well-formed XML document whose root has five child nodes, including the top-level element:
<?xml-stylesheet href="mystyle.css" type="text/css"?>
<!-- this is a perfectly legitimate XML document -->
<top_level_element/>
Five? It looks like there are only three. I think I'll let you figure out what the other two are yourself. Hint: there could actually be seven nodes in that example.
The XPath expression /
finds the document root, not the top-level element. In the above case, to find the top-level element, you'd use /top_level_element
, or /*
. (It's always safe to use /*
to find the top-level element, since the document root must have a single element child.)
So armed with that knowledge, let's look at what apply-templates
does. It basically performs a two-step process: First, it builds a set of nodes. Then, and for each one, it finds a matching template (from among the templates in the XSLT file) and applies the template to it. As you observed in one of your comments, it's conceptually very similar to a loop.
The select
attribute is used in the first step. It provides an XPath expression that's used to build the node set that it's going to apply templates to. If no select
attribute is provided, the list it builds is all children of the context node. (The "context node" is the node that the current template is being applied to.)
The match
attribute on the template
elements is used in the second step. The stylesheet processor finds all templates whose match
attribute matches the node it's trying to apply templates to. If it finds more than one, it selects the most specific one it can, e.g. given these templates:
<xsl:template match="*"/>
<xsl:template match="foo"/>
<xsl:template match="foo[bar]"/>
a foo
element with a bar
child element will be matched by the third, a foo
element with no bar
will be matched by the second, and a baz
element will be matched by the first. (The actual method that XSLT uses is defined here; in practice, I've been using XSLT for nearly a decade and I've never once needed to know specifically how it works, though it's interesting.)
If it doesn't find a match, it will use the built-in default template for the type of node - basically, you can assume that any XSLT transform implicitly contains these templates:
<xsl:template match="*">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="text()">
<xsl:copy/>
</xsl:template>
<xsl:template match="processing-instruction() | comment() | @*"/>
Armed with all this knowledge, you can now understand the identity transform:
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
That matches any node or attribute (note that attributes aren't nodes, which is why @*
is needed), copies it, and then applies templates to all of its child nodes and attributes. (Only the document root and elements will have child nodes, and only elements will have attributes.) Since it's the only template in the transform, and it matches all nodes and attributes, it applies itself to all of the child nodes and attributes. Thus, it copies everything in the source tree to the output tree.
If you add this template to the identify transform:
<xsl:template match="foo"/>
you now have a transform that copies every node in the source tree except foo
elements - that second template matches foo
elements (the first one does too, but since the second one's match
attribute is more specific, it's the one XSLT chooses) and does nothing with them.
Given all that, the answers to your specific questions:
<xsl:apply-templates>
applies templates to the children of the context node.
Matched nodes aren't "returned" in step 1; the XSLT processor finds a template for each and applies it.
In this example, the context node is the document root, an abstract node that the top-level element and any comments or processing instructions outside it are the children of.