in reply to Re: Truncating an HTML node using XPaths in HTML::TreeBuilder::XPath
in thread Truncating an HTML node using XPaths in HTML::TreeBuilder::XPath

Ok, but foo01, foo02, and foo03 are content, not elements. Thus they cannot be siblings to the <br /> element. That mix and match of types (?) prevents the sibling search from being the solution here. I'm still trying a lot of things but want to stay as much as I can with the objects created by and manipulated through HTML::Element.

Replies are listed 'Best First'.
Re^3: Truncating an HTML node using XPaths in HTML::TreeBuilder::XPath
by poj (Abbot) on Sep 27, 2019 at 16:09 UTC

    Try

    for my $d ($root->findnodes($xpath)) { my @line = $d->content_list; s/^\s+|\s+$//g for @line; printf "%s\n",$line[0]; }
    poj

      Neat. That's close but takes the first part of the node, and only the first part of the node, not necessarily all of the pieces preceeding a <br /> element. Consider foo2a in the following example.

      #!/usr/bin/perl use HTML::TreeBuilder::XPath; use strict; use warnings; my $root = HTML::TreeBuilder::XPath->new; $root->parse_file(\*DATA) or die("Could not parse the data: $!\n"); $root->eof(); my $xpath = '//div/p'; for my $d ($root->findnodes($xpath)) { my @line = $d->content_list; s/^\s+|\s+$//g for @line; $d->replace_with($line[0],qq(\n)); } print $root->as_trimmed_text,qq(\n); $root->delete; exit(0); __DATA__ <div><p>foo00 bar00</p></div> <div><p>foo01<br />bar01</p></div> <div> <p> foo02 <br /> bar02 </p> </div> <div> <p> <a href="foobar01">foobar02</a> foo02a <br /> bar02a </p> </div> <div> <p> foo03 <br /> bar03 <br /> baz03 </p> </div> <div> <p> <em>foo04</em> <br /> <strong>bar04</strong> <br /> <em>baz04</em> </p> </div> <div> <p> <em>foo05</em> </p> <p>bar05 <br /> <em>baz05</em> </p> </div>

      I am trying many experiments with $d->content_list. I suppose it would be possible to extract the node as a hash and then loop through it eliminating the <br /> element and everything after it.

        You can test each item in content_list to see if it is a <br> tag:
        for my $d ($root->findnodes($xpath)) { my @line = $d->content_list; my @truncated; for my $line (@line) { if (ref $line) { last if $line->tag eq 'br'; } push(@truncated,$line); } $d->replace_with(@truncated); }
Re^3: Truncating an HTML node using XPaths in HTML::TreeBuilder::XPath ( pindex splice_content content_array_ref )
by Anonymous Monk on Sep 29, 2019 at 03:55 UTC

    A tip for tips is to look around a tip, both above and below :)

    #!/usr/bin/perl -- use strict; use warnings; use HTML::TreeBuilder::XPath; my $tree= HTML::TreeBuilder::XPath->new_from_content(<<'HTML'); <body> <div><p>foo01<br />bar01</p></div> <div> <p> foo02 <br /> bar02 </p> </div> <div> <p> foo03 <br /> bar03 <br / baz03 </p> </div> HTML # $tree->dump; print $tree->as_HTML( '><&' => " " ), "\n";; for my $br ( $tree->findnodes( '//div/p/br[1]' ) ){ $br->parent->splice_content( $br->pindex, int@{ $br->parent->content_array_ref } ); } # $tree->dump; print $tree->as_HTML( '><&' => " " ), "\n";; __END__ <html> <head> </head> <body> <div> <p>foo01<br />bar01</div> <div> <p> foo02 <br /> bar02 </div> <div> <p> foo03 <br /> bar03 <br </p="&lt;/p" baz03="baz03" /> </div> </body> </html> <html> <head> </head> <body> <div> <p>foo01</div> <div> <p> foo02 </div> <div> <p> foo03 </div> </body> </html>