=head1 NAME
HTML::Seamstress - Perl extension for HTML generation via tree rewriting
=head1 SYNOPSIS
=head2 HTML "adulterated" with id attributes
Hello World
Hello World
Hello, my name is ah, Clem.
Today's date is Oct 6, 2001.
=head2 Perl finds nodes in the tree and rewrites them:
use HTML::Seamstress; # HTML::Seamstress 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);
}
=head3 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`);
=head1 DESCRIPTION
From reading L, we know that HTML has a tree
structure. HTML::Seamstress is a subclass of L
which makes it a little easier to perform common HTML templating
operations as tree rewriting.
=head2 Text Substitution == Node rewriting
The L 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.
=head2 Conditional Processing (aka if/unless/elsif/else) == Node Deletion
In tree rewriting terms, an C 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:
Hello, does your mother know you're
using her AOL account?
Sorry, you're not old enough to enter
(and too dumb to lie about your age)
Welcome
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);
}
}
=head2 Looping (e.g. Table Unrolling) == Child Replication
=head3 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;
=head4 Sample Usage:
my $data = Simple::Class->load_data;
++$_->{age} for @$data
=head3 Inline Code to Unroll a Table
=head4 HTML
| name | age | weight |
| NATURE BOY RIC FLAIR |
35 |
220 |
=head4 Perl
require 'simple-class.pl';
use HTML::Seamstress;
# load the view
my $seamstress = HTML::Seamstress->new_from_file('simple.html');
# load the model
my $o = Simple::Class->new;
my $data = $o->load_data;
# find the and
my $table_node = $seamstress->look_down('id', 'load_data');
my $iter_node = $table_node->look_down('id', 'iterate');
my $table_parent = $table_node->parent;
# drop the sample and from the HTML
# only add them in if there is data in the model
# this is achieved via the $add_table flag
$table_node->detach;
$iter_node->detach;
my $add_table;
# Get a row of model data
while (my $row = shift @$data) {
# We got row data. Set the flag indicating ok to hook the table into the HTML
++$add_table;
# clone the sample
my $new_iter_node = $iter_node->clone;
# find the tags labeled name age and weight and
# set their content to the row data
$new_iter_node->content_handler($_ => $row->{$_})
for qw(name age weight);
$table_node->push_content($new_iter_node);
}
# reattach the table to the HTML tree if we loaded data into some table rows
$table_parent->push_content($table_node) if $add_table;
print $seamstress->as_HTML;
=head3 Seamstress API call to Unroll a Table
require 'simple-class.pl';
use HTML::Seamstress;
# load the view
my $seamstress = HTML::Seamstress->new_from_file('simple.html');
# load the model
my $o = Simple::Class->new;
$seamstress->table
(
# tell seamstress where to find the table, via the method call
# ->look_down('id', $gi_table). Seamstress detaches the table from the
# HTML tree automatically if no table rows can be built
gi_table => 'load_data',
# tell seamstress where to find the tr. This is a bit useless as
# the
usually can be found as the first child of the parent
gi_tr => 'iterate',
# the model data to be pushed into the table
table_data => $o->load_data,
# the way to take the model data and obtain one row
# if the table data were a hashref, we would do:
# my $key = (keys %$data)[0]; my $val = $data->{$key}; delete $data->{$key}
tr_data => sub { my ($self, $data) = @_;
shift(@{$data}) ;
},
# the way to take a row of data and fill the tags
td_data => sub { my ($tr_node, $tr_data) = @_;
$tr_node->content_handler($_ => $tr_data->{$_})
for qw(name age weight) }
);
print $seamstress->as_HTML;
=head3 Looping over Multiple Sample Rows
* HTML
| name | age | weight |
| NATURE BOY RIC FLAIR |
35 |
220 |
| NATURE BOY RIC FLAIR |
35 |
220 |
* Only one change to last API call.
This:
gi_tr => 'iterate',
becomes this:
gi_tr => ['iterate1', 'iterate2']
=head3 Whither a Table with No Rows
Often when a table has no rows, we want to display a message
indicating this to the view. Use conditional processing to decide what
to display:
| name | age | weight |
| NATURE BOY RIC FLAIR |
35 |
220 |
=head2 EXPORT
None by default.
=head1 SEE ALSO
=head2 HTML Templating as Tree Rewriting: Part I: "If Statements"
L
=head2 HTATR II: HTML table generation via DWIM tree rewriting
L
=head2 Los Angeles Perl Mongers Talk on HTML::Seamstress
L
=head1 AUTHOR
Terrence Brannon, Etbone@cpan.org
=head1 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.
=cut
|