NAME
HTML::Seamstress - Perl extension for HTML generation via tree rewriting
SYNOPSIS
HTML "adulterated" with id attributes
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h1>Hello World</h1>
<p>Hello, my name is <span id="name">ah, Clem</span>.
<p>Today's date is <span id="date">Oct 6, 2001</span>.
</body>
</html>
Perl finds nodes in the tree and rewrites them:
use HTML::Seamstress; # HTML::Seamstress isa HTML::TreeBuilder :)
my $tree = HTML::Seamstress->new_from_file($html_file);
$tree->name_handler('bob');
$tree->date_handler(`date`);
sub name_handler {
my ($tree, $name) = @_;
my $name_tag = $tree->look_down('id', 'name');
$name_tag->detach_content; # delete dummy content ("ah, Clem")
$name_tag->push_content($name);
}
sub date_handler {
my ($tree, $date) = @_;
my $name_tag = $tree->look_down('id', 'date');
$name_tag->detach_content; # delete dummy content ("Oct 6, 2001")
$name_tag->push_content($date);
}
Or with convenience methods:
use HTML::Seamstress;
my $tree = HTML::Seamstress->new_from_file($html_file);
$tree->content_handler(name => 'bob');
$tree->content_handler(date => `date`);
DESCRIPTION
From reading HTML::Tree::Scanning, we know that HTML has a tree structure. HTML::Seamstress is a subclass of HTML::TreeBuilder which makes it a little 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.
(Conditional Processing aka if/unless/elsif/else) == 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.
For example, given this Template-style HTML:
[% IF age < 10 %]
Hello, does your mother know you're
using her AOL account?
[% ELSIF age < 18 %]
Sorry, you're not old enough to enter
(and too dumb to lie about your age)
[% ELSE %]
Welcome
[% END %]
Here is the HTML and Perl for Seamstress:
<span id=age_handler>
<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>
package HTML::Seamstress
use HTML::Seamstress;
my $tree = HTML::Seamstress->new();
$tree->parse_file($filename);
$tree->age_handler($age);
print $tree->as_HTML;
sub age_handler {
my ($tree, $age) = @_;
my $SPAN = $tree->look_down('id', 'age_handler');
if ($age < 10) {
$SPAN->look_down('id', $_)->detach for qw(under18 welcome);
} elsif ($age < 18) {
$SPAN->look_down('id', $_)->detach for qw(under10 welcome);
} else {
$SPAN->look_down('id', $_)->detach for qw(under10 under18);
}
}
Looping (e.g. able Unrolling) == Child Replication
Sample Model
package Simple::Class;
use Set::Array;
my @name = qw(bob bill brian babette bobo bix);
my @age = qw(99 12 44 52 12 43);
my @weight = qw(99 52 80 124 120 230);
sub new {
my $this = shift;
bless {}, ref($this) || $this;
}
sub load_data {
my @data;
for (0 .. 5) {
push @data, {
age => $age[rand $#age] + int rand 20,
name => shift @name,
weight => $weight[rand $#weight] + int rand 40
}
}
Set::Array->new(@data);
}
1;
Sample Usage:
my $data = Simple::Class->load_data;
++$_->{age} for @$data
Inline Code to Unroll a Table
HTML
<html>
<table id="load_data">
<tr> <th>name</th><th>age</th><th>weight</th> </tr>
<tr id="iterate">
<td id="name"> NATURE BOY RIC FLAIR </td>
<td id="age"> 35 </td>
<td id="weight"> 220 </td>
</tr>
</table>
</html>
Perl
Program fragment delivered error ``Can't find string terminator "'" anywhere before EOF at lib/HTML/Seamstress.tt line 137, <F> line 47.''
Seamstress API call to Unroll a Table
Program fragment delivered error ``couldnt open file : No such file or directory at ./tt.pl line 18, <F> line 47.''
Looping over Multiple Sample Rows
* HTML
Program fragment delivered error ``syntax error at lib/HTML/Seamstress.tt line 147, near "#line 147 lib/HTML/Seamstress.tt slide_code 'loop/simple-alt.html'"''
* Only one change to last API call.
This:
gi_tr => 'iterate',
becomes this:
gi_tr => ['iterate1', 'iterate2']
Whither a Table with No Rows
Use Conditional Processing before Child Replication. In human terms, if (no data) { pop in a no data table } else { pop in the data table }
<span id=no_data>
<table><tr><td>No Data is Good Data</td></tr></table>
</span>
<span id=load_data>
Program fragment delivered error ``couldnt open file : No such file or directory at ./tt.pl line 18, <F> line 47.''
</span>
EXPORT
None by default.
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
AUTHOR
Terrence Brannon, <tbone@cpan.org<gt>
COPYRIGHT AND LICENSE
Copyright 2003 by Terrence Brannon.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.