NAME
HTML::Seamstress - HTML::Tree subclass for HTML templating via tree rewriting
SYNOPSIS
Text substitution via replace_content() API call.
In our first example, we want to perform simple text substitution on the HTML template document. The HTML file html/hello_world.htm has klass attributes which serve as compiler (kompiler?) hints to Seamstress:
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h1>Hello World</h1>
<p>Hello, my name is <span id="name">dummy_name</span>.
<p>Today's date is <span id="date">dummy_date</span>.
</body>
</html>
Seamstress compiles HTML to html::hello_world
shell> seamc html/hello_world.htm
Seamstress v2.91 generating html::hello_world from html/hello_world.htm
Now you simply use the "compiled" version of HTML with API calls to HTML::TreeBuilder, HTML::Element, and HTML::Element::LIbrary
use html::hello_world;
my $tree = html::hello_world->new;
$tree->look_down(id => name)->replace_content('terrence brannon');
$tree->look_down(id => date)->replace_content('5/11/1969');
print $tree->as_HTML;
If-then-else with the highlander API call
<span id="age_dialog">
<span id="under10">
Hello, does your mother know you're
using her AOL account?
</span>
<span id="under18">
Sorry, you're not old enough to enter
(and too dumb to lie about your age)
</span>
<span id="welcome">
Welcome
</span>
</span>
Compile and use the module:
use html::age_dialog;
my $tree = html::dialog->new;
$tree->highlander
(age_dialog =>
[
under10 => sub { $_[0] < 10} ,
under18 => sub { $_[0] < 18} ,
welcome => sub { 1 }
],
$age
);
print $tree->as_HTML;
# will only output one of the 3 dialogues based on which closure
# fires first
The following libraries are always available for more complicated manipulations:
PHILOSOPHY / MOTIVATION for HTML::Seamstress
The motivation for HTML::Seamstress was to provide a module which would allow for pure HTML to be dynamically "unrolled" without any foreign elements in the HTML itself.
This design goal can be met by the 3 most popular templating systems for Perl - HTML::Mason, HTML::Template and Template, but none of them enforce it by design.
A second design goal for Seamstress was to have only two technologies, object-oriented Perl and HTML. Neither HTML::Template or Template meet this design goal. HTML::Mason has components defined as a *mix* of Perl and HTML as it's fundamental item of reuse. Seamstress keeps the two technologies pure and separate.
Mixing Perl and HTML means that validation tools for both technologies is unavailable. Mixing mini-languages and HTML means that you are stuck with the disadvantages of mini-languages. The disadvantages of mini-languages are discussed here:
http://perlmonks.org/?node_id=428053
So the above 3 modules can enforce the stated design goals but there are ways around these goals. The only CPAN modules which enforce both design goals completely are XML::LibXML, PeTaL and this module. If you have time to generate high-quality XML and are comfortable with DOM then there is no problem with this module. If you prefer a Perlish and intuitive collection of methods, then the fact that Seamstress is built on top of HTML::TreeBuilder will appeal to you. Finally, we come to PeTaL. A nice module, but I don't enjoy learning mini-languages and mastery of PeTal entails learning TAL and MetaTAL.
DESCRIPTION
This section will cover two things. What Seamstress offers and the theory of HTML as trees.
HTML as Trees
From reading HTML::Tree::Scanning, we know that HTML has a tree structure. HTML::Seamstress is a subclass of HTML::TreeBuilder and HTML::Element::Library which makes it easier to perform common HTML templating operations as tree rewriting.
Text Substitution == Node rewriting
The "SYNOPSIS" gave an example of text substitution. From a tree-writing perspective, text substitution involves an in-place change to the content of a node of an HTML tree.
You will find the "Tree Rewriting Methods" in HTML::Element::Library of great use when doing this sort of templating.
Conditional Processing (aka if/unless) == Node Deletion
In tree rewriting terms, an if
directive is used to decide whether a particular node of the HTML tree is preserved or deleted.
The most useful function for this is the highlander method, also a part of HTML::Element::Library.
Looping (e.g. Table Unrolling) == Child Replication
Table unrolling, pulldown creation, li unrolling, and dl unrolling are all examples of a tree operation in which you take a child of a node and clone it and then alter it in some way (replace the content, alter some of its attributes), and then stick it under its parent.
Functions for use with the common HTML elements --- <table>, <ol>, <ul>, <dl>, <select> are documented in HTML::Element::Lbrary and are prefaced with the words "Tree Building Methods".
What Seamstress offers
All of the tree-rewriting functionality discussed above exists outside of this distribution in libraries
The module HTML::Seamstress is a base class of HTML::Element and HTML::Element::Library which makes it easy to access the API calls of those modules in a convenient fashion.
The HTML::Seamstress distribution also comes with a small script, seamc
, which creates .pm files for .htm(l)? files, which can then be used by your Perl code. The .pm files have only a constructor, new
, which returns a tree of the HTML file blessed into the HTML::Seamstress class, which due to its subclassing, can be operated on by most of the modules listed above. Matthew Sisk's modules have not been subclassed or required by Seamstress because I have not had the personal need to use them, but doing so should be straightforward. Tests and patches welcome.
seamc requires a file called seamc.cfg to exist in the directory above the root for your HTML. Thus if your HTML is in a directory called html, the file seamc.cfg would be a sibling of the directory html. Here's an exmaple from a website I am doing now:
/var/www/terry/gimblerus.com:
total 56
drwxr-xr-x 11 terry terry 4096 Feb 3 02:19 .
drwxr-xr-x 5 terry terry 4096 Feb 4 00:46 ..
-rw-r--r-- 1 terry terry 318 Jan 30 02:59 favicon.ico
drwxr-xr-x 2 terry terry 4096 Feb 3 23:57 html
drwxr-xr-x 2 terry terry 4096 Jan 29 23:12 img
-rw-r--r-- 1 terry terry 544 Feb 2 16:35 index.html
-rw-r--r-- 1 terry terry 1 Jan 29 16:41 seamc.cfg
drwxr-xr-x 3 terry terry 4096 Jan 29 23:13 sql
/var/www/terry/gimblerus.com/html:
total 148
drwxr-xr-x 2 terry terry 4096 Feb 3 23:57 .
drwxr-xr-x 11 terry terry 4096 Feb 3 02:19 ..
-rw-r--r-- 1 terry terry 1188 Feb 3 23:57 addclan.html
-rw-r--r-- 1 terry terry 396 Feb 2 01:06 addclan.pm # <- Seamstress!
-rw-r--r-- 1 terry terry 323 Feb 3 17:44 footer.html
-rw-r--r-- 1 terry terry 394 Feb 1 23:50 footer.pm # <- Seamstress!
To use seamc, you simply type
seamc -verbose $html_file
from any directory. seamc will ascend the directory tree until it finds the seamc.cfg file and then create a Perl module whose name will allow it to be used as long as the html/
directory is in your Perl include path, @INC
.
For the example above, footer.pm will have package name html::footer and would be used like so:
use lib '/var/www/terry/gimblerus.com';
use html::footer;
my $tree = html::footer->new;
# ... etc
A simple structure-modifying method, expand_replace()
Let's say you have this HTML:
<div id="sidebar">
<div class="sideBlock" id=mpi>mc::picBar::index</div>
<div class="sideBlock" id=mnm>mc::navBox::makeLinks</div>
<div class="sideBlock" id=mg>mc::gutenBox</div>
</div>
In this case, the content of each sideBlock is the name of a Perl Seamstress-style class. As you know, When the constructor for such a class is called an HTML::Element, $E, will be returned for it's parsed content.
In this case, we want the content of the div element to go from the being the class name to being the HTML::Element that that class constructs, in other words:
and so to inline all 3 tags you would do the following;
$tree->look_down(id => $_)->expand_replace for qw(mpi mnm mg);
SEE ALSO
HTML Templating as Tree Rewriting: Part I: "If Statements"
http://perlmonks.org/index.pl?node_id=302606
HTATR II: HTML table generation via DWIM tree rewriting
http://perlmonks.org/index.pl?node_id=303188
Los Angeles Perl Mongers Talk on HTML::Seamstress
XMLC, A similar framework for Java
Similar Frameworks for Perl
Two other frameworks come to mind. Both are stricter with regard to the correctness of the HTML and both use a different means for node lookup and rewrite.
For me, Seamstress was a natural extension of my love for HTML::TreeBuilder, but if I had an XML job to do, I really think I would reach for Petal. It is quite sweet.
-
Based on Zope's TAL, this is a very nice and complete framework that is the basis of MkDoc, a XML application server. It offers a mini-language for XML rewriting, Seamstress does not. The philosophy of the Seamstress is the orthogonal integration of Perl and HTML not a mini-language and HTML.
-
By the XML guru Matt Sergeant, who is also the author of AxKit, another XML application server. This offers XPath for finding nodes
-
If I wanted to ape XMLC entirely, I would have used TJ Mather's XML::DOM. Because XMLC is based around DOM API calls. However, TreeBuilder is very handy and has a lot of nice libraries around it such HTML::PrettyPrinter. The biggest win of XML::DOM is it's easy integration with XML::Generator
From the docs, it looks like XML::GDOME is the successor to this module.
AUTHOR
Terrence Brannon, <tbone@cpan.org<gt>
COPYRIGHT AND LICENSE
Copyright 2002-2005 by Terrence Brannon.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.