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 5 Page 6 Page 7 Page 8 Page 9  Page 11 Next Page  

Using Moded Templates

We've seen how to use separate templates to process different nodes in different ways. However, one thing that we might lose when we use templates like this is the ability to process the same node in different ways in different situations. For example, say we want to create a table of contents for the HTML page that we're generating, giving a list of the channels that the TV guide offers, as shown in the following screenshot:

 

 

The HTML underlying the above page is as follows:

 

...

<h1>TV Guide</h1>

<p>

  [<a href="#BBC1">BBC1</a>]

  [<a href="#BBC2">BBC2</a>]

  [<a href="#ITV">ITV</a>]

  [<a href="#Channel 4">Channel 4</a>]

  [<a href="#Channel 5">Channel 5</a>]

</p>

<h2 class="channel"><a name="BBC1" id="BBC1">BBC1</a></h2>

...


 

We can get the table of contents by processing the <Channel> elements, but we're already processing the <Channel> elements to get the lists of the programs available on each channel. We want to process the same <Channel> elements twice: once for their entry in the channel list and once to get their details.

 

This is fairly easy with <xsl:for-each> because the content of the particular <xsl:for-each> determines the result that you get. So we could do:

 

<h1>TV Guide</h1>

<p>

  <xsl:for-each select="TVGuide/Channel">

    [<a href="#{Name}"><xsl:value-of select="Name" /></a>]

  </xsl:for-each>

</p>

<xsl:apply-templates />

 

to get the entries in the channel list, and then either use another <xsl:for-each> or apply templates (as above) to the <Channel> elements to get their content later on.

 

However, you can also achieve this by using template modes. Modes allow you to process the same node with different templates in different situations. You can apply templates in a particular mode using the mode attribute on <xsl:apply-templates>, and you can define the mode for a template with the mode attribute on <xsl:template>. When you apply templates in a particular mode then the XSLT processor will only look at those templates with that mode.

 

With modes, then, you can apply templates to the same node in different modes to get different results. So in this case, we can use a template in ChannelList mode to generate the result for each channel in the channel list, as follows:

 

<xsl:template match="Channel" mode="ChannelList">

  [<a href="#{Name}"><xsl:value-of select="Name" /></a>]

</xsl:template>

 

This template will only match <Channel> elements if you apply templates in ChannelList mode. So we need to have an <xsl:apply-templates> element in the template for the root node that applies templates in ChannelList mode:

 

<h1>TV Guide</h1>

<p>

  <xsl:apply-templates select="TVGuide/Channel" mode="ChannelList" />

</p>

<xsl:apply-templates />

 

When you apply templates without setting the mode, then the processor uses templates that don't have a mode attribute.

You can use moded templates to get different processing for the same node in different situations.


 

Built-in Moded Templates

As you'll recall, when an XSLT processor can't find a template that matches a particular node then it will use a built-in template instead. There are similar built-in templates for moded templates, one for elements, which simply applies templates to their content in the same mode:

 

<xsl:template match="*" mode="any-mode">

  <xsl:apply-templates mode="any-mode" />

</xsl:template>

 

and another that matches text nodes in that mode and gives their value:

 

<xsl:template match="text()" mode="any-mode">

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

</xsl:template>

 

These built-in templates mean that you can get rid of superfluous templates and apply templates without explicitly specifying the nodes to which you're applying them in exactly the same way as you can with the default mode.

 

When applying templates in ChannelList mode, then, we don't have to specify the nodes to which we're applying templates and can just use:

 

<h1>TV Guide</h1>

<p>

  <xsl:apply-templates mode="ChannelList" />

</p>

<xsl:apply-templates />

 

The current node in the template (which matches the root node) is the root node, so the <xsl:apply-templates> in ChannelList mode with no select attribute will apply templates to the document element, the <TVGuide> element in ChannelList mode. There isn't a template for the <TVGuide> element in ChannelList mode, so the processor will apply the built-in moded template. This template selects the children of the <TVGuide> element, the <Channel> elements, and applies templates to them in ChannelList mode.

There are built-in moded templates in the same way as there are built-in normal templates.

There are three things that we need to do to TVGuide16.xsl to create a linked list of channels in our page:

 

1.       Add anchors to the headings for the channels in the main body of the page

2.       Create a template in ChannelList mode to give the link to each channel

3.       Apply templates in ChannelList mode at the point at which the channel list should be given on the page


 

We'll make these three changes to create a new version of our stylesheet, TVGuide17.xsl.

 

You can add the anchors to the headings by changing the template for the <Name> element child of the <Channel> element to include an <a> element whose name and id attributes give the name of
the channel:

 

<xsl:template match="Channel/Name">

  <h2 class="channel">

    <a name="{.}" id="{.}"><xsl:value-of select="." /></a>

  </h2>

</xsl:template>

 

The XHTML Recommendation advises that you use both the name and id attributes when creating anchors for backward and forward compatibility. We're not yet generating proper XHTML, but it's a good guideline to follow, as that's our final goal.

 

You can create the template for <Channel> elements in ChannelList mode to reference these links, as follows:

 

<xsl:template match="Channel" mode="ChannelList">

  [<a href="#{Name}"><xsl:value-of select="Name" /></a>]

</xsl:template>

 

Finally, you can apply templates in ChannelList mode in the template matching the root node to insert the channel list just under the title. The main content of the page comes after this channel list and is generated by applying templates in the normal mode:

 

<xsl:template match="/">

  <html>

    <head>

      ...

    </head>

    <body>

      <h1>TV Guide</h1>

      <p>

        <xsl:apply-templates mode="ChannelList" />

      </p>

      <xsl:apply-templates />

    </body>

  </html>

</xsl:template>

 

You could repeat the same list again at the bottom of the page very easily, by repeating the same instruction after the <xsl:apply-templates> that generates the main body of the page:

 

<xsl:template match="/">

  <html>

    <head>

      ...


 

    </head>

    <body>

      <h1>TV Guide</h1>

      <p>

        <xsl:apply-templates mode="ChannelList" />

      </p>

      <xsl:apply-templates />

      <p>

        <xsl:apply-templates mode="ChannelList" />

      </p>

    </body>

  </html>

</xsl:template>

 

This demonstrates one of the advantages of using templates over using <xsl:for-each> – you can reuse the same code by applying the same template. Transforming TVGuide3.xml with TVGuide17.xsl gives the display that we were aiming for, with a list of channel names at the top and the bottom of the page. Clicking on the channel name takes you to the program listing for that channel.

Previous Page  Page 1 Page 2 Page 3 Page 4 Page 5 Page 6 Page 7 Page 8 Page 9  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
• C++
• Re: refresh parent after closing pop up window
• Dynamic Insertion
• Date and Time function around the world???
• Significant Factors
• Perl array access
• Re: huffman encoding and decoding in C++...
• Perl One Liner: Replace {(
• Re: html including php, accessing the functions


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-2009