Matching child elements in XSL

xml, xpath, xslt

Solution

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.

Problem

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.&#xa;</xsl:text> </xsl:template> <xsl:template match="xml/*"> <!-- will be called twice --> <xsl:text>other element countered.&#xa;</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.&#xa;</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...

Original source

Related problems