html::treebuilder(3)

NAME

HTML::TreeBuilder - Parser that builds a HTML syntax tree

SYNOPSIS

foreach my $file_name (@ARGV) {
  my $tree = HTML::TreeBuilder->new; # empty tree
  $tree->parse_file($file_name);
  print "Hey,  here's  a  dump  of  the  parse  tree  of
$file_name:0;
  $tree->dump; # a method we inherit from HTML::Element
  print "And here it is, bizarrely rerendered as HTML:0,
    $tree->as_HTML, "0;
  # Now that we're done with it, we must destroy it.
  $tree = $tree->delete;
}

DESCRIPTION

(This class is part of the HTML::Tree dist.)

This class is for HTML syntax trees that get built out of
HTML source. The way to use it is to:

1. start a new (empty) HTML::TreeBuilder object,

2. then use one of the methods from HTML::Parser (presum
ably with $tree->parse_file($filename) for files, or with
$tree->parse($document_content) and $tree->eof if you've
got the content in a string) to parse the HTML document
into the tree $tree.

(You can combine steps 1 and 2 with the "new_from_file" or
"new_from_content" methods.)

2b. call $root->elementify() if you want.

3. do whatever you need to do with the syntax tree, pre
sumably involving traversing it looking for some bit of
information in it,

4. and finally, when you're done with the tree, call
$tree->delete() to erase the contents of the tree from memory. This kind of thing usually isn't necessary with
most Perl objects, but it's necessary for TreeBuilder
objects. See HTML::Element for a more verbose explanation
of why this is the case.

METHODS AND ATTRIBUTES

Objects of this class inherit the methods of both
HTML::Parser and HTML::Element. The methods inherited
from HTML::Parser are used for building the HTML tree, and
the methods inherited from HTML::Element are what you use
to scrutinize the tree. Besides this (HTML::TreeBuilder)
documentation, you must also carefully read the HTML::Ele
ment documentation, and also skim the HTML::Parser docu
mentation -- probably only its parse and parse_file meth
ods are of interest.

Most of the following methods native to HTML::TreeBuilder
control how parsing takes place; they should be set before you try parsing into the given object. You can set the
attributes by passing a TRUE or FALSE value as argument.
E.g., $root->implicit_tags returns the current setting for
the implicit_tags option, $root->implicit_tags(1) turns that option on, and $root->implicit_tags(0) turns it off.

