{
    "content": [
        {
            "type": "text",
            "text": "# HTML::Element::traverse (perldoc)\n\n## NAME\n\nHTML::Element::traverse - discussion of HTML::Element's traverse method\n\n## SYNOPSIS\n\n# $element->traverse is unnecessary and obscure.\n#   Don't use it in new code.\n\n## DESCRIPTION\n\n\"HTML::Element\" provides a method \"traverse\" that traverses the tree and calls user-specified\ncallbacks for each node, in pre- or post-order. However, use of the method is quite superfluous:\nif you want to recursively visit every node in the tree, it's almost always simpler to write a\nsubroutine does just that, than it is to bundle up the pre- and/or post-order code in callbacks\nfor the \"traverse\" method.\n\n## Sections\n\n- **NAME**\n- **VERSION**\n- **SYNOPSIS**\n- **DESCRIPTION**\n- **EXAMPLES**\n- **THE TRAVERSE METHOD** (3 subsections)\n- **SEE ALSO**\n- **AUTHOR**\n- **COPYRIGHT**\n\nUse structuredContent.sections for detailed options, examples, and full documentation.\n"
        }
    ],
    "structuredContent": {
        "command": "HTML::Element::traverse",
        "section": "",
        "mode": "perldoc",
        "summary": "HTML::Element::traverse - discussion of HTML::Element's traverse method",
        "synopsis": "# $element->traverse is unnecessary and obscure.\n#   Don't use it in new code.",
        "tldr_summary": null,
        "tldr_examples": [],
        "tldr_source": null,
        "flags": [],
        "examples": [
            "Suppose you want to traverse at/under a node $tree and give elements an 'id' attribute unless",
            "they already have one.",
            "You can use the \"traverse\" method:",
            "my $counter = 'x0000';",
            "$startnode->traverse(",
            "[ # Callbacks;",
            "# pre-order callback:",
            "sub {",
            "my $x = $[0];",
            "$x->attr('id', $counter++) unless defined $x->attr('id');",
            "return HTML::Element::OK; # keep traversing",
            "},",
            "# post-order callback:",
            "undef",
            "],",
            "1, # don't call the callbacks for text nodes",
            ");",
            "or you can just be simple and clear (and not have to understand the calling format for",
            "\"traverse\") by writing a sub that traverses the tree by just calling itself:",
            "my $counter = 'x0000';",
            "sub giveid {",
            "my $x = $[0];",
            "$x->attr('id', $counter++) unless defined $x->attr('id');",
            "foreach my $c ($x->contentlist) {",
            "giveid($c) if ref $c; # ignore text nodes",
            "};",
            "giveid($startnode);",
            "See, isn't that nice and clear?",
            "But, if you really need to know:"
        ],
        "see_also": [],
        "section_outline": [
            {
                "name": "NAME",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "VERSION",
                "lines": 3,
                "subsections": []
            },
            {
                "name": "SYNOPSIS",
                "lines": 3,
                "subsections": []
            },
            {
                "name": "DESCRIPTION",
                "lines": 6,
                "subsections": []
            },
            {
                "name": "EXAMPLES",
                "lines": 41,
                "subsections": []
            },
            {
                "name": "THE TRAVERSE METHOD",
                "lines": 95,
                "subsections": [
                    {
                        "name": "Traversing with Recursive Anonymous Routines",
                        "lines": 39
                    },
                    {
                        "name": "Doing Recursive Things Iteratively",
                        "lines": 21
                    },
                    {
                        "name": "Pruning and Whatnot",
                        "lines": 39
                    }
                ]
            },
            {
                "name": "SEE ALSO",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "AUTHOR",
                "lines": 21,
                "subsections": []
            },
            {
                "name": "COPYRIGHT",
                "lines": 2,
                "subsections": []
            }
        ],
        "sections": {
            "NAME": {
                "content": "HTML::Element::traverse - discussion of HTML::Element's traverse method\n",
                "subsections": []
            },
            "VERSION": {
                "content": "This document describes version 5.07 of HTML::Element::traverse, released August 31, 2017 as\npart of HTML-Tree.\n",
                "subsections": []
            },
            "SYNOPSIS": {
                "content": "# $element->traverse is unnecessary and obscure.\n#   Don't use it in new code.\n",
                "subsections": []
            },
            "DESCRIPTION": {
                "content": "\"HTML::Element\" provides a method \"traverse\" that traverses the tree and calls user-specified\ncallbacks for each node, in pre- or post-order. However, use of the method is quite superfluous:\nif you want to recursively visit every node in the tree, it's almost always simpler to write a\nsubroutine does just that, than it is to bundle up the pre- and/or post-order code in callbacks\nfor the \"traverse\" method.\n",
                "subsections": []
            },
            "EXAMPLES": {
                "content": "Suppose you want to traverse at/under a node $tree and give elements an 'id' attribute unless\nthey already have one.\n\nYou can use the \"traverse\" method:\n\n{\nmy $counter = 'x0000';\n$startnode->traverse(\n[ # Callbacks;\n# pre-order callback:\nsub {\nmy $x = $[0];\n$x->attr('id', $counter++) unless defined $x->attr('id');\nreturn HTML::Element::OK; # keep traversing\n},\n# post-order callback:\nundef\n],\n1, # don't call the callbacks for text nodes\n);\n}\n\nor you can just be simple and clear (and not have to understand the calling format for\n\"traverse\") by writing a sub that traverses the tree by just calling itself:\n\n{\nmy $counter = 'x0000';\nsub giveid {\nmy $x = $[0];\n$x->attr('id', $counter++) unless defined $x->attr('id');\nforeach my $c ($x->contentlist) {\ngiveid($c) if ref $c; # ignore text nodes\n}\n};\ngiveid($startnode);\n}\n\nSee, isn't that nice and clear?\n\nBut, if you really need to know:\n",
                "subsections": []
            },
            "THE TRAVERSE METHOD": {
                "content": "The \"traverse()\" method is a general object-method for traversing a tree or subtree and calling\nuser-specified callbacks. It accepts the following syntaxes:\n\n$h->traverse(\\&callback)\nor $h->traverse(\\&callback, $ignoretext)\nor $h->traverse( [\\&precallback,\\&postcallback] , $ignoretext)\n\nThese all mean to traverse the element and all of its children. That is, this method starts at\nnode $h, \"pre-order visits\" $h, traverses its children, and then will \"post-order visit\" $h.\n\"Visiting\" means that the callback routine is called, with these arguments:\n\n$[0] : the node (element or text segment),\n$[1] : a startflag, and\n$[2] : the depth\n\nIf the $ignoretext parameter is given and true, then the pre-order call *will not* be happen\nfor text content.\n\nThe startflag is 1 when we enter a node (i.e., in pre-order calls) and 0 when we leave the node\n(in post-order calls).\n\nNote, however, that post-order calls don't happen for nodes that are text segments or are\nelements that are prototypically empty (like \"br\", \"hr\", etc.).\n\nIf we visit text nodes (i.e., unless $ignoretext is given and true), then when text nodes are\nvisited, we will also pass two extra arguments to the callback:\n\n$[3] : the element that's the parent\nof this text node\n$[4] : the index of this text node\nin its parent's content list\n\nNote that you can specify that the pre-order routine can be a different routine from the\npost-order one:\n\n$h->traverse( [\\&precallback,\\&postcallback], ...);\n\nYou can also specify that no post-order calls are to be made, by providing a false value as the\npost-order routine:\n\n$h->traverse([ \\&precallback,0 ], ...);\n\nAnd similarly for suppressing pre-order callbacks:\n\n$h->traverse([ 0,\\&postcallback ], ...);\n\nNote that these two syntaxes specify the same operation:\n\n$h->traverse([\\&foo,\\&foo], ...);\n$h->traverse( \\&foo       , ...);\n\nThe return values from calls to your pre- or post-order routines are significant, and are used\nto control recursion into the tree.\n\nThese are the values you can return, listed in descending order of my estimation of their\nusefulness:\n\nHTML::Element::OK, 1, or any other true value\n...to keep on traversing.\n\nNote that \"HTML::Element::OK\" et al are constants. So if you're running under \"use strict\"\n(as I hope you are), and you say: \"return HTML::Element::PRUEN\" the compiler will flag this\nas an error (an unallowable bareword, specifically), whereas if you spell PRUNE correctly,\nthe compiler will not complain.\n\nundef, 0, '0', '', or HTML::Element::PRUNE\n...to block traversing under the current element's content. (This is ignored if received\nfrom a post-order callback, since by then the recursion has already happened.) If this is\nreturned by a pre-order callback, no post-order callback for the current node will happen.\n(Recall that if your callback exits with just \"return;\", it is returning undef -- at least\nin scalar context, and \"traverse\" always calls your callbacks in scalar context.)\n\nHTML::Element::ABORT\n...to abort the whole traversal immediately. This is often useful when you're looking for\njust the first node in the tree that meets some criterion of yours.\n\nHTML::Element::PRUNEUP\n...to abort continued traversal into this node and its parent node. No post-order callback\nfor the current or parent node will happen.\n\nHTML::Element::PRUNESOFTLY\nLike PRUNE, except that the post-order call for the current node is not blocked.\n\nAlmost every task to do with extracting information from a tree can be expressed in terms of\ntraverse operations (usually in only one pass, and usually paying attention to only pre-order,\nor to only post-order), or operations based on traversing. (In fact, many of the other methods\nin this class are basically calls to traverse() with particular arguments.)\n\nThe source code for HTML::Element and HTML::TreeBuilder contain several examples of the use of\nthe \"traverse\" method to gather information about the content of trees and subtrees.\n\n(Note: you should not change the structure of a tree *while* you are traversing it.)\n\n[End of documentation for the \"traverse()\" method]\n",
                "subsections": [
                    {
                        "name": "Traversing with Recursive Anonymous Routines",
                        "content": "Now, if you've been reading *Structure and Interpretation of Computer Programs* too much, maybe\nyou even want a recursive lambda. Go ahead:\n\n{\nmy $counter = 'x0000';\nmy $giveid;\n$giveid = sub {\nmy $x = $[0];\n$x->attr('id', $counter++) unless defined $x->attr('id');\nforeach my $c ($x->contentlist) {\n$giveid->($c) if ref $c; # ignore text nodes\n}\n};\n$giveid->($startnode);\nundef $giveid;\n}\n\nIt's a bit nutty, and it's *still* more concise than a call to the \"traverse\" method!\n\nIt is left as an exercise to the reader to figure out how to do the same thing without using a\n$giveid symbol at all.\n\nIt is also left as an exercise to the reader to figure out why I undefine $giveid, above; and\nwhy I could achieved the same effect with any of:\n\n$giveid = 'I like pie!';\n# or...\n$giveid = [];\n# or even;\n$giveid = sub { print \"Mmmm pie!\\n\" };\n\nBut not:\n\n$giveid = sub { print \"I'm $giveid and I like pie!\\n\" };\n# nor...\n$giveid = \\$giveid;\n# nor...\n$giveid = { 'pie' => \\$giveid, 'mode' => 'a la' };\n"
                    },
                    {
                        "name": "Doing Recursive Things Iteratively",
                        "content": "Note that you may at times see an iterative implementation of pre-order traversal, like so:\n\n{\nmy @todo = ($tree); # start-node\nwhile(@todo) {\nmy $this = shift @todo;\n\n# \"Visit\" the node:\n$this->attr('id', $counter++)\nunless defined $this->attr('id');\n\nunshift @todo, grep ref $, $this->contentlist;\n# Put children on the stack -- they'll be visited next\n}\n}\n\nThis can *under certain circumstances* be more efficient than just a normal recursive routine,\nbut at the cost of being rather obscure. It gains efficiency by avoiding the overhead of\nfunction-calling, but since there are several method dispatches however you do it (to \"attr\" and\n\"contentlist\"), the overhead for a simple function call is insignificant.\n"
                    },
                    {
                        "name": "Pruning and Whatnot",
                        "content": "The \"traverse\" method does have the fairly neat features of the \"ABORT\", \"PRUNEUP\" and\n\"PRUNESOFTLY\" signals. None of these can be implemented *totally* straightforwardly with\nrecursive routines, but it is quite possible. \"ABORT\"-like behavior can be implemented either\nwith using non-local returning with \"eval\"/\"die\":\n\nmy $diedon; # if you need to know where...\nsub thing {\n... visits $[0]...\n... maybe set $diedon to $[0] and die \"ABORTTRAV\" ...\n... else call thing($child) for each child...\n...any post-order visiting $[0]...\n}\neval { thing($node) };\nif($@) {\nif($@ =~ m<^ABORTTRAV>) {\n...it died (aborted) on $diedon...\n} else {\ndie $@; # some REAL error happened\n}\n}\n\nor you can just do it with flags:\n\nmy($abortflag, $diedon);\nsub thing {\n... visits $[0]...\n... maybe set $abortflag = 1; $diedon = $[0]; return;\nforeach my $c ($[0]->contentlist) {\nthing($c);\nreturn if $abortflag;\n}\n...any post-order visiting $[0]...\nreturn;\n}\n\n$abortflag = $diedon = undef;\nthing($node);\n...if defined $abortflag, it died on $diedon\n"
                    }
                ]
            },
            "SEE ALSO": {
                "content": "HTML::Element\n",
                "subsections": []
            },
            "AUTHOR": {
                "content": "Current maintainers:\n\n*   Christopher J. Madsen \"<perl AT cjmweb.net>\"\n\n*   Jeff Fearn \"<jfearn AT cpan.org>\"\n\nOriginal HTML-Tree author:\n\n*   Gisle Aas\n\nFormer maintainers:\n\n*   Sean M. Burke\n\n*   Andy Lester\n\n*   Pete Krawczyk \"<petek AT cpan.org>\"\n\nYou can follow or contribute to HTML-Tree's development at\n<https://github.com/kentfredric/HTML-Tree>.\n",
                "subsections": []
            },
            "COPYRIGHT": {
                "content": "Copyright 2000,2001 Sean M. Burke\n",
                "subsections": []
            }
        }
    }
}