codetoad.com
  ASP Shopping CartForum & BBS
  - all for $20 from CodeToad Plus!
  
  Home || ASP | ASP.Net | C++/C# | DHTML | HTML | Java | Javascript | Perl | VB | XML || CodeToad Plus! || Forums || RAM 
Search Site:



Previous Page  Page 1 Page 2 Page 3 Page 4  Page 6 Page 7 Page 8 Page 9 Page 10 Page 11 Next Page  

The Built-in Templates

We've seen that when you apply templates to a node, the XSLT processor tries to find the template that matches that node. But what happens when there isn't a template that matches a node? For example, if we applied templates to the <Name> child of the <Channel> element, as follows, but didn't have a template to match the <Name> element:

 

<xsl:template match="Channel">

  <h2 class="channel"><xsl:apply-templates select="Name" /></h2>

  <xsl:apply-templates select="Program" />

</xsl:template>

 

When the XSLT processor can't find a template to match the node that it's been told to process, it uses a built-in template. If you find that the result of your stylesheet includes text you didn't expect, the chances are that it's due to the built-in templates. Just because there isn't a template for a particular node that doesn't mean that it's not processed.

 

For elements, the built-in template is as follows:

 

<xsl:template match="*">

  <xsl:apply-templates />

</xsl:template>

 

This template uses two bits of syntax that we haven't seen before:

 

        The match attribute of the template takes the value *. Templates with a match pattern of * match all elements.

        The <xsl:apply-templates> element doesn't have a select attribute. If you use <xsl:apply-templates> without a select attribute, the XSLT processor collects all the children of the current node (which is the node that the template matches) and applies templates to them.

 

To see the effect of this, take another look at the part of the node tree containing the <Name> element:

 

 

The <Name> element has only one child node, a text node with the value BBC1. When you tell the XSLT processor to apply templates to the <Name> element, it will use the built-in template for elements, and hence apply templates to the text node.


 

Now, again, we don't have a template that matches text nodes in our stylesheet, so the processor uses a built-in template. The built-in template for text nodes is:

 

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

  <xsl:value-of select="." />

</xsl:template>

 

Again, this template uses a couple of new bits of syntax:

 

        The match attribute of the <xsl:template> element takes the value text(). Templates with a match pattern of text() match text nodes.

        The select attribute of the <xsl:value-of> element takes the value .. The path . selects the context node, so <xsl:value-of select="." /> gives the value of the context node, in this case the text node.

 

In combination, these two built-in templates mean that if you apply templates to an element, but don't have a template for that element (or any elements it contains), then you'll get the value of the text held within the element. So applying templates to the <Name> element means that you get the value BBC1 in the result.

If a processor can't find a template that matches a node, it uses the built-in template for that node type. In effect, these give the value of the elements to which you apply templates.

There are quite a few places in our stylesheet where we want to just get the value of an element. Rather than using <xsl:value-of> to get these values, we could apply templates to the elements and let the built-in templates do their work to give us the element values.

 

We've already done this with the template for <Channel> elements, to get the name of the channel:

 

<xsl:template match="Channel">

  <h2 class="channel"><xsl:apply-templates select="Name" /></h2>

  <xsl:apply-templates select="Program" />

</xsl:template>

 

We can also replace the <xsl:value-of> instructions in the template for <Program> elements to get the values of the <Start>, <Series>, and <Description> elements:

 

<xsl:template match="Program">

  <div>

    <p>

      <span class="date"><xsl:apply-templates select="Start" /></span>

      <br />

      <span class="title"><xsl:apply-templates select="Series" /></span>

      <br />

      <xsl:apply-templates select="Description" />


 

      <span onclick="toggle({Series}Cast);">[Cast]</span>

    </p>

    <div id="{Series}Cast" style="display: none;">

      <ul class="castlist">

        <xsl:apply-templates select="CastList/CastMember" />

      </ul>

    </div>

  </div>

</xsl:template>

 

and in the template for <CastMember> elements, to get the values of the <Character> and
<Actor> elements:

 

<xsl:template match="CastMember">

  <li>

    <span class="character">

      <xsl:apply-templates select="Character" />

    </span>

    <span class="actor">

      <xsl:apply-templates select="Actor" />

    </span>

  </li>

</xsl:template>

 

