XSLT templates' ambiguity clarification
xpath, xslt, xslt-1.0, xslt-2.0
Solution
Your result is due to implicit template priorities. You can explicitly specify a priority on any template:
<xsl:template match="foo" priority="2"/>
But in most cases, you do not state explicitly what priority you would like a template to adopt - and that's where the default priorities step in. If there is conflict between templates, that is, if an input node matches several templates, XSLT defines a conflict resolution procedure that makes use of the default priorities.
The two templates that cause the processor to issue a warning:
<xsl:template match="root/value">
and
<xsl:template match="root/value[. = 'false']">
have the same default priority (0.5). You would think that the match pattern `match="root/value[. = 'false']"` is more specific than `match="root/value"`, but as far as the specification is concerned, it is not - they have exactly the same priority.
And that is why an ambiguous rule match is reported. An ambiguous rule match is a situation where the conflict cannot be resolved with either the explicit or implicit priorities. As a last resort, the last template is chosen.
To complete this thought experiment, change the order of templates to
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root/value[. = 'false']">
<false_value/>
</xsl:template>
<xsl:template match="root/value">
<true_value/>
</xsl:template>
</xsl:stylesheet>
And the result will be (see it online here):
<?xml version="1.0" encoding="utf-8"?>
<root>
<true_value/>
<true_value/>
</root>
As you can see, for both `value` elements, the last template is chosen.
Why, then, does adding `root/` to a template match result in a warning about template ambiguity?
The specific change you make is from
<xsl:template match="value">
to
<xsl:template match="root/value">
This changes the default priority (as discussed above) of the template. The default priority of `value` is 0, the default priority of `root/value` is 0.5. Only in the second case a conflict will arise, because the default priority of the other template is also 0.5.
Adding `root/` to the second template:
<xsl:template match="root/value[. = 'false']">
does not change anything, the default priority remains 0.5.
See the relevant part of the XSLT specification. Caveat: the default priorities there are not exactly easy to read.
All priorities:
<xsl:template match="value"> 0
<xsl:template match="value[. = 'false']"> 0.5
<xsl:template match="root/value"> 0.5
<xsl:template match="root/value[. = 'false']"> 0.5
Problem
When ran the following input XML ``` <root> <value>false</value> <value>true</value> </root> ``` against the following XSLT: ``` <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="value"> <true_value/> </xsl:template> <xsl:template match="value[. = 'false']"> <false_value/> </xsl:template> </xsl:stylesheet> ``` I get `value` element with 'false' as its content changed to `false_value`.. and all other `value` elements are turned into `true_value`. Output: ``` <?xml version="1.0" encoding="utf-8"?> <root> <false_value/> <true_value/> </root> ``` But only when I change the template match to `root/value` do I get ambiguous template warning. ``` <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="root/value"> <true_value/> </xsl:template> <xsl:template match="root/value[. = 'false']"> <false_value/> </xsl:template> </xsl:stylesheet> ``` Please help me by explaining what difference does addition of `root` to the xpath in `xsl:template`'s `@match` makes that I get this warning.(`Ambiguous rule match for /root[1]/value[1]`)