
=pod

=head0 NAME

Chapter 9 - Using XML

=head1 ABSTRACT

This chapter looks at XML.  You may have heard of XML, it's 
quite popular.

=head1 CHAPTER OUTLINE

=over 4

=item o

Generating XML

=item o

XML.RSS plugin

=item o

XML.XPath and XML.DOM

=item o

Stylesheet-based transformation (views, etc)

=back




XML is becoming one of the most ubiquitous data formats. It is used for
both data storage and data exchange. Template Toolkit can be used to both create
XML documents and to convert them into other formats.

In this chapter we'll take a look at some of the tools that Template Toolkit
provides for working with XML.

=head1 Creating XML Documents


We will start be looking at how to create XML documents using Template Toolkit.
We will use the example of creating an XML document which contains data
about a TV show. Let's use (to pick a show at random) I<Buffy the
Vampire Slayer>.

=head2 Modelling Data About A TV Show

A TV show consists of a number of seasons. Generally one season is made
each year. Each season will have a regular cast. A season consists of
a number of episodes. We want to create an XML file which contains all
of this data about a TV show.

We won't go into the details of how we access the data about the
TV show, we'll just assume the existance of a module called TVShow.pm 
which will be our interface to details about a show. TVShow.pm has a 
constructor, C<new>, which is passed the name of a show and returns an
object which contains all of the data we need. It also has access
methods that return all of these values.

We'll further assume the existance of Template::Plugin::TVShow which 
allows us to use a TVShow object in our templates.

=head2 DTD for a TV show

When designing an XML document, it's useful to create a Document Type
Definition (or DTD) that defines what the XML document will look like.
A DTD simply helps you to focus on the structure of the document. None
of the Template Toolkit XML tools currently make any use of the DTD.

