%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /usr/local/share/man/man3/
Upload File :
Create Path :
Current File : //usr/local/share/man/man3/HTML::Element::traverse.3pm

.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings.  \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
.    ds -- \(*W-
.    ds PI pi
.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
.    ds L" ""
.    ds R" ""
.    ds C` ""
.    ds C' ""
'br\}
.el\{\
.    ds -- \|\(em\|
.    ds PI \(*p
.    ds L" ``
.    ds R" ''
.    ds C`
.    ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.\"
.\" If the F register is turned on, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD.  Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{
.    if \nF \{
.        de IX
.        tm Index:\\$1\t\\n%\t"\\$2"
..
.        if !\nF==2 \{
.            nr % 0
.            nr F 2
.        \}
.    \}
.\}
.rr rF
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
.    \" fudge factors for nroff and troff
.if n \{\
.    ds #H 0
.    ds #V .8m
.    ds #F .3m
.    ds #[ \f1
.    ds #] \fP
.\}
.if t \{\
.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
.    ds #V .6m
.    ds #F 0
.    ds #[ \&
.    ds #] \&
.\}
.    \" simple accents for nroff and troff
.if n \{\
.    ds ' \&
.    ds ` \&
.    ds ^ \&
.    ds , \&
.    ds ~ ~
.    ds /
.\}
.if t \{\
.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
.\}
.    \" troff and (daisy-wheel) nroff accents
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
.ds ae a\h'-(\w'a'u*4/10)'e
.ds Ae A\h'-(\w'A'u*4/10)'E
.    \" corrections for vroff
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
.    \" for low resolution devices (crt and lpr)
.if \n(.H>23 .if \n(.V>19 \
\{\
.    ds : e
.    ds 8 ss
.    ds o a
.    ds d- d\h'-1'\(ga
.    ds D- D\h'-1'\(hy
.    ds th \o'bp'
.    ds Th \o'LP'
.    ds ae ae
.    ds Ae AE
.\}
.rm #[ #] #H #V #F C
.\" ========================================================================
.\"
.IX Title "HTML::Element::traverse 3"
.TH HTML::Element::traverse 3 "2019-12-18" "perl v5.16.3" "User Contributed Perl Documentation"
.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH "NAME"
HTML::Element::traverse \- discussion of HTML::Element's traverse method
.SH "VERSION"
.IX Header "VERSION"
This document describes version 5.07 of
HTML::Element::traverse, released August 31, 2017
as part of HTML-Tree.
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
.Vb 2
\&  # $element\->traverse is unnecessary and obscure.
\&  #   Don\*(Aqt use it in new code.
.Ve
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
\&\f(CW\*(C`HTML::Element\*(C'\fR provides a method \f(CW\*(C`traverse\*(C'\fR that traverses the tree
and calls user-specified callbacks for each node, in pre\- or
post-order.  However, use of the method is quite superfluous: if you
want to recursively visit every node in the tree, it's almost always
simpler to write a subroutine does just that, than it is to bundle up
the pre\- and/or post-order code in callbacks for the \f(CW\*(C`traverse\*(C'\fR
method.
.SH "EXAMPLES"
.IX Header "EXAMPLES"
Suppose you want to traverse at/under a node \f(CW$tree\fR and give elements
an 'id' attribute unless they already have one.
.PP
You can use the \f(CW\*(C`traverse\*(C'\fR method:
.PP
.Vb 10
\&  {
\&    my $counter = \*(Aqx0000\*(Aq;
\&    $start_node\->traverse(
\&      [ # Callbacks;
\&        # pre\-order callback:
\&        sub {
\&          my $x = $_[0];
\&          $x\->attr(\*(Aqid\*(Aq, $counter++) unless defined $x\->attr(\*(Aqid\*(Aq);
\&          return HTML::Element::OK; # keep traversing
\&        },
\&        # post\-order callback:
\&        undef
\&      ],
\&      1, # don\*(Aqt call the callbacks for text nodes
\&    );
\&  }
.Ve
.PP
or you can just be simple and clear (and not have to understand the
calling format for \f(CW\*(C`traverse\*(C'\fR) by writing a sub that traverses the
tree by just calling itself:
.PP
.Vb 11
\&  {
\&    my $counter = \*(Aqx0000\*(Aq;
\&    sub give_id {
\&      my $x = $_[0];
\&      $x\->attr(\*(Aqid\*(Aq, $counter++) unless defined $x\->attr(\*(Aqid\*(Aq);
\&      foreach my $c ($x\->content_list) {
\&        give_id($c) if ref $c; # ignore text nodes
\&      }
\&    };
\&    give_id($start_node);
\&  }
.Ve
.PP
See, isn't that nice and clear?
.PP
But, if you really need to know:
.SH "THE TRAVERSE METHOD"
.IX Header "THE TRAVERSE METHOD"
The \f(CW\*(C`traverse()\*(C'\fR method is a general object-method for traversing a
tree or subtree and calling user-specified callbacks.  It accepts the
following syntaxes:
.ie n .IP "$h\->traverse(\e&callback)" 4
.el .IP "\f(CW$h\fR\->traverse(\e&callback)" 4
.IX Item "$h->traverse(&callback)"
.PD 0
.ie n .IP "or $h\->traverse(\e&callback, $ignore_text)" 4
.el .IP "or \f(CW$h\fR\->traverse(\e&callback, \f(CW$ignore_text\fR)" 4
.IX Item "or $h->traverse(&callback, $ignore_text)"
.ie n .IP "or $h\->traverse( [\e&pre_callback,\e&post_callback] , $ignore_text)" 4
.el .IP "or \f(CW$h\fR\->traverse( [\e&pre_callback,\e&post_callback] , \f(CW$ignore_text\fR)" 4
.IX Item "or $h->traverse( [&pre_callback,&post_callback] , $ignore_text)"
.PD
.PP
These all mean to traverse the element and all of its children.  That
is, this method starts at node \f(CW$h\fR, \*(L"pre-order visits\*(R" \f(CW$h\fR, traverses its
children, and then will \*(L"post-order visit\*(R" \f(CW$h\fR.  \*(L"Visiting\*(R" means that
the callback routine is called, with these arguments:
.PP
.Vb 3
\&    $_[0] : the node (element or text segment),
\&    $_[1] : a startflag, and
\&    $_[2] : the depth
.Ve
.PP
If the \f(CW$ignore_text\fR parameter is given and true, then the pre-order
call \fIwill not\fR be happen for text content.
.PP
The startflag is 1 when we enter a node (i.e., in pre-order calls) and
0 when we leave the node (in post-order calls).
.PP
Note, however, that post-order calls don't happen for nodes that are
text segments or are elements that are prototypically empty (like \*(L"br\*(R",
\&\*(L"hr\*(R", etc.).
.PP
If we visit text nodes (i.e., unless \f(CW$ignore_text\fR is given and true),
then when text nodes are visited, we will also pass two extra
arguments to the callback:
.PP
.Vb 4
\&    $_[3] : the element that\*(Aqs the parent
\&             of this text node
\&    $_[4] : the index of this text node
\&             in its parent\*(Aqs content list
.Ve
.PP
Note that you can specify that the pre-order routine can
be a different routine from the post-order one:
.PP
.Vb 1
\&    $h\->traverse( [\e&pre_callback,\e&post_callback], ...);
.Ve
.PP
You can also specify that no post-order calls are to be made,
by providing a false value as the post-order routine:
.PP
.Vb 1
\&    $h\->traverse([ \e&pre_callback,0 ], ...);
.Ve
.PP
And similarly for suppressing pre-order callbacks:
.PP
.Vb 1
\&    $h\->traverse([ 0,\e&post_callback ], ...);
.Ve
.PP
Note that these two syntaxes specify the same operation:
.PP
.Vb 2
\&    $h\->traverse([\e&foo,\e&foo], ...);
\&    $h\->traverse( \e&foo       , ...);
.Ve
.PP
The return values from calls to your pre\- or post-order
routines are significant, and are used to control recursion
into the tree.
.PP
These are the values you can return, listed in descending order
of my estimation of their usefulness:
.IP "HTML::Element::OK, 1, or any other true value" 4
.IX Item "HTML::Element::OK, 1, or any other true value"
\&...to keep on traversing.
.Sp
Note that \f(CW\*(C`HTML::Element::OK\*(C'\fR et
al are constants.  So if you're running under \f(CW\*(C`use strict\*(C'\fR
(as I hope you are), and you say:
\&\f(CW\*(C`return HTML::Element::PRUEN\*(C'\fR
the compiler will flag this as an error (an unallowable
bareword, specifically), whereas if you spell \s-1PRUNE\s0 correctly,
the compiler will not complain.
.IP "undef, 0, '0', '', or HTML::Element::PRUNE" 4
.IX Item "undef, 0, '0', '', or HTML::Element::PRUNE"
\&...to block traversing under the current element's content.
(This is ignored if received from a post-order callback,
since by then the recursion has already happened.)
If this is returned by a pre-order callback, no
post-order callback for the current node will happen.
(Recall that if your callback exits with just \f(CW\*(C`return;\*(C'\fR,
it is returning undef \*(-- at least in scalar context, and
\&\f(CW\*(C`traverse\*(C'\fR always calls your callbacks in scalar context.)
.IP "HTML::Element::ABORT" 4
.IX Item "HTML::Element::ABORT"
\&...to abort the whole traversal immediately.
This is often useful when you're looking for just the first
node in the tree that meets some criterion of yours.
.IP "HTML::Element::PRUNE_UP" 4
.IX Item "HTML::Element::PRUNE_UP"
\&...to abort continued traversal into this node and its parent
node.  No post-order callback for the current or parent
node will happen.
.IP "HTML::Element::PRUNE_SOFTLY" 4
.IX Item "HTML::Element::PRUNE_SOFTLY"
Like \s-1PRUNE,\s0 except that the post-order call for the current
node is not blocked.
.PP
Almost every task to do with extracting information from a tree can be
expressed in terms of traverse operations (usually in only one pass,
and usually paying attention to only pre-order, or to only
post-order), or operations based on traversing. (In fact, many of the
other methods in this class are basically calls to \fItraverse()\fR with
particular arguments.)
.PP
The source code for HTML::Element and HTML::TreeBuilder contain
several examples of the use of the \*(L"traverse\*(R" method to gather
information about the content of trees and subtrees.
.PP
(Note: you should not change the structure of a tree \fIwhile\fR you are
traversing it.)
.PP
[End of documentation for the \f(CW\*(C`traverse()\*(C'\fR method]
.SS "Traversing with Recursive Anonymous Routines"
.IX Subsection "Traversing with Recursive Anonymous Routines"
Now, if you've been reading
\&\fIStructure and Interpretation of Computer Programs\fR too much, maybe
you even want a recursive lambda.  Go ahead:
.PP
.Vb 10
\&  {
\&    my $counter = \*(Aqx0000\*(Aq;
\&    my $give_id;
\&    $give_id = sub {
\&      my $x = $_[0];
\&      $x\->attr(\*(Aqid\*(Aq, $counter++) unless defined $x\->attr(\*(Aqid\*(Aq);
\&      foreach my $c ($x\->content_list) {
\&        $give_id\->($c) if ref $c; # ignore text nodes
\&      }
\&    };
\&    $give_id\->($start_node);
\&    undef $give_id;
\&  }
.Ve
.PP
It's a bit nutty, and it's \fIstill\fR more concise than a call to the
\&\f(CW\*(C`traverse\*(C'\fR method!
.PP
It is left as an exercise to the reader to figure out how to do the
same thing without using a \f(CW$give_id\fR symbol at all.
.PP
It is also left as an exercise to the reader to figure out why I
undefine \f(CW$give_id\fR, above; and why I could achieved the same effect
with any of:
.PP
.Vb 5
\&    $give_id = \*(AqI like pie!\*(Aq;
\&   # or...
\&    $give_id = [];
\&   # or even;
\&    $give_id = sub { print "Mmmm pie!\en" };
.Ve
.PP
But not:
.PP
.Vb 5
\&    $give_id = sub { print "I\*(Aqm $give_id and I like pie!\en" };
\&   # nor...
\&    $give_id = \e$give_id;
\&   # nor...
\&    $give_id = { \*(Aqpie\*(Aq => \e$give_id, \*(Aqmode\*(Aq => \*(Aqa la\*(Aq };
.Ve
.SS "Doing Recursive Things Iteratively"
.IX Subsection "Doing Recursive Things Iteratively"
Note that you may at times see an iterative implementation of
pre-order traversal, like so:
.PP
.Vb 4
\&   {
\&     my @to_do = ($tree); # start\-node
\&     while(@to_do) {
\&       my $this = shift @to_do;
\&
\&       # "Visit" the node:
\&       $this\->attr(\*(Aqid\*(Aq, $counter++)
\&        unless defined $this\->attr(\*(Aqid\*(Aq);
\&
\&       unshift @to_do, grep ref $_, $this\->content_list;
\&        # Put children on the stack \-\- they\*(Aqll be visited next
\&     }
\&   }
.Ve
.PP
This can \fIunder certain circumstances\fR be more efficient than just a
normal recursive routine, but at the cost of being rather obscure.  It
gains efficiency by avoiding the overhead of function-calling, but
since there are several method dispatches however you do it (to
\&\f(CW\*(C`attr\*(C'\fR and \f(CW\*(C`content_list\*(C'\fR), the overhead for a simple function call
is insignificant.
.SS "Pruning and Whatnot"
.IX Subsection "Pruning and Whatnot"
The \f(CW\*(C`traverse\*(C'\fR method does have the fairly neat features of
the \f(CW\*(C`ABORT\*(C'\fR, \f(CW\*(C`PRUNE_UP\*(C'\fR and \f(CW\*(C`PRUNE_SOFTLY\*(C'\fR signals.  None of these
can be implemented \fItotally\fR straightforwardly with recursive
routines, but it is quite possible.  \f(CW\*(C`ABORT\*(C'\fR\-like behavior can be
implemented either with using non-local returning with \f(CW\*(C`eval\*(C'\fR/\f(CW\*(C`die\*(C'\fR:
.PP
.Vb 10
\&  my $died_on; # if you need to know where...
\&  sub thing {
\&    ... visits $_[0]...
\&    ... maybe set $died_on to $_[0] and die "ABORT_TRAV" ...
\&    ... else call thing($child) for each child...
\&    ...any post\-order visiting $_[0]...
\&  }
\&  eval { thing($node) };
\&  if($@) {
\&    if($@ =~ m<^ABORT_TRAV>) {
\&      ...it died (aborted) on $died_on...
\&    } else {
\&      die $@; # some REAL error happened
\&    }
\&  }
.Ve
.PP
or you can just do it with flags:
.PP
.Vb 11
\&  my($abort_flag, $died_on);
\&  sub thing {
\&    ... visits $_[0]...
\&    ... maybe set $abort_flag = 1; $died_on = $_[0]; return;
\&    foreach my $c ($_[0]\->content_list) {
\&      thing($c);
\&      return if $abort_flag;
\&    }
\&    ...any post\-order visiting $_[0]...
\&    return;
\&  }
\&
\&  $abort_flag = $died_on = undef;
\&  thing($node);
\&  ...if defined $abort_flag, it died on $died_on
.Ve
.SH "SEE ALSO"
.IX Header "SEE ALSO"
HTML::Element
.SH "AUTHOR"
.IX Header "AUTHOR"
Current maintainers:
.IP "\(bu" 4
Christopher J. Madsen \f(CW\*(C`<perl\ AT\ cjmweb.net>\*(C'\fR
.IP "\(bu" 4
Jeff Fearn \f(CW\*(C`<jfearn\ AT\ cpan.org>\*(C'\fR
.PP
Original HTML-Tree author:
.IP "\(bu" 4
Gisle Aas
.PP
Former maintainers:
.IP "\(bu" 4
Sean M. Burke
.IP "\(bu" 4
Andy Lester
.IP "\(bu" 4
Pete Krawczyk \f(CW\*(C`<petek\ AT\ cpan.org>\*(C'\fR
.PP
You can follow or contribute to HTML-Tree's development at
<https://github.com/kentfredric/HTML\-Tree>.
.SH "COPYRIGHT"
.IX Header "COPYRIGHT"
Copyright 2000,2001 Sean M. Burke

Zerion Mini Shell 1.0