RE: [xsl] super basic xsl question

Subject: RE: [xsl] super basic xsl question
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Thu, 13 Jan 2005 18:36:12 -0000
There are several possible default template rules you can use when matching
unknown elements.

The one that's built-in is

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

This is quite useful when you're rendering document-oriented XML, because it
means "when you find an unknown element, ignore the tags and process the
content as if the tags were not there." If the element is intended to switch
on Ukrainian hyphenation rules, and you don't know how to do that, then it's
best to ignore the element but not to ignore its content.

Another useful rule is:

<xsl:template match="*">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>

This is called the identity template, and its effect is to copy any unknown
element from the source to the result - while still applying template rules
to its content. This is probably the one that you are most likely to want if
the source vocabulary and result vocabulary are the same.

Another one that you might see is:

<xsl:template match="*">
  <xsl:message>Unknown element <xsl:value-of select="name()"/></xsl:message>
</xsl:template>

This is useful if you intended to write template rules for all possible
elements, and you want to treat any other element as an error.

You sometimes see:

<xsl:template match="*">
  <xsl:copy-of select="*"/>
</xsl:template>

This copies unknown elements unconditionally to the result tree. It's less
flexible than the identity template, because you can't do any further
processing on the content of this element.

Occasionally you might want:

<xsl:template match="*"/>

which means that if there's an unknown element in the source tree, you want
to exclude not only that element, but all its content, from the result tree.

The answer to the question, why is the first one above the built-in default,
is that the WG probably thought that rendition of document-oriented XML was
the most common application area for XSLT. But don't be afraid to declare a
different default that suits your application better.

Michael Kay
http://www.saxonica.com/
 

> -----Original Message-----
> From: Jeb Boniakowski [mailto:jeb@xxxxxxxxxxx] 
> Sent: 13 January 2005 18:10
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: Re: [xsl] super basic xsl question
> 
> Wendell--
> 
> Thanks for the reply.  This is the kind of info I'm having a 
> hard time 
> getting from like w3schools.com, etc.
> 
> In this particular case, though, I want the template that matches the 
> value of <child> to be agnostic to the markup that is in 
> there, with no 
> more template processing, I just want whatever was already done (by 
> this point, that chunk of xml has been processed by other sheets, and 
> will be processed by later sheets) so I didn't want to do an explicit 
> match for the link tag.
> 
> In general though, on the topic of apply-templates, there is a larger 
> issue that trips me up.  Oftentimes, it seems that I mess up 
> my set of 
> templates in such a way that things get matched and copied to the 
> output tree automatically, even though they are matched.  To 
> deal with 
> this, I've been sticking a template at the top of my sheets that is:
> 
> <xsl:template match="text()"/>
> 
> Is this bad style?  Is it a crappy hack to deal with messed up 
> templates?  Or is it the correct way to suppress default rules?
> 
> I have situations where I have things along the lines of:
> 
> <node>
>    <description>Foo</description>
>    <datum>1</datum>
>    <datum>2</datum>
> </node>
> 
> When I do something like:
> 
> <xsl:template match="node">
>    <h1><xsl:value-of select="description"/></h1>
>    <ul><xsl:apply-templates/><ul>
> </xsl:template>
> 
> <xsl:template match="node/datum">
>   <li><xsl:value-of select="."/></li>
> </xsl:template>
> 
> I end up with:
> 
> <h1>Foo</h1>
> Foo  <!-- Extraneous foo that I don't want -->
> <ul>
>   <li>1</>
>   <li>2</2>
> </ul>
> 
> Tacking a <xsl:template match="text()"/> seems to catch the 'Foo' and 
> kill it, but why do I have to do this?  Does the 
> <apply-templates/> in 
> node automatically copy the text values of any child nodes 
> that are not 
> explicitly matched?  If so, why?  Is it better to have an additional 
> template that specifically matches 'description' and does 
> nothing?  Or 
> to take the <h1><xsl:value-of select="description"/></h1> out 
> and move 
> it into this explicit template? Or should I be doing something more 
> like <xsl:apply-templates select="datum"/>?
> 
> Again, thanks.
> 
> jeb.

Current Thread