Template Priority

Contact Us or call 1-877-932-8228
Template Priority

Template Priority

Take a look at the following code samples:

Code Sample:

TemplatesParametersVariables/Demos/DefaultPriority.xml
<?xml version="1.0"?>
<?xml-stylesheet href="DefaultPriority.xsl" type="text/xsl"?>
<person>
	<name>
		<firstname>Paul</firstname>
		<lastname>McCartney</lastname>
	</name>
	<job>Singer</job>
	<gender>Male</gender>
</person>

Code Sample:

TemplatesParametersVariables/Demos/DefaultPriority.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
				xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
	
<xsl:template match="firstname">
	<xsl:value-of select="name()"/>: We found a first name! 
</xsl:template>
	
<xsl:template match="firstname[following-sibling::lastname]">
	<xsl:value-of select="name()"/>: 
		We found a first name followed by a last name! 
</xsl:template>

<xsl:template match="*">
	<xsl:value-of select="name()"/>: We found an element! 
	<xsl:apply-templates/>
</xsl:template>

<xsl:template match="text()"/>
</xsl:stylesheet>

Code Sample:

TemplatesParametersVariables/Demos/DefaultPriorityOutput.xml
person: We found an element! 
	name: We found an element! 
	firstname: We found a first name followed by a last name! 
lastname: We found an element! 
	job: We found an element! 
	gender: We found an element! 
	

The firstname element in the XML document matches all of the first three templates. But, the processor chooses the second template because it has the most specific match. The output is shown below with the output resulting from the firstname match in bold.

Conflicts such as the ones seen in the example above are resolved by assigning priorities to templates. We'll see how to explicitly assign priorities in a moment, but first let's look at the default priorities.

Default Priorities

There are three default levels of priority assigned to patterns in templates.

  1. Patterns that match a class of nodes (e.g., *) in any namespace have a default priority of -0.5.
  2. Patterns that match a class of nodes in a specific namespace (e.g., cw:*) have a default priority of -0.25.
  3. Patterns that match a node name (e.g., firstname) have a default priority of 0.
  4. Patterns that match a node according to its context (e.g., firstname[following-sibling::lastname] and name/firstname) have a default priority of 0.5.

Only the template with the highest priority will be matched. But what happens if a node matches two templates with the same priority. Compare the following two examples.

Code Sample:

TemplatesParametersVariables/Demos/SamePriority.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
				xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>

<xsl:template match="name/firstname">
	<xsl:value-of select="name()"/>: 
		We found a first name in a name element! 
	<xsl:apply-templates/>
</xsl:template>
	
<xsl:template match="firstname[following-sibling::lastname]">
	<xsl:value-of select="name()"/>: 
		We found a first name followed by a last name! 
</xsl:template>

<xsl:template match="text()"/>
</xsl:stylesheet>

Code Sample:

TemplatesParametersVariables/Demos/SamePriority2.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
				xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
	
<xsl:template match="firstname[following-sibling::lastname]">
	<xsl:value-of select="name()"/>: 
		We found a first name followed by a last name! 
</xsl:template>

<xsl:template match="name/firstname">
	<xsl:value-of select="name()"/>: 
		We found a first name in a name element! 
	<xsl:apply-templates/>
</xsl:template>

<xsl:template match="text()"/>
</xsl:stylesheet>

The only difference between these two XSLTs is the order of the templates. The specification states that it is an error to have two templates in an XSLT with equal precedence. However, it gives the XSLT processor the option of reporting this error or using the last-is-first rule, meaning that the template defined later should be used. In practice, XSLT processors generally use the last-is-first rule rather than report an error.

So, when you transform the SamePriority.xml against SamePriority.xsl, the output reads "firstname: We found a first name followed by a last name!"

When you transform the SamePriority2.xml against SamePriority2.xsl, the output reads "firstname: We found a first name in a name element!"

Assigning Priorities

Priorities can be explicitly assigned to templates using the priority attribute. By assigning a priority higher than .5 (e.g., 1), you ensure that the template in question will take precedence over any template that does not include an explicitly-defined priority. The example below illustrates this.

Code Sample:

TemplatesParametersVariables/Demos/SetPriority.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
				xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>

<xsl:template match="name/firstname" priority="1">
	<xsl:value-of select="name()"/>: 
		We found a first name in a name element! 
	<xsl:apply-templates/>
</xsl:template>
	
<xsl:template match="firstname[following-sibling::lastname]">
	<xsl:value-of select="name()"/>: 
		We found a first name followed by a last name! 
</xsl:template>

<xsl:template match="text()"/>
</xsl:stylesheet>

When you transform the SetPriority.xml against SetPriority.xsl, the output reads "firstname: We found a first name in a name element!", because the template that produces this output has an assigned priority of 1, which is higher than the default priority of the template that immediately follows it in the code.

Next