9
votes

Consider this XML:

<people>
  <person>
    <firstName>Deane</firstName>
    <lastName>Barker</lastName>
  </person>
</people>

What if two XSLT templates match an element through different XPaths? I know that if the "match" element on two templates is identical (which should never happen, I don't think), the last template will fire.

However, consider this XSL:

<xsl:template match="person/firstName">
    Template #1
</xsl:template>

<xsl:template match="firstName">
    Template #2
</xsl:template>

The "firstName" element will match on either of these templates -- the first one as a child of "person" and the second one standalone.

I have tested this, and Template #1 executes, while Template #2 does not. What is the operative principle behind this? I can think of three things:

  1. Specificity of XPath (highly doubtful)
  2. Location in the XSLT file (also doubtful)
  3. Some pre-emption of Template #2 by Template #1. Something happens during the execution of Template #1 that tells Template #2 not to execute.
4

4 Answers

8
votes

Your first point is actually correct, there is a defined order described in https://www.w3.org/TR/1999/REC-xslt-19991116#conflict. According to the spec person/firstName has a priority of 0 while firstName has a priority of -0.5. You can also specify the priority yourself using the priority attribute on xsl:template.

3
votes

I know that if the "match" element on two templates is identical (which should never happen, I don't think)

This can happen but would not be much point doing this and having two matching templates.

From the spec:

It is an error if this leaves more than one matching template rule. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing, from amongst the matching template rules that are left, the one that occurs last in the stylesheet.

So in other words you may get an error or it will just use the last template in your XSLT depending on how the processor your are using has been written to handle this situation.

3
votes

Note that the value of the match attribute is not an XPath expression (though it uses a subset of XPath syntax). It's an XSLT pattern. Absent explicit priority attributes, the choice comes down to which pattern has the highest default priority:

person/firstName has a default priority of .5

firstName has a default priority of 0

Thus, person/firstName wins.

A complete explanation of how conflict resolution works can be found here (although I recommend you study the entire chapter, "How XSLT Works"): Conflict Resolution for Template Rules

0
votes

Consider this with the context in mind. The first one matches, and changes the context n (so the second does not match). The context is set to AFTER the first one is selected and processed so the visible element from that context no longer contains "firstname". IF you want both to execute, then you can call them instead so that the context changes back to the top.

 <xsl:template match="people">
    <xsl:apply-templates select="person/firstname"/>
    <xsl:apply-templates select="firstname"/>
</xsl:template>