I thought I saw a mistake in an answer to this question, and pointed it out. I was told I was incorrect, and my answer was later deleted.
I still don't see how I was wrong. Therefore, I am posting here and hoping someone can explain my misunderstanding to me.
The answer I responded to explained the use of apply-templates. It contained the following XML and XSL, describing how the templates would be matched:
<!-- sample XML snippet -->
<xml>
<foo /><bar /><baz />
</xml>
<!-- sample XSLT snippet -->
<xsl:template match="xml">
<xsl:apply-templates select="*" /> <!-- three nodes selected here -->
</xsl:template>
<xsl:template match="foo"> <!-- will be called once -->
<xsl:text>foo element encountered</xsl:text>
</xsl:template>
<xsl:template match="xml/*"> <!-- will be called twice -->
<xsl:text>other element countered</xsl:text>
</xsl:template>
My comment was that the last template in should be:
<xsl:template match="*"> <!-- will be called twice -->
<xsl:text>other element countered</xsl:text>
</xsl:template>
because the current node is already <xml>
I was told:
No, xml/* is a pattern that matches child elements of an element with the name xml.
Testing the original answer
However, with this XML:
<xml>
<foo /><bar /><baz />
</xml>
And this XSL stylesheet (filling out the snippet above):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="xml">
<xsl:apply-templates select="*" /> <!-- three nodes selected here -->
</xsl:template>
<xsl:template match="foo"> <!-- will be called once -->
<xsl:text>foo element encountered.
</xsl:text>
</xsl:template>
<xsl:template match="xml/*"> <!-- will be called twice -->
<xsl:text>other element countered.
</xsl:text>
</xsl:template>
</xsl:stylesheet>
I get:
other element countered.
other element countered.
other element countered.
Testing my 'corrected' version
If I replace the last template with:
<xsl:template match="*"> <!-- will be called twice -->
<xsl:text>other element countered.
</xsl:text>
</xsl:template>
as per my answer I get:
foo element encountered.
other element countered.
other element countered.
which would appear to be correct.
I hope my question doesn't break any guidelines, but I can't see that I'm wrong and am hoping someone can explain it more fully.
PS. I'm afraid my original response on the other question was posted as an answer, not a comment, as I don't have enough points to post comments yet. I wasn't sure what the best thing was to do...
This is correct, according to the rules on the default priority of templates. A template matching foo
has default priority 0, one matching *
has default priority -0.5, but one matching xml/*
has default priority 0.5. The xml/*
template is considered more specific than the foo
one, so it wins when either could match.
So you were right that the template's match expression needed to be *
rather than xml/*
, but not for the right reason - an xml/*
template can match for an apply-templates select="*"
when the current node is xml
, and it will apply to any of those selected elements (since they are all children of xml
) except where there is another template with an explicit priority
greater than 0.5 that can take precedence.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With