Both the <Character> and <Actor> elements actually contain <Name> elements giving the name of the character or actor. With the built-in templates, you get the value of the text held in these <Name> elements.

 

The stylesheet TVGuide6.xsl still contains the same number of templates, but applies templates to all the elements that it processes rather than simply getting their values. If you run TVGuide6.xsl with TVGuide.xml you should get exactly the same result as you did before. Changing the <xsl:value-of> elements to <xsl:apply-templates> elements hasn't altered the result of the stylesheet.

Extending Stylesheets

As we've seen in the previous section, the effect of the built-in templates is that if you apply templates to an element, you get all the text that's contained in the element, at any level. This is the same as what you get when you use <xsl:value-of> and select the element. In other words, if you don't have a template that matches <Program> elements or any of their descendants then the following instructions give you exactly the same result:

 

<xsl:apply-templates select="Program" />

<xsl:value-of select="Program" />

 

There are pluses and minuses to using <xsl:apply-templates> rather than <xsl:value-of>. The biggest downside is that it's less efficient to use <xsl:apply-templates> because it forces the XSLT processor to search through the stylesheet for templates that match the node rather than directly giving the value of the node. For this reason, I would generally only apply templates to elements that I know could contain other elements, and not to text nodes, attributes, or elements that I know only have text content.


 

 

On the plus side, using <xsl:apply-templates> makes it a lot easier to change the format of the value that you get from an element, just by adding a template for that element. For example, if I wanted to change the way I give the name of the series so that it's given as a link to a page on that series instead, I can add a template that matches the <Series> element and generates an <a> element in the result giving a link to the page.

 

<xsl:template match="Series">

  <a href="{.}.html">

    <xsl:value-of select="." />

  </a>

</xsl:template>

 

This uses an attribute value template (which we met in the last chapter) to give the URL for the page, using the value of the context node (the <Series> element) plus the string '.html'. For example, the element <Series>EastEnders</Series> will result in a link to EastEnders.html.

 

This flexibility is also very useful when the XML format that you're converting from isn't finalized. If we added <Description> elements to the <Character> and <Actor> elements, as in TVGuide2.xml in the code download, then we could update the stylesheet to cope with the change by adding templates for these elements so that they only generate the value of the <Name> rather than including the description. We do this in TVGuide7.xsl, which contains:

 

<xsl:template match="Actor">

  <xsl:apply-templates select="Name" />

</xsl:template>

 

<xsl:template match="Character">

  <xsl:apply-templates select="Name" />

</xsl:template>

 

If you didn't add these templates, then applying templates to the <Actor> or <Character> elements would result in text containing both the name and description of the actor or
character, concatenated.

Using templates allows you to extend your stylesheet more easily than you can if you use <xsl:for-each> and <xsl:value-of>.

Previous Page  Page 1 Page 2 Page 3 Page 4  Page 6 Page 7 Page 8 Page 9 Page 10 Page 11 Next Page  




Click here to Buy!

Buy Beginning XSLT here

© Copyright 2002 Wrox Press This chapter is written by Jeni Tennison and taken from "Beginning XSLT" published by Wrox Press Limited in June 2002; ISBN 1861005946; copyright © Wrox Press Limited 2002; all rights reserved.

No part of these chapters may be reproduced, stored in a retrieval system or transmitted in any form or by any means -- electronic, electrostatic, mechanical, photocopying, recording or otherwise -- without the prior written permission of the publisher, except in the case of brief quotations embodied in critical articles or reviews.











Recent Forum Threads
• Re: How to concatenate a string and a variable using perl?
• Re: repaint() slow performence..
• Re: How Can I Get The Height Of A Hidden <div>?
• Re: Firefox/IE doctype problem.
• Re: Plz its urgent:validation code
• Re: Write text strings to Serial Port
• Re: Error configuring webservice identity in reporting services 2005
• Re: sort hash by value, numerically
• Re: Accessing user control in master page from any content page


Recent Articles
ASP GetTempName
Decode and Encode UTF-8
ASP GetFile
ASP FolderExists
ASP FileExists
ASP OpenTextFile
ASP FilesystemObject
ASP CreateFolder
ASP CreateTextFile
Javascript Get Selected Text


© Copyright codetoad.com 2001-2010