Dmitry Arestov
Dmitry Arestov

Reputation: 1678

How does XSLT processor find matching templates?

For example, consider the following XML:

<root>
    <level1>
        <!--S-->
        <level2>bingo!</level2>
    </level1>
</root>

And assume we have two templates: match="level2" and match="level1/level2".

When parser reaches the level2 node, how exactly does it determine that current node is matched by both templates, and that it must choose second template because it is more specific? What is formal definition of a "more specific" template?

Upvotes: 3

Views: 257

Answers (1)

Abel
Abel

Reputation: 57189

I agree with FiveO that this is a duplicate question, but then again, you also ask specification what the difference is between foo and bar/foo and which one is selected.

Essentially, unless you specify a priority on the xsl:template declaration, the order in which things are matched is determined by the rules in 5.5 Conflict Resolution for Template Rules for XSLT 1.0, 6.4 Conflict Resolution for Template Rules for XSLT 2.0 and 6.4 Conflict Resolution for Template Rules. These are the formal definitions you asked for.

However, the basic rule is quite simple: the more specific a match, the higher the priority. Except that there is no difference in priority between multiple predicates or deeper paths.

If two templates match that have the same priority, in XSLT 1.0 and 2.0 the processor can either recover (take the last one in declaration order) or signal the error. In 3.0 you can set this behavior declarative with <xsl:mode on-multiple-match="xxx" />.

A NodeTest (which is your match="level2") gets default priority -0.5 and if it has a child axis specifier (which is your match="level1/level2") it gets default priority 0. Higher priority goes first, which is why bar/foo will match foo, provided it has a parent bar. Otherwise it will match foo.

The basics of these rules have not changed between XSLT versions, they have just been expanded to allow specification of new allowed syntax.

More information is in the linked question.

Update, based on comment:
You ask how this is implemented. I can only speak for our XSLT 3.0 processor, Exselt, and explain it in general lines, because the actual process is rather involved because of many subtleties and optimizations.

  • Processing starts with the initial context node with the initial mode
  • Processor keeps a hash of all modes and splits all unions into separate matching templates
  • Each mode has a list of patterns that are ordered by priority
  • Upon visiting a node (here the initial context node), the processor goes over all patterns and finds the first that matches
  • It does this by compare the path backwards (similar to how it is explained in the spec), as follows: ** The path to a node is known as an annotation ** The rightmost child axis step is taken and matched to the current node based on its NameTest or KindTest (see productions of these in the XPath spec) ** Only if it matches, the next (to the left) child axis step is matched, and so on ** If the full path matches, the predicate, if any is evaluated against the current node, this is done later, because it is a more involved process and may require the processor to move away from the current node, which is relatively costly.
  • If all matches, the matched template is executed with the current node set to the context node of the template.

Upvotes: 4

Related Questions