$root = HTML::TreeBuilder->new_from_file(...)
This "shortcut" constructor merely combines construct
ing a new object (with the "new" method, below), and
calling $new->parse_file(...) on it. Returns the new
object. Note that this provides no way of setting any
parse options like store_comments (for that, call new,
and then set options, before calling parse_file). See
the notes (below) on parameters to parse_file.
$root = HTML::TreeBuilder->new_from_content(...)
This "shortcut" constructor merely combines construct
ing a new object (with the "new" method, below), and
calling for(...){$new->parse($_)} and $new->eof on it.
Returns the new object. Note that this provides no
way of setting any parse options like store_comments
(for that, call new, and then set options, before
calling parse_file). Example usages: HTML::Tree
Builder->new_from_content(@lines), or HTML::Tree
Builder->new_from_content($content)
$root = HTML::TreeBuilder->new()
This creates a new HTML::TreeBuilder object. This
method takes no attributes.
$root->parse_file(...)
[An important method inherited from HTML::Parser,
which see. Current versions of HTML::Parser can take
a filespec, or a filehandle object, like *FOO, or some
object from class IO::Handle, IO::File, IO::Socket) or
the like. I think you should check that a given file
exists before calling $root->parse_file($filespec).]
$root->parse(...)
[A important method inherited from HTML::Parser, which
see. See the note below for $root->eof().]
$root->eof()
This signals that you're finished parsing content into
this tree; this runs various kinds of crucial cleanup
on the tree. This is called for you when you call
$root->parse_file(...), but not when you call
$root->parse(...). So if you call $root->parse(...),
then you must call $root->eof() once you've finished feeding all the chunks to parse(...), and before you
actually start doing anything else with the tree in
$root.
$root->delete()
[An important method inherited from HTML::Element,
which see.]
$root->elementify()
This changes the class of the object in $root from
HTML::TreeBuilder to the class used for all the rest
of the elements in that tree (generally HTML::Ele
ment). Returns $root.
For most purposes, this is unnecessary, but if you
call this after (after!!) you've finished building a
tree, then it keeps you from accidentally trying to
call anything but HTML::Element methods on it. (I.e.,
if you accidentally call "$root->parse_file(...)" on
the already-complete and elementified tree, then
instead of charging ahead and wreaking havoc, it'll throw a fatal error -- since $root is now an object
just of class HTML::Element which has no "parse_file"
method.
Note that elementify currently deletes all the private
attributes of $root except for "_tag", "_parent",
"_content", "_pos", and "_implicit". If anyone
requests that I change this to leave in yet more pri
vate attributes, I might do so, in future versions.
@nodes = $root->guts()
$parent_for_nodes = $root->guts()
In list context (as in the first case), this method
returns the topmost non-implicit nodes in a tree.
This is useful when you're parsing HTML code that you
know doesn't expect an HTML document, but instead just
a fragment of an HTML document. For example, if you
wanted the parse tree for a file consisting of just
this:

<li>I like pie!
Then you would get that with "@nodes =
$root->guts();". It so happens that in this case,
@notes will contain just one element object, repre
senting the "li" node (with "I like pie!" being its
text child node). However, consider if you were pars
ing this:

<hr>Hooboy!<hr>
In that case, "$root->guts()" would return three
items: an element object for the first "hr", a text
string "Hooboy!", and another "hr" element object.
For cases where you want definitely one element (so
you can treat it as a "document fragment", roughly
speaking), call "guts()" in scalar context, as in
"$parent_for_nodes = $root->guts()". That works like
"guts()" in list context; in fact, "guts()" in list
context would have returned exactly one value, and if
it would have been an object (as opposed to a text
string), then that's what "guts" in scalar context
will return. Otherwise, if "guts()" in list context
would have returned no values at all, then "guts()" in
scalar context returns undef. In all other cases,
"guts()" in scalar context returns an implicit 'div'
element node, with children consisting of whatever
nodes "guts()" in list context would have returned.
Note that that may detach those nodes from $root's
tree.
@nodes = $root->disembowel()
$parent_for_nodes = $root->disembowel()
The "disembowel()" method works just like the "guts()"
method, except that disembowel definitively destroys
the tree above the nodes that are returned. Usually
when you want the guts from a tree, you're just going
to toss out the rest of the tree anyway, so this saves
you the bother. (Remember, "disembowel" means "remove
the guts from".)
$root->implicit_tags(value)
Setting this attribute to true will instruct the
parser to try to deduce implicit elements and implicit
end tags. If it is false you get a parse tree that
just reflects the text as it stands, which is unlikely
to be useful for anything but quick and dirty parsing.
(In fact, I'd be curious to hear from anyone who finds
it useful to have implicit_tags set to false.)
Default is true.
Implicit elements have the implicit() attribute set.
$root->implicit_body_p_tag(value)
This controls an aspect of implicit element behavior,
if implicit_tags is on: If a text element (PCDATA) or
a phrasal element (such as "<em>") is to be inserted
under "<body>", two things can happen: if
implicit_body_p_tag is true, it's placed under a new,
implicit "<p>" tag. (Past DTDs suggested this was the
only correct behavior, and this is how past versions
of this module behaved.) But if implicit_body_p_tag
is false, nothing is implicated -- the PCDATA or
phrasal element is simply placed under "<body>".
Default is false.
$root->ignore_unknown(value)
This attribute controls whether unknown tags should be
represented as elements in the parse tree, or whether
they should be ignored. Default is true (to ignore
unknown tags.)
$root->ignore_text(value)
Do not represent the text content of elements. This
saves space if all you want is to examine the struc
ture of the document. Default is false.
$root->ignore_ignorable_whitespace(value)
If set to true, TreeBuilder will try to avoid creating
ignorable whitespace text nodes in the tree. Default
is true. (In fact, I'd be interested in hearing if
there's ever a case where you need this off, or where
leaving it on leads to incorrect behavior.)
$root->no_space_compacting(value)
This determines whether TreeBuilder compacts all
whitespace strings in the document (well, outside of
PRE or TEXTAREA elements), or leaves them alone. Nor
mally (default, value of 0), each string of contiguous
whitespace in the document is turned into a single
space. But that's not done if no_space_compacting is
set to 1.
Setting no_space_compacting to 1 might be useful if
you want to read in a tree just to make some minor
changes to it before writing it back out.
This method is experimental. If you use it, be sure
to report any problems you might have with it.
$root->p_strict(value)
If set to true (and it defaults to false), TreeBuilder
will take a narrower than normal view of what can be
under a "p" element; if it sees a non-phrasal element
about to be inserted under a "p", it will close that
"p". Otherwise it will close p elements only for
other "p"'s, headings, and "form" (altho the latter
may be removed in future versions).
For example, when going thru this snippet of code,

<p>stuff
<ul>
TreeBuilder will normally (with "p_strict" false) put
the "ul" element under the "p" element. However, with
"p_strict" set to true, it will close the "p" first.
In theory, there should be strictness options like
this for other/all elements besides just "p"; but I
treat this as a specal case simply because of the fact
that "p" occurs so frequently and its end-tag is omit
ted so often; and also because application of strict
ness rules at parse-time across all elements often
makes tiny errors in HTML coding produce drastically
bad parse-trees, in my experience.
If you find that you wish you had an option like this
to enforce content-models on all elements, then I sug
gest that what you want is content-model checking as a
stage after TreeBuilder has finished parsing.
$root->store_comments(value)
This determines whether TreeBuilder will normally
store comments found while parsing content into $root.
Currently, this is off by default.
$root->store_declarations(value)
This determines whether TreeBuilder will normally
store markup declarations found while parsing content
into $root. Currently, this is off by default.
It is somewhat of a known bug (to be fixed one of
these days, if anyone needs it?) that declarations in
the preamble (before the "html" start-tag) end up
actually under the "html" element.
$root->store_pis(value)
This determines whether TreeBuilder will normally
store processing instructions found while parsing con
tent into $root -- assuming a recent version of
HTML::Parser (old versions won't parse PIs correctly).
Currently, this is off (false) by default.
It is somewhat of a known bug (to be fixed one of
these days, if anyone needs it?) that PIs in the
preamble (before the "html" start-tag) end up actually
under the "html" element.
$root->warn(value)
This determines whether syntax errors during parsing
should generate warnings, emitted via Perl's "warn"
function.
This is off (false) by default.

HTML AND ITS DISCONTENTS

HTML is rather harder to parse than people who write it
generally suspect.

Here's the problem: HTML is a kind of SGML that permits
"minimization" and "implication". In short, this means
that you don't have to close every tag you open (because
the opening of a subsequent tag may implicitly close it),
and if you use a tag that can't occur in the context you
seem to using it in, under certain conditions the parser
will be able to realize you mean to leave the current con
text and enter the new one, that being the only one that
your code could correctly be interpreted in.

Now, this would all work flawlessly and unproblematically
if: 1) all the rules that both prescribe and describe HTML
were (and had been) clearly set out, and 2) everyone was
aware of these rules and wrote their code in compliance to
them.

