Default Rules

1. Default template action (Unwanted output)
2. Built in rules
3. Default templates, further clarification
4. Default templates

1.

Default template action (Unwanted output)

Jeni Tennison



> I wonder why a part of the XML-Tree is displayed in the transformed
> document, although I have no expression in the XSL-stylesheet.

This is happening because of the built-in templates in XSLT. XSLT has a couple of built in templates, which say:

  - when you apply templates to an element, process its child elements
  - when you apply templates to a text node, give its value

Together, it means that if you apply templates to an element but don't have an explicit template for that element, then its content gets processed and eventually you end up with the text that the element contains.

In your case, you're apply templates to the module element from your template:

>    <xsl:template match="/">
>       <xsl:apply-templates />
>    </xsl:template>

There's no template matching the module element, so the required and foo elements that it contains both get templates applied to them. There are no templates for either of those, so their children get templates applied as well -- the recordset elements. Only the recordset element within the required element has a template that matches it:


>    <xsl:template match="module/required/recordset">
>      <form action="foo.html" method="post">
>         advertnr<input type="Text" readonly="readonly" name="advertnr"
> value="{element[@name='advertnr']}" class="readonly" />
>      </form>
>    </xsl:template>

The recordset within the foo element doesn't have a template, so again its content gets templates applied and so on until you get to the text node 'TESTTEXT'. That text node's content gets output as text.

To stop this from happening, you have two choices. The first is to have a template that overrides the default template for text nodes and outputs nothing:


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

The second (and better) alternative is to only apply templates to the elements that you want to process. If you only want to process the recordset element in the required element, then tell the processor to apply templates to that element; don't tell it to process other elements:

<xsl:template match="/">
  <xsl:apply-templates select="module/required/recordset" />
</xsl:template>

Then you can have your template match all recordset elements, secure in the knowledge that the only one that will be processed is the one within the required element:

<xsl:template match="recordset">
  ...
</xsl:template>

2.

Built in rules

Evan Lenz

Built-in rule is used as follows:

1. copy text to result

Being aware of the nodes selected by <xsl:apply-templates/> as well as the template rules matching them, whether built-in or provided explicitly in the stylesheet, will enable you to better understand why the results of your transformations look the way they do, as well as to have better control over the result when controlling whitespace is important.

To summarize, here are the built-in template rules for each of the seven XPath node types:

Table 1. Actions of default rules

ElementsApply templates to children
TextCopy text to the result tree
CommentsDo nothing
PIsDo nothing
AttributesCopy the value of the attribute to the result tree
NamespaceDo nothing
RootApply templates to children

Note that unless you selectively process nodes using the select attribute of <xsl:apply-templates/>, the only nodes you'll have to worry about are those that qualify as children (the first four in the above list). Since the built-in rules for comments and PIs are to do nothing, all you really have to worry about is being aware of how built-in rules will be applied to elements and text, which we covered in painful detail above.

To avoid processing whitespace nodes in the source tree, you can use <xsl:strip-space/> in your stylesheet, the details of which I won't go into here.

The section on whitespace in chapter 3 of Michael Kay's book (XSLT Programmer's Reference) was very helpful to me and I highly recommend it along with the rest of the book.

3.

Default templates, further clarification

David Carlisle



  If I understand this right, the behavior of the default template is
  simply to render the text contents of nodes. 

Not directly, it simply recurses on elements and copies text nodes, ie it is as if you had

<xsl:template match="*">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="text()">
  <xsl:value-of select="."/>
</xsl:template>

in your stylesheet. By actually having templates that match those things you can change the behaviour, eg if you had

<xsl:template match="*"/>

Then the default behaviour on elements would be to discard them and all their contents.

  	<xsl:template match="/">
  		<xsl:apply-templates select="WHATEVER"/>
  	</xsl:template>
  
  The root node match says specifically apply this template WHATEVER,
  which by implication means to ignore all other nodes off the root which
  do NOT match this template.  Otherwise, if nodes are neither matched nor
  excluded, the default template applies to them.  Is that it?

The terminology here is very confused so I'm not sure what you mean, but I think that you mean something that is incorrect.

There can only be one root node in a document (it essentially _is_ the document, it isn't the top level element of the document)

The default template for / is the same as the one above for elements and applies templates to all its children, there can't be any top level text if teh input is well formed, and the default template for comments and pis is to discard, so by default processing moves to the top level element.

If that has multiple children and you only specify templates for one of them, you will get the result you described: text from all the other children will appear at the top level of the output.

4.

Default templates

David Carlisle



  If I understand this right, the behavior of the default template is
  simply to render the text contents of nodes. 

Not directly, it simply recurses on elements and copies text nodes, ie it is as if you had

<xsl:template match="*">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="text()">
  <xsl:value-of select="."/>
</xsl:template>

in your stylesheet. By actually having templates that match those things you can change the behaviour, eg if you had

<xsl:template match="*"/>

Then the default behaviour on elements would be to discard them and all their contents.

   <xsl:template match="/">
   <xsl:apply-templates select="WHATEVER"/>
   </xsl:template>
  
  The root node match says specifically apply this template WHATEVER,
  which by implication means to ignore all other nodes off the root which
  do NOT match this template.  Otherwise, if nodes are neither matched nor
  excluded, the default template applies to them.  Is that it?

The terminology here is very confused so I'm not sure what you mean, but I think that you mean something that is incorrect.

There can only be one root node in a document (it essentially _is_ the document, it isn't the top level element of the document)

The default template for / is the same as the one above for elements and applies templates to all its children, there can't be any top level text if teh input is well formed, and the default template for comments and pis is to discard, so by default processing moves to the top level element.

If that has multiple children and you only specify templates for one of them, you will get the result you described: text from all the other children will appear at the top level of the output.