=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
nameageweight
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
nameageweight
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:
No Data is Good Data
nameageweight
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