However, it didn't happen that way, and so most HTML pages
are difficult if not impossible to correctly parse with
nearly any set of straightforward SGML rules. That's why
the internals of HTML::TreeBuilder consist of lots and
lots of special cases -- instead of being just a generic
SGML parser with HTML DTD rules plugged in.

TRANSLATIONS?

The techniques that HTML::TreeBuilder uses to perform what
I consider very robust parses on everyday code are not
things that can work only in Perl. To date, the algo
rithms at the center of HTML::TreeBuilder have been imple
mented only in Perl, as far as I know; and I don't foresee
getting around to implementing them in any other language
any time soon.

If, however, anyone is looking for a semester project for
an applied programming class (or if they merely enjoy
extra-curricular masochism), they might do well to see about choosing as a topic the implementation/adaptation of
these routines to any other interesting programming lan
guage that you feel currently suffers from a lack of
robust HTML-parsing. I welcome correspondence on this
subject, and point out that one can learn a great deal
about languages by trying to translate between them, and
then comparing the result.

The HTML::TreeBuilder source may seem long and complex,
but it is rather well commented, and symbol names are gen
erally self-explanatory. (You are encouraged to read the
Mozilla HTML parser source for comparison.) Some of the
complexity comes from little-used features, and some of it
comes from having the HTML tokenizer (HTML::Parser) being
a separate module, requiring somewhat of a different
interface than you'd find in a combined tokenizer and
tree-builder. But most of the length of the source comes
from the fact that it's essentially a long list of special
cases, with lots and lots of sanity-checking, and sanityrecovery -- because, as Roseanne Rosannadanna once said,
"it's always something".

Users looking to compare several HTML parsers should look
at the source for Raggett's Tidy ("<http://www.w3.org/Peo
ple/Raggett/tidy/>"), Mozilla
("<http://www.mozilla.org/>"), and possibly root around
the browsers section of Yahoo to find the various opensource ones ("<http://dir.yahoo.com/Computers_and_Inter
net/Software/Internet/World_Wide_Web/Browsers/>").

BUGS

* Framesets seem to work correctly now. Email me if you
get a strange parse from a document with framesets.

* Really bad HTML code will, often as not, make for a
somewhat objectionable parse tree. Regrettable, but
unavoidably true.

* If you're running with implicit_tags off (God help
you!), consider that $tree->content_list probably contains
the tree or grove from the parse, and not $tree itself
(which will, oddly enough, be an implicit 'html' element).
This seems counter-intuitive and problematic; but seeing
as how almost no HTML ever parses correctly with
implicit_tags off, this interface oddity seems the least
of your problems.

BUG REPORTS

When a document parses in a way different from how you
think it should, I ask that you report this to me as a
bug. The first thing you should do is copy the document,
trim out as much of it as you can while still producing
the bug in question, and then email me that mini-document
and the code you're using to parse it, at
"sburke@cpan.org". Include a note as to how it parses
(presumably including its $tree->dump output), and then a
careful and clear explanation of where you think the parser is going astray, and how you would prefer that it
work instead.

SEE ALSO

HTML::Tree; HTML::Parser, HTML::Element, HTML::Tagset

HTML::DOMbo

COPYRIGHT

Copyright 1995-1998 Gisle Aas; copyright 1999-2002 Sean M.
Burke. This library is free software; you can redis
tribute it and/or modify it under the same terms as Perl
itself.

This program is distributed in the hope that it will be
useful, but without any warranty; without even the implied
warranty of merchantability or fitness for a particular
purpose.

AUTHOR

Original author Gisle Aas <gisle@aas.no>; current main
tainer Sean M. Burke, <sburke@cpan.org>
Copyright © 2010-2025 Platon Technologies, s.r.o.           Home | Man pages | tLDP | Documents | Utilities | About
Design by styleshout