in reply to processing text nodes using HTML::Element

You need to look at the '~literal' pseudo-element of HTML::Element.

If I understand your requirements correctly, the following code should do what you want.

#!/usr/bin/perl use warnings; use strict; my $html = <<'EOHTML'; <html> <body> <p>The relationship can be expressed by the following equation:<br> <blockquote> y &lt;= (7x<sup>3</sup> + 3x<sup>2</sup>)/((x - 3)(x - 5) </blockquote> <p>Of course x != 3 &amp; x != 5 -- That goes without saying. </body> </html> EOHTML use HTML::TreeBuilder; my $tree = HTML::TreeBuilder->new_from_content($html); # Look for double-dashes in the text, # and change them to &mdash;es. $tree->look_down(sub { my $element = shift; my @content = $element->content_list(); @content = map { if(ref) { $_ # Skip non-text children } else { # Break up the text child into pieces on the --'s my @texts = split /(--)/, $_; # Replaces those --'s with a ~literal # pseudo-element containing an &mdash; @texts = map { $_ eq '--' ? HTML::Element->new('~literal', text => '&mdash;') : $_ } @texts; @texts; } } @content; # Replace the old content with the modified content $element->splice_content(0, scalar $element->content_list, @content) +; return 0; }); print $tree->as_HTML;

Update: The (formatted) output of the above is this:

<html> <head> </head> <body> <p>The relationship can be expressed by the following equation:<br> <blockquote> y &lt;= (7x<sup>3</sup> + 3x<sup>2</sup>)/((x - 3)(x - 5) </blockquote> <p>Of course x != 3 &amp; x != 5 &mdash; That goes without saying. </body> </html>

bbfu
Black flowers blossum
Fearless on my breath

Replies are listed 'Best First'.
Re: Re: processing text nodes using HTML::Element
by Anonymous Monk on Mar 09, 2003 at 21:38 UTC

    bbfu,

    Thank you for your reply.

    I perused your code, not running it. I trust it works. In fact, at one point I'd thought I'd have to do it "your" way.

    Let me backtrack and get certain facts straight. From my reading of the documentation I understand there are two ways of controlling how the printed output of a document tree will look.

    (a) The $entities parameter passed to the as_HTML method.
    (b) Using the '~literal' pseudo-element.

    Am I right or missing something ?

    Let me keep on ruminating. In my situation, I've dozens of HTML files whose contents I know nothing about, and should not have to care to know about. By contents I mean text the user can see rendered in the browser—not markup.

    My program reflects the following process:

    (a) read an HTML input file;
    (b) construct a document tree;
    (c) repair text nodes, traversing the tree;
    (d) print the tree as an HTML file.

    Suppose my input HTML file contains the following string:

    &mdash;&nbsp;&copy;

    When my program goes through steps (a), (b) and (d), omitting the step (c), the string in the output file is DIFFERENT from that in the input file.

    Before I go any further in this conversation, let me pause here and ask this question:

    Do you know how to get from the document tree exactly the same text as “went into” the tree ?

    Thank you for your time.

    Cheers

    P.S.

    I'm using ActiveState's Perl 5.6.1 on Win2K.

      Technically, I'm not sure that the '~literal' pseudo-element actually has any effect on how things are printed out (though that's how it's explained in the docs). It seems more sensical to me that it controls whether the text inserted is escaped or not. *shrug* But that's just implementation details. :)

      Honestly, I don't really think there's a way to get HTML::TreeBuilder to print out the original HTML exactly the same. You can get pretty close by calling $tree->no_space_compacting(1) before parsing the HTML, but it doesn't seem to be 100% the same.

      If all you want to do is make some minor changes (eg, changing '--' to '&mdash;') to the text parts, keeping the rest of the HTML exactly the same, you're probably best off switching to HTML::Parser (which HTML::TreeBuilder is based on). Code follows...

      #!/usr/bin/perl use warnings; use strict; our $html = <<'EOHTML'; <html> <body> <p>The relationship can be expressed by the following equation:<br> <blockquote> y &lt;= (7x<sup>3</sup> + 3x<sup>2</sup>)/((x - 3)(x - 5) </blockquote> <p>Of course x != 3 &amp; x != 5 -- That goes without saying. <p>:) </body> </html> EOHTML use HTML::Parser; my $parser = HTML::Parser->new( handlers => { default => [sub { print @_ }, 'text'], # print out HTML tags unmod +ified text => [\&process_text, 'text'], }, ); $parser->parse($html); sub process_text { $_ = shift; # Make any changes to the text here... s/--/&mdash;/g; s/:\)/<img src="smiley.gif">/g; # and so forth. # Now print out the modified text. print; }

      Output:

      <html> <body> <p>The relationship can be expressed by the following equation:<br> <blockquote> y &lt;= (7x<sup>3</sup> + 3x<sup>2</sup>)/((x - 3)(x - 5) </blockquote> <p>Of course x != 3 &amp; x != 5 &mdash; That goes without saying. <p><img src="smiley.gif"> </body> </html>

      bbfu
      Black flowers blossum
      Fearless on my breath