.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32 .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .\" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .hy 0 .if n .na .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Template::Plugin::XML::LibXML 3pm" .TH Template::Plugin::XML::LibXML 3pm "2008-03-01" "perl v5.8.8" "User Contributed Perl Documentation" .SH "NAME" Template::Plugin::XML::LibXML \- XML::LibXML Template Toolkit Plugin .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& [% USE docroot = XML.LibXML("helloworld.xml") %] .Ve .PP .Vb 1 \& The message is: [% docroot.find("/greeting/text") %] .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module provides a plugin for the XML::LibXML module. It can be utilised the same as any other Template Toolkit plugin, by using a \s-1USE\s0 statement from within a Template. The use statment will return a reference to root node of the parsed document .Sh "Specifying a Data Source" .IX Subsection "Specifying a Data Source" The plugin is capable of using either a string, a filename or a filehandle as a source for either \s-1XML\s0 data, or \s-1HTML\s0 data which will be converted to \s-1XHTML\s0 internally. .PP The \s-1USE\s0 statement can take one or more arguments to specify what \s-1XML\s0 should be processed. If only one argument is passed then the plugin will attempt to guess how what it has been passed should be interpreted. .PP When it is forced to guess what type of data it is used the routine will first look for an open filehandle, which if it finds it will assume it's a filehandle to a file containing \s-1XML\s0. Failing this (in decreasing order) it will look for the chars \*(L"\*(R" tag (and assume it's \s-1HTML\s0 string,) look for a \*(L"<\*(R" (and assume it's \s-1XML\s0 string without a header,) or assume what it's been passed is the filename to a file containing \s-1XML\s0. .PP In the interests of being explicit, you may specify the type of data you are loading using the same names as in the \fBXML::LibXML\fR documentation: .PP .Vb 2 \& # value contains the xml string \& [% USE docroot = XML.LibXML(string => value) %] .Ve .PP .Vb 2 \& # value contains the filename of the xml \& [% USE docroot = XML.LibXML(file => value) %] .Ve .PP .Vb 2 \& # value contains an open filehandle to some xml \& [% USE docroot = XML.LibXML(fh => value) %] .Ve .PP .Vb 2 \& # value contains the html string \& [% USE docroot = XML.LibXML(html_string => value) %] .Ve .PP .Vb 2 \& # value contains the filename of the html \& [% USE docroot = XML.LibXML(html_file => value) %] .Ve .PP .Vb 2 \& # value contains an open filehandle to some html \& [% USE docroot = XML.LibXML(html_fh => value) %] .Ve .PP Or, if you want you can use similar names to that the \s-1XML\s0.XPath plugin uses: .PP .Vb 3 \& # value contains the xml string \& [% USE docroot = XML.LibXML(xml => value) %] or \& [% USE docroot = XML.LibXML(text => value) %] .Ve .PP .Vb 2 \& # value contains the filename of the xml \& [% USE docroot = XML.LibXML(filename => value) %] .Ve .PP .Vb 3 \& # value contains the html string \& [% USE docroot = XML.LibXML(html => value) %] or \& [% USE docroot = XML.LibXML(html_text => value) %] .Ve .PP .Vb 3 \& # value contains the filename of the html \& [% USE docroot = XML.LibXML(html_file => value) %] \& [% USE docroot = XML.LibXML(html_filename => value) %] .Ve .PP You can provide extra arguments which will be used to set parser options. See XML::LibXML for details on these. I will repeat the following warning however: \*(L"LibXML options are global (unfortunately this is a limitation of the underlying implementation, not this interface)...Note that even two forked processes will share some of the same options, so be careful out there!\*(R" .PP .Vb 3 \& # turn off expanding entities \& [% USE docroot = XML.LibXML("file.xml", \& expand_entities => 0); .Ve .Sh "Obtaining Parts of an \s-1XML\s0 Document" .IX Subsection "Obtaining Parts of an XML Document" XML::LibXML provides two simple mechanisms for obtaining sections of the \s-1XML\s0 document, both of which can be used from within the Template Toolkit .PP The first of these is to use a XPath statement. Simple values can be found with the \f(CW\*(C`findvalue\*(C'\fR routine: .PP .Vb 3 \& # get the title attribute of the first page node \& # (note xpath starts counting from one not zero) \& [% docroot.findvalue("/website/section/page[1]/@title"); %] .Ve .PP .Vb 2 \& # get the text contained within a node \& [% htmldoc.findvalue("/html/body/h1[1]/text()") %] .Ve .PP Nodes of the xml document can be found with the \f(CW\*(C`findnodes\*(C'\fR .PP .Vb 2 \& # get all the pages (\(aqpages\(aq is a list of nodes) \& [% pages = docroot.findnodes("/website/section/page") %] .Ve .PP .Vb 3 \& # get the first page (as TT folds single elements arrays \& # to scalars, \(aqpage1\(aq is the one node that matched) \& [% page1 = docroot.findnodes("/website/section/page[1]") %] .Ve .PP Then further xpath commands can then be applied to those nodes in turn: .PP .Vb 2 \& # get the title attribute of the first page \& [% page1.findvalue("@title") %] .Ve .PP An alternative approach is to use individual method calls to move around the tree. So the above could be written: .PP .Vb 5 \& # get the text of the h1 node \& [% htmlroot.documentElement \& .getElementsByLocalName("body").first \& .getElementsByLocalName("h1").first \& .textContent %] .Ve .PP .Vb 5 \& # get the title of the first page \& [% docroot.documentElement \& .getElementsByLocalName("section").first \& .getElementsByLocalName("page").first \& .getAttribute("title") %] .Ve .PP You should use the technique that makes the most since in the particular situation. These approaches can even be mixed: .PP .Vb 3 \& # get the first page title \& [% page1 = htmlroot.findnodes("/website/section/page[1]"); \& page1.getAttribute("title") %] .Ve .PP Much more information can be found in XML::LibXML::Node. .Sh "Rendering \s-1XML\s0" .IX Subsection "Rendering XML" The simplest way to use this plugin is simply to extract each value you want to print by hand .PP .Vb 2 \& The title of the first page is \(aq[% \& docroot.findvalue("/website/section/page[1]/@title") %]\(aq .Ve .PP or .PP .Vb 5 \& The title of the first page is \(aq[% \& docroot.documentElement \& .getElementsByLocalName("section").first \& .getElementsByLocalName("page").first \& .getAttribute("title") %]\(aq .Ve .PP You might want to discard whitespace from text areas. XPath can remove all leading and following whitespace, and condense all multiple spaces in the text to single spaces. .PP .Vb 3 \&

[% htmlroot.findvalue("normalize\-space( \& /html/body/p[1]/text() \& )" | html %]

.Ve .PP Note that, as above, when we're inserting the values extracted into a \&\s-1XML\s0 or \s-1HTML\s0 document we have to be careful to re-encode the attributes we need to escape with something like the html filter. A slightly more advanced technique is to extract a whole node and use the toString method call on it to convert it to a string of \s-1XML\s0. This is most useful when you are extracting an existing chunk of \s-1XML\s0 en mass, as things like and tags will be passed thought correctly and entities will be encoded suitably (for example '"' will be turned into '"') .PP .Vb 2 \& # get the second paragraph and insert it here as XML \& [% htmlroot.findnodes("/html/body/p[2]").toString %] .Ve .PP The most powerful technique is to use a view (as defined by the \s-1VIEW\s0 keyword) to recursively render out the \s-1XML\s0. By loading this plugin \&\f(CW\*(C`present\*(C'\fR methods will be created in the \fBXML::LibXML::Node\fR classes and subclasses. Calling \f(CW\*(C`present\*(C'\fR on a node with a \s-1VIEW\s0 will cause it to be rendered by the view block matching the local name of that node (with any non alphanumeric charecters turned to underscores. So a tag will be rendered by the 'author' block. Text nodes will call the 'text' block with the text of the node. .PP As the blocks can refer back to both the node it was called with and the view they can choose to recursively render out it's children using the view again. To better facilitate this technique the extra methods \&\f(CW\*(C`starttag\*(C'\fR (recreate a string of the starting tag, including attributes,) \f(CW\*(C`endtag\*(C'\fR (recreate a string of the ending tag) and \&\f(CW\*(C`content\*(C'\fR (when called with a view, will render by calling all the children of that node in turn with that view) have been added. .PP This is probably best shown with a well commented example: .PP .Vb 2 \& # create the view \& [% VIEW myview notfound => \(aqpassthru\(aq %] .Ve .PP .Vb 6 \& # default tag that will recreate the tag \(aqas is\(aq meaning \& # that unknown tags will \(aqpassed though\(aq by the view \& [% BLOCK passthru; item.starttag; \& item.content(view); \& item.endtag; \& END %] .Ve .PP .Vb 5 \& # convert all sections to headed paragraphs \& [% BLOCK section %] \&

[% item.getAttribute("title") %]

\&

[% item.content(view) %]

\& [% END %] .Ve .PP .Vb 4 \& # urls link to themselves \& [% BLOCK url %] \& [% item.content(view) %] \& [% END %] .Ve .PP .Vb 4 \& # email link to themselves with mailtos \& [% BLOCK email %] \& [% item.content(view) %] \& [% END %] .Ve .PP .Vb 4 \& # make pod links bold \& [% BLOCK pod %] \& [% item.content(view) %] \& [% END %] .Ve .PP .Vb 2 \& # render text, re\-encoding the attributes as we go \& [% BLOCK text; item | html; END %] .Ve .PP .Vb 2 \& # render arrays out \& [% BLOCK list; FOREACH i = item; view.print(i); END ; END %] .Ve .PP .Vb 1 \& [% END %] .Ve .PP .Vb 14 \& # use it to render the paragraphs \& [% USE doc = XML.LibXML("mydoc.xml") %] \& \& \& [% doc.findvalue("/doc/page[1]/@title") %] \& \& \& [% sections = doc.findnodes("/doc/page[1]/section"); \& FOREACH section = sections %] \& \& [% section.present(myview); \& END %] \& \& .Ve .SH "BUGS" .IX Header "BUGS" In order to detect if a scalar is an open filehandle (which is used if the \s-1USE\s0 isn't explicit about it's data source) this plugin uses the \&\f(CW\*(C`openhandle\*(C'\fR routine from \fBScalar::Util\fR. If you do not have \&\fBScalar::Util\fR installed, or the version of \fBScalar::Util\fR is sufficiently old that it does not support the \f(CW\*(C`openhandle\*(C'\fR routine then a much cruder \f(CW\*(C`defined(fileno $scalar)\*(C'\fR check will be employed. .PP Bugs may be reported either via the \s-1CPAN\s0 \s-1RT\s0 at http://rt.cpan.org/NoAuth/Bugs.html?Dist=Template\-Plugin\-XML\-LibXML or via the Template Toolkit mailing list: http://www.template\-toolkit.org/mailman/listinfo/templates or direct to the author .SH "AUTHOR" .IX Header "AUTHOR" Written by Mark Fowler .PP Copyright Mark Fowler 2002\-3, all rights reserved. .PP This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .PP This module wouldn't have been possible without the wonderful work that has been put into the libxml library by the gnome team or the equally wonderful work put in by Matt Sergeant and Christian Glahn in creating XML::LibXML. .SH "SEE ALSO" .IX Header "SEE ALSO" Template, Template::Plugin, XML::LibXML, XML::LibXML::Node. .PP On a similar note, you may want to see Template::Plugin::XML::XPath. .PP The t/test directory in the Template-Plugin-XML-LibXML distribution contains all the example \s-1XML\s0 files discussed in this documentation.