views:

65

answers:

2

Given the following XML and XSL transformation, I'd expect two <node/> elements in the output containing the texts first and second. This expectation is based on the following reasoning:

  1. The template with match="/root" will execute first. The <xsl:apply-templates/> instruction in this template will apply the most specific templates for all child nodes.
  2. These <foo/> child nodes will be processed by the second template. This template also contains the <xsl:apply-templates/> instruction, which applies templates to the child nodes of these nodes.
  3. The <foo/> nodes only contain <bar/> nodes, which don't match any template. This implies that no further nodes will be processed.

XML

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="style.xsl"?>
<root>
  <foo name="first">
    <bar>
      <foo name="nested"/>
    </bar>
  </foo>
  <foo name="second">
    <bar>
      <baz>
        <foo name="nested"/>
      </baz>
    </bar>
  </foo>
</root>

XSL

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="/root">
    <output>
      <xsl:apply-templates/>
    </output>
  </xsl:template>
  <xsl:template match="foo">
    <node>
      <xsl:value-of select="@name"/>
    </node>
    <xsl:apply-templates/>
  </xsl:template>
</xsl:stylesheet>

However, the actual result of the above transformation contains four <node/> elements, of which two contain the text nested. This means that the second template is also applied to the most inner <foo/> nodes. But according to the aforementioned step 3, the processing engine should never reach these nodes.

I have tested the transformation in multiple web browsers and using the Notepad++ XML Tools plug-in, and all of them show the "wrong" result. So I guess I'm wrong here, but what's wrong with my reasoning?

+1  A: 

Your assumption is that template matching is done according to nesting levels. This is not the case.

<xsl:template match="foo">

This matches all foo elements, whatever their nesting level, so when calling apply-templates, all foo elements will use this template.

The built in template rules will also cause the bar nodes to be matched.

Oded
Yes, the template will match all `<foo/>` elements, regardless of nesting levels. But `apply-templates` *does* take nesting level into account. So without mentioning the built-in template, your answer is slightly inaccurate.
Niels van der Rest
@Niels - fair enough. Will update answer.
Oded
+2  A: 

But the bar nodes do match a template, they match the built in "*" template, which propagates the templates, calling the inner bar/node template

Woody
You're right, I wasn't aware of the [built-in templates](http://www.w3.org/TR/xslt#built-in-rule). Thanks.
Niels van der Rest