=head1 NAME

HTML::Seamstress - HTML::Tree subclass for HTML templating via tree rewriting

=head1 SYNOPSIS

=head2 Text substitution

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 <klass=content span id="name">dummy_name</span>.
   <p>Today's date is <klass=content span id="date">dummy_date</span>.
 </body>
 </html>

=head3 Seamstress compiles HTML to C<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 object-oriented
accessors.  

 use html::hello_world; 
 
 my $tree = html::hello_world->new; 
 $tree->name('terrence brannon')->date('5/11/1969')->as_HTML;

=head2 If-then-else with the highlander kompiler hint

The C<highlander> kompiler hint is used to mark a subtree of HTML in
which only one child should survive:

 <span klass="highlander" 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>


=head3 Compile and use the module:

 use html::highlander;

 my $tree = html::highlander->new;

 $tree->age_dialog
    (
     [
      under10 => sub { $_[0] < 10} , 
      under18 => sub { $_[0] < 18} ,
      welcome => sub { 1 }
     ],
     $age
    )->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:

=over 

=item * L<HTML::ElementTable>

=item * L<HTML::Element::Library>

=item * L<HTML::Seamstress>

=item * L<HTML::Element>

=back

More functionality of 


=head1 DESCRIPTION

From reading L<HTML::Tree::Scanning>, we know that HTML has a tree
structure. HTML::Seamstress is a subclass of L<HTML::TreeBuilder>
which makes it a little easier to perform common HTML templating
operations as tree rewriting.

=head2 Text Substitution == Node rewriting

The L</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.

There are two methods for rewriting the content of a node. The more powerful
method is C<set_child_content>. The more convenient is C<content_handler>.
Both are desc

=head3 $tree->set_child_content(@look_down, $content)

This method looks down $tree using the criteria specified in 
C<@look_down>
using the the HTML::Element C<look_down()> method. 

After finding the node, it detaches the node's content
and pushes $content as the node's content.

=head3 $tree->content_handler($sid_value , $content)

This is a convenience method. Because the look_down criteria will often
simply be:

   sid => 'fixup'

to find things like:

   <a sid=fixup href=http://www.somesite.org>replace_content</a>

You can call this method to shorten your typing a bit:

   $tree->content_handler( fixup => 'new text' )

Instead of typing:

  $tree->set_child_content(sid => 'fixup', 'new text') 


=head3 set_content()

=head2 Conditional Processing (aka if/unless) == Node Deletion 

In tree rewriting terms, an C<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);
  }

 }


=head2 Looping (e.g. Table Unrolling) == Child Replication




=head2 EXPORT

None by default.



=head1 SEE ALSO

=head2 HTML Templating as Tree Rewriting: Part I: "If Statements"

L<http://perlmonks.org/index.pl?node_id=302606>

=head2 HTATR II: HTML table generation via DWIM tree rewriting

L<http://perlmonks.org/index.pl?node_id=303188>

=head2 Los Angeles Perl Mongers Talk on HTML::Seamstress

L<http://www.metaperl.com>

=head2 XMLC, A similar framework for Java

L<http://xmlc.enhydra.org>

=head2 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.

=over

=item * L<Petal>

Based on Zope's TAL, this is a very nice and complete framework that is
the basis of MkDoc, a XML application server.

=item * L<XML::LibXML>

By the XML guru Matt Sergeant, who is also the author of AxKit, another XML 
application server.

=back

=head1 AUTHOR

Terrence Brannon, E<lt>tbone@cpan.org<gt>

=head1 COPYRIGHT AND LICENSE

Copyright 2002-2004 by Terrence Brannon.

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself. 

=cut