Here's the DTD that we'll be using for our XML.

  <!ELEMENT show (name, creator, seasons)>
  <!ELEMENT name (#PCDATA)>
  <!ELEMENT creator (#PCDATA)>
  <!ELEMENT seasons (season+)>
  <!ELEMENT season (cast, episodes)>
  <!ATTLIST season number CDATA>
  <!ATTLIST season year CDATA>
  <!ELEMENT cast (regular+)>
  <!ELEMENT regular (character, actor)>
  <!ELEMENT character (#PCDATA)>
  <!ELEMENT actor (#PCDATA)>
  <!ELEMENT episodes (episode+)>
  <!ELEMENT episode (name, summary)>
  <!ATTLIST episode number CDATA>
  <!ATTLIST episode date CDATA>

Whilst there are a large number of elements in this DTD it isn't very
complex. In English, the description looks something like this:

=over 4

=item *

A TV show consists of a name, a creator and a list of seasons.

=item * 

A list of seasons consists of one or more seasons.

=item *

A season consists of a cast and a list of episodes. It has two attributes -
the season number and the year of broadcast.

=item *

A cast consists of one or more regulars.

=item *

A regular has a character name and an actor name.

=item *

An episode list consists of one or more episodes.

=item *

An episode has a name and a summary. It has two attributes - the episode
number and the date of first transmission.

=back

For more information on creating and interpreting DTDs see T<XML in a Nutshell> by Elliotte Rusty Harold and W. Scott Means or T<Learning XML> by Eric T. Ray.

=head2 XML Template

A<ch10-create-xml> shows a simple template that will take use the TVShow
module to create an XML document conforming to our DTD.

=begin example Sample template to create an XML document

  Z<ch10-create-xml>[% USE show = TVShow(name) -%]
  <?xml version="1.0"?>
  <show>
    <name>[% show.name | html %]</name>
    <creator>[% show.creator | html %]</creator>
    <seasons>
  [%- FOREACH season = show.seasons %]
      <season number="[% loop.count %]"
              year="[% season.year %]">
        <cast>
        [%- FOREACH part = season.regulars %]
          <regular>
            <character>[% part.character | html %]</character>
            <actor>[% part.actor | html %]</actor>
          </regular>
        [%- END %]
        </cast>

        <episodes>
        [%- FOREACH episode = season.episodes %]
          <episode number="[% loop.count %]"
                   date="[% episode.date %]">
            <name>[% episode.name | html %]</name>
            <summary>[% episode.summary | html %]</summary>
          </episode>
        [%- END %]
        </episodes>
      </season>
  [% END -%]
    </seasons>
  </show>

=end

This template takes one parameter, C<name>, which can be passed in on the 
command line, so we can create a document for the I<Buffy the Vampire Slayer> 
using C<tpage> like this:

  $ tpage --define name='Buffy the Vampire Slayer' show.tt > show.xml

A<ch10-buffy-xml> shows an example of the XML created. Repeated sections have 
been replaced with ellipsis.

=begin example XML document describing I<Buffy>

  Z<ch10-buffy-xml><?xml version="1.0"?>
  <show>
    <name>Buffy the Vampire Slayer</name>
    <creator>Joss Whedon</creator>
    <seasons>
      <season number="1"
              year="1997">
        <cast>
          <regular>
            <character>Buffy Summers</character>
            <actor>Sarah Michelle Geller</actor>
          </regular>
          <regular>
            <character>Xander Harris</character>
            <actor>Nicholas Brendon</actor>
          </regular>

          ...

        </cast>

        <episodes>
          <episode number="1"
                   date="00:00:00 10-03-1997">
            <name>Welcome to the Hellmouth</name>
            <summary>Buffy Summers moves to Sunnydale</summary>
          </episode>
          <episode number="2"
                   date="00:00:00 17-03-1997">
            <name>The Harvest</name>
            <summary>The Master plans to escape by harvesting people</summary>
          </episode>

          ...

        </episodes>
      </season>

      ...

    </seasons>
  </show>

=end

The template itself doesn't do anything complex. It simply uses access
methods on the TVShow object to get the data that it needs. Notice that 
it uses the C<date> plugin to format the date and the C<loop.count> variable 
to create the season and episode numbers..

Notice also that anywhere that we are displaying text that could
possibly include characters that have a special meaning in XML (C<&>,
C<E<lt>>, C<E<gt>> or C<">) we use the C<html> filter to convert these
characters into their equivalent XML entity (C<&amp;>, C<&lt;>, C<&gt;>
and C<&quot;> respectively).


=head1 Processing RSS files with XML.RSS


Before we start looking at using Template Toolkit to process arbitrary XML
documents, let's take a look a plugin that can't be used to handle
an industry standard XML format - RSS.

RSS (Rich Site Summary) [footnote: though exact translations of the 
abbreviation seem to vary on a daily basis] is a method that web sites can 
use to exchange headlines and other data with each other. Web sites can 
produce RSS files which other web sites can periodically download and process.
These files contain information which the subscriber web sites can display 
along with links to more detailed information on the publisher's web site.
This gives the subscribers a relatively simple way to have frequently updated
information on their web site. A good example of this concept are the 
"slashboxes" that appear on the front page of U<http://slashdot.org/>. You 
can get more information about RSS from T<Content Syndication with RSS> by Ben Hammersley.

An RSS file consists of a small number of tags which describe the
web site that produced the file, together with a list of items. 
A<ch10-cpan-rss> is an example of an RSS file. This example is taken from the 
CPAN and it lists the most recent module uploads. You can see the most recent 
version of this file at U<http://search.cpan.org/rss/search.rss>. We've 
removed all but two ofthe modules from the file to keep the example to a 
manageable size.

=begin example Example RSS file from the CPAN

  <rss version="0.91">
    <channel>
      <title>search.cpan.org</title>
      <link>http://search.cpan.org</link>
      <description>The CPAN search site</description>
      <language>en</language>
      <image>
        <title>searchDOTcpan</title>
        <url>http://search.cpan.org/s/img/cpanrdf.gif</url>
        <link>http://search.cpan.org</link>
        <width>88</width>
        <height>31</height>
        <description>All Modules, All the time</description>
      </image>
      <item>
        <title>DateTime-Format-Builder-0.62</title>
        <link>http://search.cpan.org/author/SPOON/DateTime-Format-Builder-0.62</link>
      </item>
      <item>
        <title>VCS-Lite-0.04</title>
        <link>http://search.cpan.org/author/IVORW/VCS-Lite-0.04</link>
      </item>
    </channel>
  </rss>

=end

The structure of this file is easy to understand. The E<lt>channelE<gt> 
element contains a number of details about the web site providing the file 
in the E<lt>titleE<gt>, E<lt>linkE<gt>, E<lt>descriptionE<gt> and 
E<lt>languageE<gt> tags. Then we see the E<lt>imageE<gt> tag which contains 
details of an image that we can use to illustrate our display of the 
information. Following this there are a number of E<lt>itemE<gt> tags each 
of which includes information about one recently uploaded CPAN module.

Template Toolkit's support for RSS is provided by the plugin
C<Template::Plugin::XML::RSS> which is, in turn, a thin wrapper round
Jonathan Eisenzopf's C<XML::RSS>.

The RSS plugin makes it very simple to use RSS files in your templates.
To use it, you need to add the line

  [% USE rss = XML.RSS(rssfile) %]

Where C<rssfile> is a variable which is set to the filename of the RSS file
that you want to use. You can then access individual items from the
file using access methods on the C<rss> object. Here is a very simple
template to extract a list of the newest modules.

  [% rss.channel.title -%]

  [%- FOREACH item = rss.items %]
  * [% item.title -%]
  [% END %]

It's only a little more complex to build an HTML page as shown in
A<ch10-rss-html>.

=begin example Template to build HTML from an RSS file

  Z<ch10-rss-html><html>
    <head>
  [% USE rss = XML.RSS(rssfile) -%]
      <title>[% rss.channel.title | html %]</title>
    </head>
    <body>
      <h1>[% rss.channel.title | html%]</h1>
      <p><a href="[% rss.image.link | html %]"><img src="[% rss.image.url | html %]"
                                             title="[% rss.image.title | html %]"
                                             alt="[% rss.image.title | html %]" /></a></p>

      <ul>
      [%- FOREACH item = rss.items %]
        <li><a href="[% item.link | html %]">[% item.title |html %]</a></li>
      [% END %]
      </ul>
    </body>
  </html>

Notice that as with the XML document we produced in the previous section,
any text displayed is passed through the C<html> filter to turn 
dangerous characters into HTML entities.

From processing one RSS file link this, it's easy to move to 
processing a number of them on one page to create your own news page.

There is one slight complication with this scenario. There are a number
of different versions of the RSS file that you will find on the Internet.
You will come across versions 0.91, 0.92, 1.0 and 2.0.

The simple templates we've shown up to now will work with all versions
equally well, but versions 1.0 and 2.0 have a number extensions which
allow them to contain more information. The extensions in version 1.0
are incompatible with those in 2.0. Luckily the C<XML::RSS> plugin gives
us access to the version attribute from the RSS file so our templates
can make intelligent decisions on what data to expect to find.

For more details on the support of the extensions to RSS 1.0 and 2.0, see
the documentation for F<XML::RSS> at U<http://search.cpan.org/dist/XML-RSS/>.


=head1 Processing XML documents with XML.DOM



A number of standards for XML document processing. On of the most
popular ins the M<Document Object Model> (or DOM). Template Toolkit supports
this method through the plugin C<Template::Plugin::XML::DOM> which is, in
turn, a thin wrapper around the C<XML::DOM> module which is written by 
Enno Derksen.

Because the DOM is mature standard, there are stable implementations of
it in many languages. For this reason it is very popular with programmers
who often switch between different languages. C<XML::DOM> parses the XML
document into a tree structure which you can then query using a large 
set of defined method calls.

To demonstrate the use of the C<XML.XPath> plugin, let's go back to the
TV show XML document that we created earlier in this chapter.
A<ch10-dom-html> shows a basic template that will transform that XML into 
an HTML page that describes a particular TV show.

=begin example Creating HTML from XML using Template::Plugin::XML::DOM

  Z<ch10-dom-html>[% USE date (format = '%d %b %Y') -%]
  [% USE dom = XML.DOM;
     show = dom.parse('show.xml');
     name = show.getElementsByTagName('name').0.getFirstChild.getNodeValue -%]
  <html>
    <head>
      <title>[% name | html %]</title>
    </head>
    <body>
      <ul>
      [% FOREACH season = show.getElementsByTagName('season') -%]
        [% number = season.getAttribute('number') %]
        <li><a href="#season[% number %]">Season [% number %]</a></li>
      [%- END %]
      </ul>

      <h1>[% name | html %]</h1>
      <p>Created by [% show.getElementsByTagName('creator').getFirstChild.getNodeValue | html %]</p>

      [% FOREACH season = show.getElementsByTagName('season') -%]
      [%- number = season.getAttribute('number') -%]
      <h2><a name="season[% number %]">Season [% number %]</a>
        ([% season.getAttribute('year') %])</h2>

      <h3>Regular Cast</h3>

      <ul>
      [% FOREACH part = season.getElementsByTagName('regular', 1) -%]
        <li><b>[% part.getElementsByTagName('actor').getFirstChild.getNodeValue | html %]</b> as
          <i>[% part.getElementsByTagName('character').getFirstChild.getNodeValue | html %]</i></li>
      [% END %]
      </ul>

      <h3>Episodes</h3>
      [%- FOREACH episode = season.getElementsByTagName('episode',1) %]
      <h4>[% episode.getAttribute('number') %] - 
        [% episode.getElementsByTagName('name').getFirstChild.getNodeValue | html %]</h4>

      <p><i>First broadcast 
        [% date.format(episode.getAttribute('date')) %]</i><br />
      [% episode.getElementsByTagName('summary',1).getFirstChild.getNodeValue | html %]</p>
      [%- END %]

      [% END %]
  </html>

=end

The first thing to notice is that we parse the XML document in two stages.

  [% USE dom = XML.DOM;
     show = dom.parse('show.xml') %]

In the first line we create a DOM parser object called C<dom> and on
the second line we use that object to parse our input file and create
a DOM tree which we store in the variable C<show>. We can then call 
various XML::DOM methods on this object to extract information about
the show. You'll notice that you will often need to string several
method calls together to get the information that you need. For example
to get the name of the show we use the expression

  name = show.getElementsByTagName('name').0.getFirstChild.getNodeValue

The method C<getElementsByTagName> returns a list of all of the elements
that are children of the C<show> element and have the name C<name>. We
then take the first node from that list (using the index C<0>) and get 
the first child of that node. This will be the text node that contains
the name of the show. We can then use C<getNodeValue> to get the value
(i.e. the text) of that node.

As always, when we display any text extracted from the XML document we
pass it through the C<html> filter to convert dangerous characters to
their HTML entity equivalents.

The output from this code is shown in A<ch10-dom-html-out>.

=begin example HTML created from XML using Template::Plugin::XML::DOM

  Z<ch10-dom-html-out><html>
    <head>
      <title>Buffy the Vampire Slayer</title>
    </head>
    <body>
      <ul>
          
        <li><a href="#season1">Season 1</a></li>
      </ul>

      <h1>Buffy the Vampire Slayer</h1>
      <p>Created by Joss Whedon</p>

          <h2><a name="season1">Season 1</a>
        (1997)</h2>

      <h3>Regular Cast</h3>

      <ul>
            <li><b>Sarah Michelle Geller</b> as
          <i>Buffy Summers</i></li>
            <li><b>Nicholas Brendon</b> as
          <i>Xander Harris</i></li>
    
      </ul>

      <h3>Episodes</h3>
      <h4>1 - 
        Welcome to the Hellmouth</h4>

       <p><i>First broadcast 
        10 Mar 1997</i><br />
      Buffy Summers moves to Sunnydale</p>
      <h4>2 - 
        The Harvest</h4>

       <p><i>First broadcast 
        17 Mar 1997</i><br />
      The Master plans to escape by harvesting people</p>

    
  </html>

=end

You can get more details on using the DOM from Template Toolkit by reading 
the module documentation for F<Template::Plugin::XML::DOM> (at
U<http://www.template-toolkit.org/docs/plain/Modules/Template/Plugin/XML/DOM.html>)
and F<XML::DOM> (at U<http://search.cpan.org/dist/XML-DOM/>). There
is more information about the DOM standard in T<XML in a Nutshell> by Elliotte Rusty Harold and W. Scott Means.

As you can see, using the DOM to extract data from an XML document can
get a little long-winded. Luckily there are other ways to handle XML
documents in Template Toolkit. In the next section we will look at another.


=head1 Processing XML documents with XML.XPath


=head2 Using XML::XPath to Munge XML

Another common standard for extracting data from XML documents is called 
M<XPath>. XPath is structured vaguely like a file system path:  consecutive
elements are joined with C</>, beginning at the root, and each element
in the path is nested below the previous.  The XPath statement:

  /html/head/title/text()

retrieves "Welcome to Foo.com" from the following XML:

  <html>
    <head>
      <title>Welcome to Foo.com</title>
    </head>
  </html>

Template Toolkit has support for XPath via the C<XML.XPath> plugin, which
wraps around Matt Sergeant's excellent C<XML::XPath> module, available
from CPAN (see U<http://search.cpan.org/dist/XML-XPath/>).  The C<XML.XPath> plugin is given
either the name of an XML document or a string containing XML..

A<ch10-xpath-html> shows a template which uses the XPath plugin to create 
an HTML page from our XML file containing information about I<Buffy the 
Vampire Slayer>. This is identical to the one we created in the previous
section using the DOM (see A<ch10-dom-html-out>)..

=begin example Creating HTML from XML using Template::Plugin::XML::XPath

  Z<ch10-xpath-html>[% USE date (format = '%d %b %Y') -%]
  [% USE show = XML.XPath('show.xml') -%]
  [% name = show.findvalue('/show/name/text()') -%]
  <html>
    <head>
      <title>[% name | html %]</title>
    </head>
    <body>
      <ul>
      [% FOREACH season = show.findnodes('/show/seasons/season') -%]
        [% number = season.findvalue('@number') %]
        <li><a href="#season[% number %]">Season [% number %]</a></li>
      [%- END %]
      </ul>

      <h1>[% name | html %]</h1>
      <p>Created by [% show.findvalue('show/creator/text()') | html %]</p>

      [% FOREACH season = show.findnodes('/show/seasons/season') -%]
      [%- number = season.findvalue('@number') -%]
      <h2><a name="season[% number %]">Season [% number %]</a>
        ([% season.findvalue('@year') %])</h2>

      <h3>Regular Cast</h3>

      <ul>
      [% FOREACH part = season.findnodes('cast/regular') -%]
        <li><b>[% part.findvalue('actor/text()') | html %]</b> as
          <i>[% part.findvalue('character/text()') | html %]</i></li>
      [% END %]
      </ul>

      <h3>Episodes</h3>
      [% FOREACH episode = season.findnodes('episodes/episode') -%]
      <h4>[% episode.findvalue('@number') %] - 
        [% episode.findvalue('name/text()') | html %]</h4>

      <p><i>First broadcast 
        [% date.format(episode.findvalue('@date')) %]</i><br />
      [% episode.findvalue('summary/text()') | html %]</p>
      [%- END %]

      [% END %]
    </div>
  </html>

We are basically using three methods from the C<XML.XPath> plugin. The line

  [% USE show = XML.XPath('show.xml') -%]

creates a new F<XML::XPath> object based on the file F<show.xml>. This
object is a tree structure which models the XML structure of the XML
document.  We can then use the methods C<findvalue> and C<findnodes>
to run XPath queries against this object. C<findvalue> takes an XPath
expression which will return a single value and returns the result of
evaluating that expression.  For example, we use

  [% name = show.findvalue('/show/name/text()') -%]

to get the name of the show from the current document. The XPath query
translates as "get the text for contained in the E<lt>nameE<gt> element
which is a child of the E<lt>showE<gt> element which is a child of the
root." Any kind of XPath expression can be used. For example we use
"@number" to get the number attribute of the current node (which just
happens to be an episode node at that point).

The C<findnode> method is used to loop over a list of nodes. For example
we use

  [% FOREACH season = show.findnodes('/show/seasons/season') %]

to get each E<lt>seasonE<gt> node that is contained in the document and

  [% FOREACH episode = season.findnodes('episodes.episode') %]

to get each episode in a season. Notice that as C<findnodes> returns
a list of nodes, we use a variable to store each node in return as we
work our way across the loop. These nodes are also C<XML::XPath> objects
and we can therefore run XPath queries against them in exactly the same
way as we can with the original C<show> object.

The current node that we are working from is called the M<context node>.
Continuing the file system analogy that we mentioned earlier, using a
context node is like changing your current directory. Any XPath query
that doesn't start with C</> is taken to be relative to your context
node in the same way as a directory path that doesn't start with C</> is
taken to be relative to your current directory. Any XPath quer that starts
with C</> is taken to be relative to the root node in the same way as a
directory path that starts with C</> is taken as realtive to the root
directory.

You can get more details on using XPath from Template Toolkit by reading 
the module documentation for F<Template::Plugin::XML::XPath> (at
U<http://www.template-toolkit.org/docs/plain/Modules/Template/Plugin/XML/PAth.html>)
and F<XML::XPath> (at U<http://search.cpan.org/dist/XML-XPath/>). There
is more information about the XPath standard in T<XML in a Nutshell> by Elliotte Rusty Harold and W. Scott Means.


=head1 Processing XML documents with XML.LibXML


All of the XML processors that we have seen up to now are based on the
Perl module F<XML::Parser> which is, in turn, based on James Clark's
F<expat> XML parser. However, F<expat>  doesn't have support for
newer XML features like namespaces and another parser has emerged as
the first choice for many XML processing tasks. It is called F<libxml2>
and you can find more details at U<http://www.libxml.org/>.

Perl has a module, F<XML::LibXML>, which gives access to the F<libxml2>
API and Mark Fowler has written F<Template::Plugin::XML::LibXML> which
allows it to be used from Template Toolkit. Both of these modules can be 
downloaded from the CPAN at U<http://search.cpan.org/dist/XML-LibXML/>
and U<http://search.cpan.org/Template-Plugin-XML-LibXML/> respectively.

F<libxml2> contains support for both DOM and XPath so both of the 
previous examples will work almost unchanged. You will just need to
alter the lines that load and parse the XML document.


=head1 Using Views to Transform XML Content



The XML processing methods that we have seen so far are very useful
for I<data-centric> XML documents. These are documents where the structure is
very well-defined. This type of file is commonly seem when the file
is modelling some kind of data structure. They of commonly used for 
transfering data between different systems, The TV show example was a 
good example of this as the relationships between the various data
items in the document was well understood and was unlikely to change.

There is another type of XML file. These are known as 
I<narrative-centric>. In these files the data is less well structured.
A good example of this kind of document is a book. Although a book will
have some high-level structure (table of contents, chapters, appendices
and index) once you get down to the text in a chapter, the structure
is much less defined. A paragraph can contain italic text, bold text,
references to footnotes, URLs and any number of other types of text
all of which will need to be processed differently.

Whilst it is possible to handle these kinds of documents using the
techniques we have seen previously, using the VIEW directive makes
it far easier to process narrative-centric XML.

A<ch10-faq-xml> shows a narrative-centric XML document.

=begin example A Narrative-Centric XML document

  Z<ch10-faq-xml><faq>
    <qna id="q1">
      <question>
        What is the ultimate answer to life, the universe and everything?
      </question>

      <answer author="Deep Thought">
        <para>42</para>
        <note>The problem may well be that you don't <i>actually</i>
          know what the question is!</note>
      </answer>
    </qna>

    <qna id="q2">
      <question>
        Where shall we have lunch?
      </question>

      <answer author="Milliways Marketing Dept">
        <para>Have you considered <froody>Milliways</froody>, the restaurant
        at the end of the universe.</para>

        <quote>If you've done six impossible things today then why
          not top it off with dinner at Milliways?</quote>
      </answer>
    </qna>
  </faq>

=end

Notice that while the higher levels of the document are well-structured,
once you get into the C<answer> tag then the text is unstructured. The
C<para>, C<note> and C<quote> tags are used interchangeably and there
are other tags used - you can see C<i> and C<froody>.

To process this file we will create a VIEW called 'faq_html' which will
convert the FAQ to HTML. For our first attempt we will create a "do
nothing" view that will simply pass the document through unchanged. This
view is shown in A<ch01-faq-view1>

=begin example A pass-thru view

  Z<ch01-faq-view1>[% VIEW faq_html notfound='passthru' %]

  [% BLOCK text; item; END %]

  [% BLOCK passthru -%]
  [% item.starttag; item.content(view); item.endtag -%]
  [%- END %]

  [% END %]

=end

The [% VIEW %] directive defines a block which can contain other named
blocks. In this VIEW we have defined two blocks. The first is called
C<text>. This is the default name for a block which will be called to
process text nodes from the document. Our text block is simple and
just displays the current item. Note that from within a VIEW template
the current node is available in the C<item> variable and the current
view is in the C<view> variable.

The other block we have defined is the block that is called if no
matching block is found for a node. This is defined using the 
C<notfound> parameter to the VIEW directive. Our passthru block
displays the start and end tags for the node and between them it
calls the current node's C<content> method passing it the current
view. The C<content> method finds all of the current node's child
nodes and displays them using the given view. This is an important
method. If you want child nodes to be processed then your template
must call it.

In order to use this template we need to have a parsed XML document.
VIEWs work well with any of the XML modules that we have seen before,
but support for the XPath plugin is the most advanced. We can create
and process an XML::XPath object with code like this:

  [% USE doc=XML.XPath(file => 'faq.xml');
     node = doc.findnodes('/faq');
     faq_html.print(node) %]

Calling the C<print> method on the VIEW and passing it the starting
node, starts the VIEW processing the document. Each type of node in the 
document is handled handled by the block with the same name. Any type of
node that doesn't match a block in the VIEW is handled by the C<notfound>
block.

Currently our template has no names blocks so all nodes are handled by the
C<notfound> block. We can add blocks that handle any nodes that need
more than this default processing. A<ch10-faq-view2> fills in
processing for a number of tags.

=begin example A more complex view

  Z<ch10-faq-view2>[% VIEW faq_html notfound='xmlstring' %]

  [% BLOCK faq %]<h1>Frequently Asked Questions</h1>
  [%- item.content(view); END %]
  [% BLOCK question %]<h2>[% item.content(view) %]</h2>[% END %]

  [% BLOCK answer %]
  [% item.content(view) %]
  <p>Answer by [% item.getAttribute('author') %]</p>
  [% END %]

  [% BLOCK para %]<p>[% item.content(view) %]</p>[% END %]

  [% BLOCK note -%]
  <p>Note: [% item.content(view) %]</p>
  [%- END %]

  [% BLOCK quote -%]
  <blockquote><i>[% item.content(view) %]</i></blockquote>
  [%- END %]

  [% BLOCK qna; item.content(view); END %]

  [% BLOCK text; item; END %]

  [% BLOCK xmlstring -%]
  [% item.starttag; item.content(view); item.endtag -%]
  [%- END %]

  [% END %]

  [% USE doc=XML.XPath(file => 'faq.xml');
     node=doc.findnodes('/faq');
     faq_html.print(node) %]

=end

A couple of points to note. Firstly we have created a block for the
C<qna> node which does nothing but process its children. This is because
if we left it to the default block, then the opening and closing C<qna>
tags would be displayed, and we don't want that. Secondly, we haven't 
defined a block for the C<i> tag. This is because we are happy for
it to pass through unchanged so it becomes part of the HTML page that
is created.

Our input document also contains a C<froody> tag, currently this tag
is passed through untouched (and presumeably ignored by the browser that
displays the finished page.) But when the management of Milliway's
complain that their text should be displayed in a certain manner, it
will be simple for us to add a block that handles it. For example:
  
  [% BLOCK froody -%]
  <font size="20" color="red"><i>[% item.content(view) %]</i></font>
  [%- END %]

It is this extensibility that makes C<VIEW>s a perfect tool for 
processing narrative-centric XML documents. It is very simple to add
processing for news tags and it doesn't matter whereabouts in the
document structure that they appear.


=cut
