[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Debian JP master SVN www commits (rev.242)
=======================================================
Repository: /org/svn.debian.or.jp/repos
Revision: 242
Commiter: kmuto
Date: 2007-04-01 20:07:38 +0900 (日, 01 4月 2007)
=======================================================
Log:
commit XML plugin for sid users.
=======================================================
Changed:
A www/trunk/XML/
A www/trunk/XML/DOM.pm
A www/trunk/XML/README
A www/trunk/XML/RSS.pm
A www/trunk/XML/Simple.pm
A www/trunk/XML/Style.pm
A www/trunk/XML/XPath.pm
Added: www/trunk/XML/DOM.pm
===================================================================
--- www/trunk/XML/DOM.pm (rev 0)
+++ www/trunk/XML/DOM.pm 2007-04-01 11:07:38 UTC (rev 242)
@@ -0,0 +1,841 @@
+#============================================================= -*-Perl-*-
+#
+# Template::Plugin::XML::DOM
+#
+# DESCRIPTION
+#
+# Simple Template Toolkit plugin interfacing to the XML::DOM.pm module.
+#
+# AUTHORS
+# Andy Wardley <abw@xxxxxxx>
+# Simon Matthews <sam@xxxxxxxxxxxxxxxxx>
+#
+# COPYRIGHT
+# Copyright (C) 2000 Andy Wardley, Simon Matthews. All Rights Reserved.
+#
+# This module is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+#
+#----------------------------------------------------------------------------
+#
+# $Id: DOM.pm,v 2.55 2004/01/30 19:33:34 abw Exp $
+#
+#============================================================================
+
+package Template::Plugin::XML::DOM;
+
+require 5.004;
+
+use strict;
+use Template::Plugin;
+use XML::DOM;
+
+use base qw( Template::Plugin );
+use vars qw( $VERSION $DEBUG );
+
+$VERSION = 2.6;
+$DEBUG = 0 unless defined $DEBUG;
+
+
+#------------------------------------------------------------------------
+# new($context, \%config)
+#
+# Constructor method for XML::DOM plugin. Creates an XML::DOM::Parser
+# object and initialise plugin configuration.
+#------------------------------------------------------------------------
+
+sub new {
+ my $class = shift;
+ my $context = shift;
+ my $args = ref $_[-1] eq 'HASH' ? pop(@_) : { };
+
+ my $parser ||= XML::DOM::Parser->new(%$args)
+ || return $class->_throw("failed to create XML::DOM::Parser\n");
+
+ # we've had to deprecate the old usage because it broke things big time
+ # with DOM trees never getting cleaned up.
+ return $class->_throw("XML::DOM usage has changed - you must now call parse()\n")
+ if @_;
+
+ bless {
+ _PARSER => $parser,
+ _DOCS => [ ],
+ _CONTEXT => $context,
+ _PREFIX => $args->{ prefix } || '',
+ _SUFFIX => $args->{ suffix } || '',
+ _DEFAULT => $args->{ default } || '',
+ _VERBOSE => $args->{ verbose } || 0,
+ _NOSPACE => $args->{ nospace } || 0,
+ _DEEP => $args->{ deep } || 0,
+ }, $class;
+}
+
+
+#------------------------------------------------------------------------
+# parse($content, \%named_params)
+#
+# Parses an XML stream, provided as the first positional argument (assumed
+# to be a filename unless it contains a '<' character) or specified in
+# the named parameter hash as one of 'text', 'xml' (same as text), 'file'
+# or 'filename'.
+#------------------------------------------------------------------------
+
+sub parse {
+ my $self = shift;
+ my $args = ref $_[-1] eq 'HASH' ? pop(@_) : { };
+ my $parser = $self->{ _PARSER };
+ my ($content, $about, $method, $doc);
+
+ # determine the input source from a positional parameter (may be a
+ # filename or XML text if it contains a '<' character) or by using
+ # named parameters which may specify one of 'file', 'filename', 'text'
+ # or 'xml'
+
+ if ($content = shift) {
+ if ($content =~ /\</) {
+ $about = 'xml text';
+ $method = 'parse';
+ }
+ else {
+ $about = "xml file $content";
+ $method = 'parsefile';
+ }
+ }
+ elsif ($content = $args->{ text } || $args->{ xml }) {
+ $about = 'xml text';
+ $method = 'parse';
+ }
+ elsif ($content = $args->{ file } || $args->{ filename }) {
+ $about = "xml file $content";
+ $method = 'parsefile';
+ }
+ else {
+ return $self->_throw('no filename or xml text specified');
+ }
+
+ # parse the input source using the appropriate method determined above
+ eval { $doc = $parser->$method($content) } and not $@
+ or return $self->_throw("failed to parse $about: $@");
+
+ # update XML::DOM::Document _UserData to contain config details
+ $doc->[ XML::DOM::Node::_UserData ] = {
+ map { ( $_ => $self->{ $_ } ) }
+ qw( _CONTEXT _PREFIX _SUFFIX _VERBOSE _NOSPACE _DEEP _DEFAULT ),
+ };
+
+ # keep track of all DOM docs for subsequent dispose()
+# print STDERR "DEBUG: $self adding doc: $doc\n"
+# if $DEBUG;
+
+ push(@{ $self->{ _DOCS } }, $doc);
+
+ return $doc;
+}
+
+
+#------------------------------------------------------------------------
+# _throw($errmsg)
+#
+# Raised a Template::Exception of type XML.DOM via die().
+#------------------------------------------------------------------------
+
+sub _throw {
+ my ($self, $error) = @_;
+ die (Template::Exception->new('XML.DOM', $error));
+}
+
+
+#------------------------------------------------------------------------
+# DESTROY
+#
+# Cleanup method which calls dispose() on any and all DOM documents
+# created by this object. Also breaks any circular references that
+# may exist with the context object.
+#------------------------------------------------------------------------
+
+sub DESTROY {
+ my $self = shift;
+
+ # call dispose() on each document produced by this parser
+ foreach my $doc (@{ $self->{ _DOCS } }) {
+# print STDERR "DEBUG: $self destroying $doc\n"
+# if $DEBUG;
+ if (ref $doc) {
+# print STDERR "disposing of $doc\n";
+ undef $doc->[ XML::DOM::Node::_UserData ]->{ _CONTEXT };
+ $doc->dispose();
+ }
+ }
+ delete $self->{ _CONTEXT };
+ delete $self->{ _PARSER };
+}
+
+
+
+#========================================================================
+package XML::DOM::Node;
+#========================================================================
+
+
+#------------------------------------------------------------------------
+# present($view)
+#
+# Method to present node via a view (supercedes all that messy toTemplate
+# stuff below).
+#------------------------------------------------------------------------
+
+sub present {
+ my ($self, $view) = @_;
+
+ if ($self->getNodeType() == XML::DOM::ELEMENT_NODE) {
+ # it's an element
+ $view->view($self->getTagName(), $self);
+ }
+ else {
+ my $text = $self->toString();
+ $view->view('text', $text);
+ }
+}
+
+sub content {
+ my ($self, $view) = @_;
+ my $output = '';
+ foreach my $node (@{ $self->getChildNodes }) {
+ $output .= $node->present($view);
+
+# abw test passing args, Aug 2001
+# $output .= $view->print($node);
+ }
+ return $output;
+}
+
+
+#------------------------------------------------------------------------
+# toTemplate($prefix, $suffix, \%named_params)
+#
+# Process the current node as a template.
+#------------------------------------------------------------------------
+
+sub toTemplate {
+ my $self = shift;
+ _template_node($self, $self->_args(@_));
+}
+
+
+#------------------------------------------------------------------------
+# childrenToTemplate($prefix, $suffix, \%named_params)
+#
+# Process all the current node's children as templates.
+#------------------------------------------------------------------------
+
+sub childrenToTemplate {
+ my $self = shift;
+ _template_kids($self, $self->_args(@_));
+}
+
+
+#------------------------------------------------------------------------
+# allChildrenToTemplate($prefix, $suffix, \%named_params)
+#
+# Process all the current node's children, and their children, and
+# their children, etc., etc., as templates. Same effect as calling the
+# childrenToTemplate() method with the 'deep' option set.
+#------------------------------------------------------------------------
+
+sub allChildrenToTemplate {
+ my $self = shift;
+ my $args = $self->_args(@_);
+ $args->{ deep } = 1;
+ _template_kids($self, $args);
+}
+
+
+#------------------------------------------------------------------------
+# _args($prefix, $suffix, \%name_params)
+#
+# Reads the optional positional parameters, $prefix and $suffix, and
+# also examines any named parameters hash to construct a set of
+# current configuration parameters. Where not specified directly, the
+# object defaults are used.
+#------------------------------------------------------------------------
+
+sub _args {
+ my $self = shift;
+ my $args = ref $_[-1] eq 'HASH' ? pop(@_) : { };
+ my $doc = $self->getOwnerDocument() || $self;
+ my $data = $doc->[ XML::DOM::Node::_UserData ];
+
+ return {
+ prefix => @_ ? shift : $args->{ prefix } || $data->{ _PREFIX },
+ suffix => @_ ? shift : $args->{ suffix } || $data->{ _SUFFIX },
+ verbose => $args->{ verbose } || $data->{ _VERBOSE },
+ nospace => $args->{ nospace } || $data->{ _NOSPACE },
+ deep => $args->{ deep } || $data->{ _DEEP },
+ default => $args->{ default } || $data->{ _DEFAULT },
+ context => $data->{ _CONTEXT },
+ };
+}
+
+
+
+#------------------------------------------------------------------------
+# _template_node($node, $args, $vars)
+#
+# Process a template for the current DOM node where the template name
+# is taken from the node TagName, with any specified 'prefix' and/or
+# 'suffix' applied. The 'default' argument can also be provided to
+# specify a default template to be used when a specific template can't
+# be found. The $args parameter referenced a hash array through which
+# these configuration items are passed (see _args()). The current DOM
+# node is made available to the template as the variable 'node', along
+# with any other variables passed in the optional $vars hash reference.
+# To permit the 'children' and 'prune' callbacks to be raised as node
+# methods (see _template_kids() below), these items, if defined in the
+# $vars hash, are copied into the node object where its AUTOLOAD method
+# can find them.
+#------------------------------------------------------------------------
+
+sub _template_node {
+ my $node = shift || die "no XML::DOM::Node reference\n";
+ my $args = shift || die "no XML::DOM args passed to _template_node\n";
+ my $vars = shift || { };
+ my $context = $args->{ context } || die "no context in XML::DOM args\n";
+ my $template;
+ my $output = '';
+
+ # if this is not an element then it is text so output it
+ unless ($node->getNodeType() == XML::DOM::ELEMENT_NODE ) {
+ if ($args->{ verbose }) {
+ $output = $node->toString();
+ $output =~ s/\s+$// if $args->{ nospace };
+ }
+ }
+ else {
+ my $element = ( $args->{ prefix } || '' )
+ . $node->getTagName()
+ . ( $args->{ suffix } || '' );
+
+ # locate a template by name built from prefix, tagname and suffix
+ # or fall back on any default template specified
+ eval { $template = $context->template($element) };
+ eval { $template = $context->template($args->{ default }) }
+ if $@ && $args->{ default };
+ $template = $element unless $template;
+
+ # copy 'children' and 'prune' callbacks into node object (see AUTOLOAD)
+ my $doc = $node->getOwnerDocument() || $node;
+ my $data = $doc->[ XML::DOM::Node::_UserData ];
+
+ $data->{ _TT_CHILDREN } = $vars->{ children };
+ $data->{ _TT_PRUNE } = $vars->{ prune };
+
+ # add node reference to existing vars hash
+ $vars->{ node } = $node;
+
+ $output = $context->include($template, $vars);
+
+ # break any circular references
+ delete $vars->{ node };
+ delete $data->{ _TT_CHILDREN };
+ delete $data->{ _TT_PRUNE };
+ }
+
+ return $output;
+}
+
+
+#------------------------------------------------------------------------
+# _template_kids($node, $args)
+#
+# Process all the children of the current node as templates, via calls
+# to _template_node(). If the 'deep' argument is set, then the process
+# will continue recursively. In this case, the node template is first
+# processed, followed by any children of that node (i.e. depth first,
+# parent before). A closure called 'children' is created and added
+# to the Stash variables passed to _template_node(). This can be called
+# from the parent template to process all child nodes at the current point.
+# This then "prunes" the tree preventing the children from being processed
+# after the parent template. A 'prune' callback is also added to prune
+# the tree without processing the children. Note that _template_node()
+# copies these callbacks into each parent node, allowing them to be called
+# as [% node.
+#------------------------------------------------------------------------
+
+sub _template_kids {
+ my $node = shift || die "no XML::DOM::Node reference\n";
+ my $args = shift || die "no XML::DOM args passed to _template_kids\n";
+ my $context = $args->{ context } || die "no context in XML::DOM args\n";
+ my $output = '';
+
+ foreach my $kid ( $node->getChildNodes() ) {
+ # define some callbacks to allow template to call [% content %]
+ # or [% prune %]. They are also inserted into each node reference
+ # so they can be called as [% node.content %] and [% node.prune %]
+ my $prune = 0;
+ my $vars = { };
+ $vars->{ children } = sub {
+ $prune = 1;
+ _template_kids($kid, $args);
+ };
+ $vars->{ prune } = sub {
+ $prune = 1;
+ return '';
+ };
+
+ $output .= _template_node($kid, $args, $vars);
+ $output .= _template_kids($kid, $args)
+ if $args->{ deep } && ! $prune;
+ }
+ return $output;
+}
+
+
+#========================================================================
+package XML::DOM::Element;
+#========================================================================
+
+use vars qw( $AUTOLOAD );
+
+sub AUTOLOAD {
+ my $self = shift;
+ my $method = $AUTOLOAD;
+ my $attrib;
+
+ $method =~ s/.*:://;
+ return if $method eq 'DESTROY';
+
+ my $doc = $self->getOwnerDocument() || $self;
+ my $data = $doc->[ XML::DOM::Node::_UserData ];
+
+ # call 'content' or 'prune' callbacks, if defined (see _template_node())
+ return &$attrib()
+ if ($method =~ /^children|prune$/)
+ && defined($attrib = $data->{ "_TT_\U$method" })
+ && ref $attrib eq 'CODE';
+
+ return $attrib
+ if defined ($attrib = $self->getAttribute($method));
+
+ return '';
+}
+
+
+1;
+
+__END__
+
+
+#------------------------------------------------------------------------
+# IMPORTANT NOTE
+# This documentation is generated automatically from source
+# templates. Any changes you make here may be lost.
+#
+# The 'docsrc' documentation source bundle is available for download
+# from http://www.template-toolkit.org/docs.html and contains all
+# the source templates, XML files, scripts, etc., from which the
+# documentation for the Template Toolkit is built.
+#------------------------------------------------------------------------
+
+=head1 NAME
+
+Template::Plugin::XML::DOM - Plugin interface to XML::DOM
+
+=head1 SYNOPSIS
+
+ # load plugin
+ [% USE dom = XML.DOM %]
+
+ # also provide XML::Parser options
+ [% USE dom = XML.DOM(ProtocolEncoding =E<gt> 'ISO-8859-1') %]
+
+ # parse an XML file
+ [% doc = dom.parse(filename) %]
+ [% doc = dom.parse(file => filename) %]
+
+ # parse XML text
+ [% doc = dom.parse(xmltext) %]
+ [% doc = dom.parse(text => xmltext) %]
+
+ # call any XML::DOM methods on document/element nodes
+ [% FOREACH node = doc.getElementsByTagName('report') %]
+ * [% node.getAttribute('title') %] # or just '[% node.title %]'
+ [% END %]
+
+ # define VIEW to present node(s)
+ [% VIEW report notfound='xmlstring' %]
+ # handler block for a <report>...</report> element
+ [% BLOCK report %]
+ [% item.content(view) %]
+ [% END %]
+
+ # handler block for a <section title="...">...</section> element
+ [% BLOCK section %]
+ <h1>[% item.title %]</h1>
+ [% item.content(view) %]
+ [% END %]
+
+ # default template block converts item to string representation
+ [% BLOCK xmlstring; item.toString; END %]
+
+ # block to generate simple text
+ [% BLOCK text; item; END %]
+ [% END %]
+
+ # now present node (and children) via view
+ [% report.print(node) %]
+
+ # or print node content via view
+ [% node.content(report) %]
+
+ # following methods are soon to be deprecated in favour of views
+ [% node.toTemplate %]
+ [% node.childrenToTemplate %]
+ [% node.allChildrenToTemplate %]
+
+=head1 PRE-REQUISITES
+
+This plugin requires that the XML::Parser (2.19 or later) and XML::DOM
+(1.27 or later) modules be installed. These are available from CPAN:
+
+ http://www.cpan.org/modules/by-module/XML
+
+Note that the XML::DOM module is now distributed as part of the
+'libxml-enno' bundle.
+
+=head1 DESCRIPTION
+
+This is a Template Toolkit plugin interfacing to the XML::DOM module.
+The plugin loads the XML::DOM module and creates an XML::DOM::Parser
+object which is stored internally. The parse() method can then be
+called on the plugin to parse an XML stream into a DOM document.
+
+ [% USE dom = XML.DOM %]
+ [% doc = dom.parse('/tmp/myxmlfile') %]
+
+NOTE: earlier versions of this XML::DOM plugin expected a filename to
+be passed as an argument to the constructor. This is no longer
+supported due to the fact that it caused a serious memory leak. We
+apologise for the inconvenience but must insist that you change your
+templates as shown:
+
+ # OLD STYLE: now fails with a warning
+ [% USE dom = XML.DOM('tmp/myxmlfile') %]
+
+ # NEW STYLE: do this instead
+ [% USE dom = XML.DOM %]
+ [% doc = dom.parse('tmp/myxmlfile') %]
+
+The root of the problem lies in XML::DOM creating massive circular
+references in the object models it constructs. The dispose() method
+must be called on each document to release the memory that it would
+otherwise hold indefinately. The XML::DOM plugin object (i.e. 'dom'
+in these examples) acts as a sentinel for the documents it creates
+('doc' and any others). When the plugin object goes out of scope at
+the end of the current template, it will automatically call dispose()
+on any documents that it has created. Note that if you dispose of the
+the plugin object before the end of the block (i.e. by assigning a
+new value to the 'dom' variable) then the documents will also be
+disposed at that point and should not be used thereafter.
+
+ [% USE dom = XML.DOM %]
+ [% doc = dom.parse('/tmp/myfile') %]
+ [% dom = 'new value' %] # releases XML.DOM plugin and calls
+ # dispose() on 'doc', so don't use it!
+
+Any template processing parameters (see toTemplate() method and
+friends, below) can be specified with the constructor and will be used
+to define defaults for the object.
+
+ [% USE dom = XML.DOM(prefix => 'theme1/') %]
+
+The plugin constructor will also accept configuration options destined
+for the XML::Parser object:
+
+ [% USE dom = XML.DOM(ProtocolEncoding => 'ISO-8859-1') %]
+
+=head1 METHODS
+
+=head2 parse()
+
+The parse() method accepts a positional parameter which contains a filename
+or XML string. It is assumed to be a filename unless it contains a E<lt>
+character.
+
+ [% xmlfile = '/tmp/foo.xml' %]
+ [% doc = dom.parse(xmlfile) %]
+
+ [% xmltext = BLOCK %]
+ <xml>
+ <blah><etc/></blah>
+ ...
+ </xml>
+ [% END %]
+ [% doc = dom.parse(xmltext) %]
+
+The named parameters 'file' (or 'filename') and 'text' (or 'xml') can also
+be used:
+
+ [% doc = dom.parse(file = xmlfile) %]
+ [% doc = dom.parse(text = xmltext) %]
+
+The parse() method returns an instance of the XML::DOM::Document object
+representing the parsed document in DOM form. You can then call any
+XML::DOM methods on the document node and other nodes that its methods
+may return. See L<XML::DOM> for full details.
+
+ [% FOREACH node = doc.getElementsByTagName('CODEBASE') %]
+ * [% node.getAttribute('href') %]
+ [% END %]
+
+This plugin also provides an AUTOLOAD method for XML::DOM::Node which
+calls getAttribute() for any undefined methods. Thus, you can use the
+short form of
+
+ [% node.attrib %]
+
+in place of
+
+ [% node.getAttribute('attrib') %]
+
+=head2 toTemplate()
+
+B<NOTE: This method will soon be deprecated in favour of the VIEW based
+approach desribed below.>
+
+This method will process a template for the current node on which it is
+called. The template name is constructed from the node TagName with any
+optional 'prefix' and/or 'suffix' options applied. A 'default' template
+can be named to be used when the specific template cannot be found. The
+node object is available to the template as the 'node' variable.
+
+Thus, for this XML fragment:
+
+ <page title="Hello World!">
+ ...
+ </page>
+
+and this template definition:
+
+ [% BLOCK page %]
+ Page: [% node.title %]
+ [% END %]
+
+the output of calling toTemplate() on the E<lt>pageE<gt> node would be:
+
+ Page: Hello World!
+
+=head2 childrenToTemplate()
+
+B<NOTE: This method will soon be deprecated in favour of the VIEW based
+approach desribed below.>
+
+Effectively calls toTemplate() for the current node and then for each of
+the node's children. By default, the parent template is processed first,
+followed by each of the children. The 'children' closure can be called
+from within the parent template to have them processed and output
+at that point. This then suppresses the children from being processed
+after the parent template.
+
+Thus, for this XML fragment:
+
+ <foo>
+ <bar id="1"/>
+ <bar id="2"/>
+ </foo>
+
+and these template definitions:
+
+ [% BLOCK foo %]
+ start of foo
+ end of foo
+ [% END %]
+
+ [% BLOCK bar %]
+ bar [% node.id %]
+ [% END %]
+
+the output of calling childrenToTemplate() on the parent E<lt>fooE<gt> node
+would be:
+
+ start of foo
+ end of foo
+ bar 1
+ bar 2
+
+Adding a call to [% children %] in the 'foo' template:
+
+ [% BLOCK foo %]
+ start of foo
+ [% children %]
+ end of foo
+ [% END %]
+
+then creates output as:
+
+ start of foo
+ bar 1
+ bar 2
+ end of foo
+
+The 'children' closure can also be called as a method of the node, if you
+prefer:
+
+ [% BLOCK foo %]
+ start of foo
+ [% node.children %]
+ end of foo
+ [% END %]
+
+The 'prune' closure is also defined and can be called as [% prune %] or
+[% node.prune %]. It prunes the currrent node, preventing any descendants
+from being further processed.
+
+ [% BLOCK anynode %]
+ [% node.toString; node.prune %]
+ [% END %]
+
+=head2 allChildrenToTemplate()
+
+B<NOTE: This method will soon be deprecated in favour of the VIEW based
+approach desribed below.>
+
+Similar to childrenToTemplate() but processing all descendants (i.e. children
+of children and so on) recursively. This is identical to calling the
+childrenToTemplate() method with the 'deep' flag set to any true value.
+
+=head1 PRESENTING DOM NODES USING VIEWS
+
+You can define a VIEW to present all or part of a DOM tree by automatically
+mapping elements onto templates. Consider a source document like the
+following:
+
+ <report>
+ <section title="Introduction">
+ <p>
+ Blah blah.
+ <ul>
+ <li>Item 1</li>
+ <li>item 2</li>
+ </ul>
+ </p>
+ </section>
+ <section title="The Gory Details">
+ ...
+ </section>
+ </report>
+
+We can load it up via the XML::DOM plugin and fetch the node for the
+E<lt>reportE<gt> element.
+
+ [% USE dom = XML.DOM;
+ doc = dom.parse(file => filename);
+ report = doc.getElementsByTagName('report')
+ %]
+
+We can then define a VIEW as follows to present this document fragment in
+a particular way. The L<Template::Manual::Views> documentation
+contains further details on the VIEW directive and various configuration
+options it supports.
+
+ [% VIEW report_view notfound='xmlstring' %]
+ # handler block for a <report>...</report> element
+ [% BLOCK report %]
+ [% item.content(view) %]
+ [% END %]
+
+ # handler block for a <section title="...">...</section> element
+ [% BLOCK section %]
+ <h1>[% item.title %]</h1>
+ [% item.content(view) %]
+ [% END %]
+
+ # default template block converts item to string representation
+ [% BLOCK xmlstring; item.toString; END %]
+
+ # block to generate simple text
+ [% BLOCK text; item; END %]
+ [% END %]
+
+Each BLOCK defined within the VIEW represents a presentation style for
+a particular element or elements. The current node is available via the
+'item' variable. Elements that contain other content can generate it
+according to the current view by calling [% item.content(view) %].
+Elements that don't have a specific template defined are mapped to the
+'xmlstring' template via the 'notfound' parameter specified in the VIEW
+header. This replicates the node as an XML string, effectively allowing
+general XML/XHTML markup to be passed through unmodified.
+
+To present the report node via the view, we simply call:
+
+ [% report_view.print(report) %]
+
+The output from the above example would look something like this:
+
+ <h1>Introduction</h1>
+ <p>
+ Blah blah.
+ <ul>
+ <li>Item 1</li>
+ <li>item 2</li>
+ </ul>
+ </p>
+
+ <h1>The Gory Details</h1>
+ ...
+
+To print just the content of the report node (i.e. don't process the
+'report' template for the report node), you can call:
+
+ [% report.content(report_view) %]
+
+=head1 AUTHORS
+
+This plugin module was written by Andy Wardley E<lt>abw@xxxxxxxxxxxx<gt>
+and Simon Matthews E<lt>sam@xxxxxxxxxxxxxxxxxx<gt>.
+
+The XML::DOM module is by Enno Derksen E<lt>enno@xxxxxxxx<gt> and Clark
+Cooper E<lt>coopercl@xxxxxxxxxxx<gt>. It extends the the XML::Parser
+module, also by Clark Cooper which itself is built on James Clark's expat
+library.
+
+=head1 VERSION
+
+2.6, distributed as part of the
+Template Toolkit version 2.14, released on 04 October 2004.
+
+
+
+=head1 HISTORY
+
+Version 2.5 : updated for use with version 1.27 of the XML::DOM module.
+
+=over 4
+
+=item *
+
+XML::DOM 1.27 now uses array references as the underlying data type
+for DOM nodes instead of hash array references. User data is now
+bound to the _UserData node entry instead of being forced directly
+into the node hash.
+
+=back
+
+=head1 BUGS
+
+The childrenToTemplate() and allChildrenToTemplate() methods can easily
+slip into deep recursion.
+
+The 'verbose' and 'nospace' options are not documented. They may
+change in the near future.
+
+=head1 COPYRIGHT
+
+Copyright (C) 2000-2001 Andy Wardley, Simon Matthews. All Rights Reserved.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<Template::Plugin|Template::Plugin>, L<XML::DOM|XML::DOM>, L<XML::Parser|XML::Parser>
+
Added: www/trunk/XML/README
===================================================================
--- www/trunk/XML/README (rev 0)
+++ www/trunk/XML/README 2007-04-01 11:07:38 UTC (rev 242)
@@ -0,0 +1,5 @@
+Unfortunately libtemplate-perl has removed XML plugin since 2.15.
+Here is backported files from 2.14 (and tweaked a bit) for keeping
+a compatibility.
+Please copy these files to your /usr/lib/perl5/Template/Plugin/XML/
+directory until the upstream author revives XML plugin.
Added: www/trunk/XML/RSS.pm
===================================================================
--- www/trunk/XML/RSS.pm (rev 0)
+++ www/trunk/XML/RSS.pm 2007-04-01 11:07:38 UTC (rev 242)
@@ -0,0 +1,194 @@
+#============================================================= -*-Perl-*-
+#
+# Template::Plugin::XML::RSS
+#
+# DESCRIPTION
+#
+# Template Toolkit plugin which interfaces to Jonathan Eisenzopf's XML::RSS
+# module. RSS is the Rich Site Summary format.
+#
+# AUTHOR
+# Andy Wardley <abw@xxxxxxx>
+#
+# COPYRIGHT
+# Copyright (C) 2000 Andy Wardley. All Rights Reserved.
+#
+# This module is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+#
+#----------------------------------------------------------------------------
+#
+# $Id: RSS.pm,v 2.65 2004/01/30 19:33:36 abw Exp $
+#
+#============================================================================
+
+package Template::Plugin::XML::RSS;
+
+require 5.004;
+
+use strict;
+use vars qw( $VERSION );
+use base qw( Template::Plugin );
+use Template::Plugin;
+use XML::RSS;
+
+$VERSION = sprintf("%d.%02d", q$Revision: 2.65 $ =~ /(\d+)\.(\d+)/);
+
+sub load {
+ return $_[0];
+}
+
+sub new {
+ my ($class, $context, $filename) = @_;
+
+ return $class->fail('No filename specified')
+ unless $filename;
+
+ my $rss = XML::RSS->new
+ or return $class->fail('failed to create XML::RSS');
+
+ # Attempt to determine if $filename is an XML string or
+ # a filename. Based on code from the XML.XPath plugin.
+ eval {
+ if ($filename =~ /\</) {
+ $rss->parse($filename);
+ }
+ else {
+ $rss->parsefile($filename)
+ }
+ } and not $@
+ or return $class->error("failed to parse $filename: $@");
+
+ return $rss;
+}
+
+1;
+
+__END__
+
+
+#------------------------------------------------------------------------
+# IMPORTANT NOTE
+# This documentation is generated automatically from source
+# templates. Any changes you make here may be lost.
+#
+# The 'docsrc' documentation source bundle is available for download
+# from http://www.template-toolkit.org/docs.html and contains all
+# the source templates, XML files, scripts, etc., from which the
+# documentation for the Template Toolkit is built.
+#------------------------------------------------------------------------
+
+=head1 NAME
+
+Template::Plugin::XML::RSS - Plugin interface to XML::RSS
+
+=head1 SYNOPSIS
+
+ [% USE news = XML.RSS($filename) %]
+
+ [% FOREACH item = news.items %]
+ [% item.title %]
+ [% item.link %]
+ [% END %]
+
+=head1 PRE-REQUISITES
+
+This plugin requires that the XML::Parser and XML::RSS modules be
+installed. These are available from CPAN:
+
+ http://www.cpan.org/modules/by-module/XML
+
+=head1 DESCRIPTION
+
+This Template Toolkit plugin provides a simple interface to the
+XML::RSS module.
+
+ [% USE news = XML.RSS('mysite.rdf') %]
+
+It creates an XML::RSS object, which is then used to parse the RSS
+file specified as a parameter in the USE directive. A reference to
+the XML::RSS object is then returned.
+
+An RSS (Rich Site Summary) file is typically used to store short news
+'headlines' describing different links within a site. This example is
+extracted from http://slashdot.org/slashdot.rdf.
+
+ <?xml version="1.0"?><rdf:RDF
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://my.netscape.com/rdf/simple/0.9/">
+
+ <channel>
+ <title>Slashdot:News for Nerds. Stuff that Matters.</title>
+ <link>http://slashdot.org</link>
+ <description>News for Nerds. Stuff that Matters</description>
+ </channel>
+
+ <image>
+ <title>Slashdot</title>
+ <url>http://slashdot.org/images/slashdotlg.gif</url>
+ <link>http://slashdot.org</link>
+ </image>
+
+ <item>
+ <title>DVD CCA Battle Continues Next Week</title>
+ <link>http://slashdot.org/article.pl?sid=00/01/12/2051208</link>
+ </item>
+
+ <item>
+ <title>Matrox to fund DRI Development</title>
+ <link>http://slashdot.org/article.pl?sid=00/01/13/0718219</link>
+ </item>
+
+ <item>
+ <title>Mike Shaver Leaving Netscape</title>
+ <link>http://slashdot.org/article.pl?sid=00/01/13/0711258</link>
+ </item>
+
+ </rdf:RDF>
+
+The attributes of the channel and image elements can be retrieved directly
+from the plugin object using the familiar dotted compound notation:
+
+ [% news.channel.title %]
+ [% news.channel.link %]
+ [% news.channel.etc... %]
+
+ [% news.image.title %]
+ [% news.image.url %]
+ [% news.image.link %]
+ [% news.image.etc... %]
+
+The list of news items can be retrieved using the 'items' method:
+
+ [% FOREACH item = news.items %]
+ [% item.title %]
+ [% item.link %]
+ [% END %]
+
+=head1 AUTHORS
+
+This plugin was written by Andy Wardley E<lt>abw@xxxxxxxxxxxx<gt>,
+inspired by an article in Web Techniques by Randal Schwartz
+E<lt>merlyn@xxxxxxxxxxxxxxx<gt>.
+
+The XML::RSS module, which implements all of the functionality that
+this plugin delegates to, was written by Jonathan Eisenzopf
+E<lt>eisen@xxxxxxxxxx<gt>.
+
+=head1 VERSION
+
+2.65, distributed as part of the
+Template Toolkit version 2.14, released on 04 October 2004.
+
+=head1 COPYRIGHT
+
+ Copyright (C) 1996-2004 Andy Wardley. All Rights Reserved.
+ Copyright (C) 1998-2002 Canon Research Centre Europe Ltd.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<Template::Plugin|Template::Plugin>, L<XML::RSS|XML::RSS>, L<XML::Parser|XML::Parser>
+
Added: www/trunk/XML/Simple.pm
===================================================================
--- www/trunk/XML/Simple.pm (rev 0)
+++ www/trunk/XML/Simple.pm 2007-04-01 11:07:38 UTC (rev 242)
@@ -0,0 +1,142 @@
+#============================================================= -*-Perl-*-
+#
+# Template::Plugin::XML::Simple
+#
+# DESCRIPTION
+# Template Toolkit plugin interfacing to the XML::Simple.pm module.
+#
+# AUTHOR
+# Andy Wardley <abw@xxxxxxx>
+#
+# COPYRIGHT
+# Copyright (C) 2001 Andy Wardley. All Rights Reserved.
+#
+# This module is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+#
+#----------------------------------------------------------------------------
+#
+# $Id: Simple.pm,v 2.65 2004/09/24 06:49:13 abw Exp $
+#
+#============================================================================
+
+package Template::Plugin::XML::Simple;
+
+require 5.004;
+
+use strict;
+use Template::Plugin;
+use XML::Simple;
+
+use base qw( Template::Plugin );
+use vars qw( $VERSION );
+
+$VERSION = sprintf("%d.%02d", q$Revision: 2.65 $ =~ /(\d+)\.(\d+)/);
+
+
+#------------------------------------------------------------------------
+# new($context, $file_or_text, \%config)
+#------------------------------------------------------------------------
+
+sub new {
+ my $class = shift;
+ my $context = shift;
+ my $input = shift;
+ my $args = ref $_[-1] eq 'HASH' ? pop(@_) : { };
+
+ if (defined($input)) {
+ # an input parameter can been be provided and can contain
+ # XML text or the filename of an XML file, which we load
+ # using insert() to honour the INCLUDE_PATH; then we feed
+ # it into XMLin().
+ $input = $context->insert($input) unless ( $input =~ /</ );
+ return XMLin($input, %$args);
+ }
+ else {
+ # otherwise return a XML::Simple object
+ return new XML::Simple;
+ }
+}
+
+
+
+#------------------------------------------------------------------------
+# _throw($errmsg)
+#
+# Raise a Template::Exception of type XML.Simple via die().
+#------------------------------------------------------------------------
+
+sub _throw {
+ my ($self, $error) = @_;
+ die (Template::Exception->new('XML.Simple', $error));
+}
+
+
+1;
+
+__END__
+
+
+#------------------------------------------------------------------------
+# IMPORTANT NOTE
+# This documentation is generated automatically from source
+# templates. Any changes you make here may be lost.
+#
+# The 'docsrc' documentation source bundle is available for download
+# from http://www.template-toolkit.org/docs.html and contains all
+# the source templates, XML files, scripts, etc., from which the
+# documentation for the Template Toolkit is built.
+#------------------------------------------------------------------------
+
+=head1 NAME
+
+Template::Plugin::XML::Simple - Plugin interface to XML::Simple
+
+=head1 SYNOPSIS
+
+ # load plugin and specify XML text or file to parse
+ [% USE xml = XML.Simple(xml_file_or_text) %]
+
+ # or load plugin as an object...
+ [% USE xml = XML.Simple %]
+
+ # ...then use XMLin or XMLout as usual
+ [% xml.XMLout(data_ref, args) %]
+ [% xml.XMLin(xml_file_or_text, args) %]
+
+=head1 DESCRIPTION
+
+This is a Template Toolkit plugin interfacing to the XML::Simple module.
+
+=head1 PRE-REQUISITES
+
+This plugin requires that the XML::Parser and XML::Simple modules be
+installed. These are available from CPAN:
+
+ http://www.cpan.org/modules/by-module/XML
+
+=head1 AUTHORS
+
+This plugin wrapper module was written by Andy Wardley
+E<lt>abw@xxxxxxxxxxxx<gt>.
+
+The XML::Simple module which implements all the core functionality
+was written by Grant McLean E<lt>grantm@xxxxxxxxxx<gt>.
+
+=head1 VERSION
+
+2.65, distributed as part of the
+Template Toolkit version 2.14, released on 04 October 2004.
+
+=head1 COPYRIGHT
+
+ Copyright (C) 1996-2004 Andy Wardley. All Rights Reserved.
+ Copyright (C) 1998-2002 Canon Research Centre Europe Ltd.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<Template::Plugin|Template::Plugin>, L<XML::Simple|XML::Simple>, L<XML::Parser|XML::Parser>
+
Added: www/trunk/XML/Style.pm
===================================================================
--- www/trunk/XML/Style.pm (rev 0)
+++ www/trunk/XML/Style.pm 2007-04-01 11:07:38 UTC (rev 242)
@@ -0,0 +1,357 @@
+#============================================================= -*-Perl-*-
+#
+# Template::Plugin::XML::Style
+#
+# DESCRIPTION
+# Template Toolkit plugin which performs some basic munging of XML
+# to perform simple stylesheet like transformations.
+#
+# AUTHOR
+# Andy Wardley <abw@xxxxxxx>
+#
+# COPYRIGHT
+# Copyright (C) 2001 Andy Wardley. All Rights Reserved.
+#
+# This module is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+#
+# REVISION
+# $Id: Style.pm,v 2.35 2004/01/30 19:33:36 abw Exp $
+#
+#============================================================================
+
+package Template::Plugin::XML::Style;
+
+require 5.004;
+
+use strict;
+use Template::Plugin::Filter;
+
+use base qw( Template::Plugin::Filter );
+use vars qw( $VERSION $DYNAMIC $FILTER_NAME );
+
+$VERSION = sprintf("%d.%02d", q$Revision: 2.35 $ =~ /(\d+)\.(\d+)/);
+$DYNAMIC = 1;
+$FILTER_NAME = 'xmlstyle';
+
+
+#------------------------------------------------------------------------
+# new($context, \%config)
+#------------------------------------------------------------------------
+
+sub init {
+ my $self = shift;
+ my $name = $self->{ _ARGS }->[0] || $FILTER_NAME;
+ $self->install_filter($name);
+ return $self;
+}
+
+
+sub filter {
+ my ($self, $text, $args, $config) = @_;
+
+ # munge start tags
+ $text =~ s/ < ([\w\.\:]+) ( \s+ [^>]+ )? >
+ / $self->start_tag($1, $2, $config)
+ /gsex;
+
+ # munge end tags
+ $text =~ s/ < \/ ([\w\.\:]+) >
+ / $self->end_tag($1, $config)
+ /gsex;
+
+ return $text;
+
+}
+
+
+sub start_tag {
+ my ($self, $elem, $textattr, $config) = @_;
+ $textattr ||= '';
+ my ($pre, $post);
+
+ # look for an element match in the stylesheet
+ my $match = $config->{ $elem }
+ || $self->{ _CONFIG }->{ $elem }
+ || return "<$elem$textattr>";
+
+ # merge element attributes into copy of stylesheet attributes
+ my $attr = { %{ $match->{ attributes } || { } } };
+ while ($textattr =~ / \s* ([\w\.\:]+) = " ([^"]+) " /gsx ) {
+ $attr->{ $1 } = $2;
+ }
+ $textattr = join(' ', map { "$_=\"$attr->{$_}\"" } keys %$attr);
+ $textattr = " $textattr" if $textattr;
+
+ $elem = $match->{ element } || $elem;
+ $pre = $match->{ pre_start } || '';
+ $post = $match->{ post_start } || '';
+
+ return "$pre<$elem$textattr>$post";
+}
+
+
+sub end_tag {
+ my ($self, $elem, $config) = @_;
+ my ($pre, $post);
+
+ # look for an element match in the stylesheet
+ my $match = $config->{ $elem }
+ || $self->{ _CONFIG }->{ $elem }
+ || return "</$elem>";
+
+ $elem = $match->{ element } || $elem;
+ $pre = $match->{ pre_end } || '';
+ $post = $match->{ post_end } || '';
+
+ return "$pre</$elem>$post";
+}
+
+
+1;
+
+__END__
+
+
+#------------------------------------------------------------------------
+# IMPORTANT NOTE
+# This documentation is generated automatically from source
+# templates. Any changes you make here may be lost.
+#
+# The 'docsrc' documentation source bundle is available for download
+# from http://www.template-toolkit.org/docs.html and contains all
+# the source templates, XML files, scripts, etc., from which the
+# documentation for the Template Toolkit is built.
+#------------------------------------------------------------------------
+
+=head1 NAME
+
+Template::Plugin::XML::Style - Simple XML stylesheet transfomations
+
+=head1 SYNOPSIS
+
+ [% USE xmlstyle
+ table = {
+ attributes = {
+ border = 0
+ cellpadding = 4
+ cellspacing = 1
+ }
+ }
+ %]
+
+ [% FILTER xmlstyle %]
+ <table>
+ <tr>
+ <td>Foo</td> <td>Bar</td> <td>Baz</td>
+ </tr>
+ </table>
+ [% END %]
+
+=head1 DESCRIPTION
+
+This plugin defines a filter for performing simple stylesheet based
+transformations of XML text.
+
+Named parameters are used to define those XML elements which require
+transformation. These may be specified with the USE directive when
+the plugin is loaded and/or with the FILTER directive when the plugin
+is used.
+
+This example shows how the default attributes C<border="0"> and
+C<cellpadding="4"> can be added to E<lt>tableE<gt> elements.
+
+ [% USE xmlstyle
+ table = {
+ attributes = {
+ border = 0
+ cellpadding = 4
+ }
+ }
+ %]
+
+ [% FILTER xmlstyle %]
+ <table>
+ ...
+ </table>
+ [% END %]
+
+This produces the output:
+
+ <table border="0" cellpadding="4">
+ ...
+ </table>
+
+Parameters specified within the USE directive are applied automatically each
+time the C<xmlstyle> FILTER is used. Additional parameters passed to the
+FILTER directive apply for only that block.
+
+ [% USE xmlstyle
+ table = {
+ attributes = {
+ border = 0
+ cellpadding = 4
+ }
+ }
+ %]
+
+ [% FILTER xmlstyle
+ tr = {
+ attributes = {
+ valign="top"
+ }
+ }
+ %]
+ <table>
+ <tr>
+ ...
+ </tr>
+ </table>
+ [% END %]
+
+Of course, you may prefer to define your stylesheet structures once and
+simply reference them by name. Passing a hash reference of named parameters
+is just the same as specifying the named parameters as far as the Template
+Toolkit is concerned.
+
+ [% style_one = {
+ table = { ... }
+ tr = { ... }
+ }
+ style_two = {
+ table = { ... }
+ td = { ... }
+ }
+ style_three = {
+ th = { ... }
+ tv = { ... }
+ }
+ %]
+
+ [% USE xmlstyle style_one %]
+
+ [% FILTER xmlstyle style_two %]
+ # style_one and style_two applied here
+ [% END %]
+
+ [% FILTER xmlstyle style_three %]
+ # style_one and style_three applied here
+ [% END %]
+
+Any attributes defined within the source tags will override those specified
+in the style sheet.
+
+ [% USE xmlstyle
+ div = { attributes = { align = 'left' } }
+ %]
+
+
+ [% FILTER xmlstyle %]
+ <div>foo</div>
+ <div align="right">bar</div>
+ [% END %]
+
+The output produced is:
+
+ <div align="left">foo</div>
+ <div align="right">bar</div>
+
+The filter can also be used to change the element from one type to another.
+
+ [% FILTER xmlstyle
+ th = {
+ element = 'td'
+ attributes = { bgcolor='red' }
+ }
+ %]
+ <tr>
+ <th>Heading</th>
+ </tr>
+ <tr>
+ <td>Value</td>
+ </tr>
+ [% END %]
+
+The output here is as follows. Notice how the end tag C<E<lt>/thE<gt>> is
+changed to C<E<lt>/tdE<gt>> as well as the start tag.
+
+ <tr>
+ <td bgcolor="red">Heading</td>
+ </tr>
+ <tr>
+ <td>Value</td>
+ </tr>
+
+You can also define text to be added immediately before or after the
+start or end tags. For example:
+
+ [% FILTER xmlstyle
+ table = {
+ pre_start = '<div align="center">'
+ post_end = '</div>'
+ }
+ th = {
+ element = 'td'
+ attributes = { bgcolor='red' }
+ post_start = '<b>'
+ pre_end = '</b>'
+ }
+ %]
+ <table>
+ <tr>
+ <th>Heading</th>
+ </tr>
+ <tr>
+ <td>Value</td>
+ </tr>
+ </table>
+ [% END %]
+
+The output produced is:
+
+ <div align="center">
+ <table>
+ <tr>
+ <td bgcolor="red"><b>Heading</b></td>
+ </tr>
+ <tr>
+ <td>Value</td>
+ </tr>
+ </table>
+ </div>
+
+=head1 AUTHOR
+
+Andy Wardley E<lt>abw@xxxxxxxxxxxxxxxx<gt>
+
+L<http://www.andywardley.com/|http://www.andywardley.com/>
+
+
+
+
+=head1 VERSION
+
+2.35, distributed as part of the
+Template Toolkit version 2.14, released on 04 October 2004.
+
+=head1 COPYRIGHT
+
+ Copyright (C) 1996-2004 Andy Wardley. All Rights Reserved.
+ Copyright (C) 1998-2002 Canon Research Centre Europe Ltd.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<Template::Plugin|Template::Plugin>
+
+=cut
+
+# Local Variables:
+# mode: perl
+# perl-indent-level: 4
+# indent-tabs-mode: nil
+# End:
+#
+# vim: expandtab shiftwidth=4:
Added: www/trunk/XML/XPath.pm
===================================================================
--- www/trunk/XML/XPath.pm (rev 0)
+++ www/trunk/XML/XPath.pm 2007-04-01 11:07:38 UTC (rev 242)
@@ -0,0 +1,284 @@
+#============================================================= -*-Perl-*-
+#
+# Template::Plugin::XML::XPath
+#
+# DESCRIPTION
+#
+# Template Toolkit plugin interfacing to the XML::XPath.pm module.
+#
+# AUTHOR
+# Andy Wardley <abw@xxxxxxx>
+#
+# COPYRIGHT
+# Copyright (C) 2000 Andy Wardley. All Rights Reserved.
+#
+# This module is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+#
+#----------------------------------------------------------------------------
+#
+# $Id: XPath.pm,v 2.70 2004/01/30 19:33:36 abw Exp $
+#
+#============================================================================
+
+package Template::Plugin::XML::XPath;
+
+require 5.004;
+
+use strict;
+use Template::Exception;
+use Template::Plugin;
+use XML::XPath;
+
+use base qw( Template::Plugin );
+use vars qw( $VERSION );
+
+$VERSION = sprintf("%d.%02d", q$Revision: 2.70 $ =~ /(\d+)\.(\d+)/);
+
+
+#------------------------------------------------------------------------
+# new($context, \%config)
+#
+# Constructor method for XML::XPath plugin. Creates an XML::XPath
+# object and initialises plugin configuration.
+#------------------------------------------------------------------------
+
+sub new {
+ my $class = shift;
+ my $context = shift;
+ my $args = ref $_[-1] eq 'HASH' ? pop(@_) : { };
+ my ($content, $about);
+
+ # determine the input source from a positional parameter (may be a
+ # filename or XML text if it contains a '<' character) or by using
+ # named parameters which may specify one of 'file', 'filename', 'text'
+ # or 'xml'
+
+ if ($content = shift) {
+ if ($content =~ /\</) {
+ $about = 'xml text';
+ $args->{ xml } = $content;
+ }
+ else {
+ $about = "xml file $content";
+ $args->{ filename } = $content;
+ }
+ }
+ elsif ($content = $args->{ text } || $args->{ xml }) {
+ $about = 'xml text';
+ $args->{ xml } = $content;
+ }
+ elsif ($content = $args->{ file } || $args->{ filename }) {
+ $about = "xml file $content";
+ $args->{ filename } = $content;
+ }
+ else {
+ return $class->_throw('no filename or xml text specified');
+ }
+
+ return XML::XPath->new(%$args)
+ or $class->_throw("failed to create XML::XPath::Parser\n");
+}
+
+
+
+#------------------------------------------------------------------------
+# _throw($errmsg)
+#
+# Raise a Template::Exception of type XML.XPath via die().
+#------------------------------------------------------------------------
+
+sub _throw {
+ my ($self, $error) = @_;
+# print STDERR "about to throw $error\n";
+ die (Template::Exception->new('XML.XPath', $error));
+}
+
+
+#========================================================================
+package XML::XPath::Node::Element;
+#========================================================================
+
+#------------------------------------------------------------------------
+# present($view)
+#
+# Method to present an element node via a view.
+#------------------------------------------------------------------------
+
+sub present {
+ my ($self, $view) = @_;
+ $view->view($self->getName(), $self);
+}
+
+sub content {
+ my ($self, $view) = @_;
+ my $output = '';
+ foreach my $node (@{ $self->getChildNodes }) {
+ $output .= $node->present($view);
+ }
+ return $output;
+}
+
+#----------------------------------------------------------------------
+# starttag(), endtag()
+#
+# Methods to output the start & end tag, e.g. <foo bar="baz"> & </foo>
+#----------------------------------------------------------------------
+
+sub starttag {
+ my ($self) = @_;
+ my $output = "<". $self->getName();
+ foreach my $attr ($self->getAttributes())
+ {
+ $output .= $attr->toString();
+ }
+ $output .= ">";
+ return $output;
+}
+
+sub endtag {
+ my ($self) = @_;
+ return "</". $self->getName() . ">";
+}
+
+#========================================================================
+package XML::XPath::Node::Text;
+#========================================================================
+
+#------------------------------------------------------------------------
+# present($view)
+#
+# Method to present a text node via a view.
+#------------------------------------------------------------------------
+
+sub present {
+ my ($self, $view) = @_;
+ $view->view('text', $self->string_value);
+}
+
+
+#========================================================================
+package XML::XPath::Node::Comment;
+#========================================================================
+
+sub present { return ''; }
+sub starttag { return ''; }
+sub endtag { return ''; }
+
+
+1;
+
+__END__
+
+
+#------------------------------------------------------------------------
+# IMPORTANT NOTE
+# This documentation is generated automatically from source
+# templates. Any changes you make here may be lost.
+#
+# The 'docsrc' documentation source bundle is available for download
+# from http://www.template-toolkit.org/docs.html and contains all
+# the source templates, XML files, scripts, etc., from which the
+# documentation for the Template Toolkit is built.
+#------------------------------------------------------------------------
+
+=head1 NAME
+
+Template::Plugin::XML::XPath - Plugin interface to XML::XPath
+
+=head1 SYNOPSIS
+
+ # load plugin and specify XML file to parse
+ [% USE xpath = XML.XPath(xmlfile) %]
+ [% USE xpath = XML.XPath(file => xmlfile) %]
+ [% USE xpath = XML.XPath(filename => xmlfile) %]
+
+ # load plugin and specify XML text to parse
+ [% USE xpath = XML.XPath(xmltext) %]
+ [% USE xpath = XML.XPath(xml => xmltext) %]
+ [% USE xpath = XML.XPath(text => xmltext) %]
+
+ # then call any XPath methods (see XML::XPath docs)
+ [% FOREACH page = xpath.findnodes('/html/body/page') %]
+ [% page.getAttribute('title') %]
+ [% END %]
+
+ # define VIEW to present node(s)
+ [% VIEW repview notfound='xmlstring' %]
+ # handler block for a <report>...</report> element
+ [% BLOCK report %]
+ [% item.content(view) %]
+ [% END %]
+
+ # handler block for a <section title="...">...</section> element
+ [% BLOCK section %]
+ <h1>[% item.getAttribute('title') | html %]</h1>
+ [% item.content(view) %]
+ [% END %]
+
+ # default template block passes tags through and renders
+ # out the children recursivly
+ [% BLOCK xmlstring;
+ item.starttag; item.content(view); item.endtag;
+ END %]
+
+ # block to generate simple text
+ [% BLOCK text; item | html; END %]
+ [% END %]
+
+ # now present node (and children) via view
+ [% repview.print(page) %]
+
+ # or print node content via view
+ [% page.content(repview) %]
+
+=head1 PRE-REQUISITES
+
+This plugin requires that the XML::Parser and XML::XPath modules be
+installed. These are available from CPAN:
+
+ http://www.cpan.org/modules/by-module/XML
+
+=head1 DESCRIPTION
+
+This is a Template Toolkit plugin interfacing to the XML::XPath module.
+
+All methods implemented by the XML::XPath modules are available. In
+addition, the XML::XPath::Node::Element module implements
+present($view) and content($view) methods method for seamless
+integration with Template Toolkit VIEWs. The XML::XPath::Node::Text
+module is also adorned with a present($view) method which presents
+itself via the view using the 'text' template.
+
+To aid the reconstruction of XML, methods starttag and endtag are
+added to XML::XPath::Node::Element which return the start and
+end tag for that element. This means that you can easily do:
+
+ [% item.starttag %][% item.content(view) %][% item.endtag %]
+
+To render out the start tag, followed by the content rendered in the
+view "view", followed by the end tag.
+
+=head1 AUTHORS
+
+This plugin module was written by Andy Wardley E<lt>abw@xxxxxxxxxxxx<gt>.
+
+The XML::XPath module is by Matt Sergeant E<lt>matt@xxxxxxxxxxxxx<gt>.
+
+=head1 VERSION
+
+2.70, distributed as part of the
+Template Toolkit version 2.14, released on 04 October 2004.
+
+=head1 COPYRIGHT
+
+ Copyright (C) 1996-2004 Andy Wardley. All Rights Reserved.
+ Copyright (C) 1998-2002 Canon Research Centre Europe Ltd.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<Template::Plugin|Template::Plugin>, L<XML::XPath|XML::XPath>, L<XML::Parser|XML::Parser>
+