XSL template precedence

Maro picture Maro · Apr 19, 2011 · Viewed 15.8k times · Source

I have 2 Templates

<template match="vehicle_details[preceding-sibling::vehicle_type = '4x4']/*">
    ...
</xsl:template>
<xsl:template match="vehicle_details[descendant::color = 'red']/*" >
    ...
</xsl:template>

My question is: which template will take precedence on transformation. And can someone give me an overview/resources about XSL template precedence?

Thanks in advance!

Answer

Wayne picture Wayne · Apr 19, 2011

The full resolution process is described in section 5.5 of the XSLT spec.

In general, the following rules apply in order (e.g. a template eliminated from consideration due to lower import precedence is eliminated permanently, regardless of its priority):

  1. Imported templates have lower precedence than templates in the primary stylesheet
  2. Templates with a higher value in their priority attribute have higher precedence
  3. Templates without a priority attribute are assigned a default priority. Templates with more specific patterns take precedence.
  4. It's an error if the previous three steps leave more than one template in consideration, but XSLT processors can recover by defaulting to the last one in the file.

In your specific case both templates have the same priority, so #4 above applies. To demonstrate:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match=
             "vehicle_details[preceding-sibling::vehicle_type = '4x4']/*">
        template1
    </xsl:template>
    <xsl:template match="vehicle_details[descendant::color = 'red']/*">
        template2
    </xsl:template>
</xsl:stylesheet>

Applied to this input (both templates match):

<root>
    <vehicle_type>4x4</vehicle_type>
    <vehicle_details>
        <color>red</color>
    </vehicle_details>
</root>

Output:

template2

But if we swap the order of the templates:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="vehicle_details[descendant::color = 'red']/*">
        template2
    </xsl:template>
    <xsl:template match=
             "vehicle_details[preceding-sibling::vehicle_type = '4x4']/*">
        template1
    </xsl:template>
</xsl:stylesheet>

Then the output is:

template1