The following code is a shortened version of an example from HTML::Parser
#!/usr/bin/perl -w
use strict;
my $code = shift || usage();
sub edit_print { local $_ = shift; tr/a-z/n-za-m/; print } 
use HTML::开发者_如何学运维Parser 3.05;
my $p = HTML::Parser->new(unbroken_text => 1,
     default_h => [ sub { print @_; }, "text" ],
     text_h    => [ \&edit_print,      "text" ],
);
my $file = shift;
$p->parse_file($file)
This code works pretty well, but it has a disadvantage that it also rewrites the text inside <script> and also <head> sections. I've adapted the example above to do what I want, but unfortunately there is a remaining bug where it rewrites things like the text inside the <title> tag which I don't want to rewrite.
Does anyone know how to write something like the above, but without mangling the JavaScript, <title>, or other sections? I'm happy to use another module apart from HTML::Parser if necessary.
Add start and end handlers to your parser, and have them record the ancestry of the current element. When the ancestry contains <head> or <script>, disable rewriting.
Keep your front matter
#! /usr/bin/perl
use warnings;
use strict;
use HTML::Parser 3.05;
sub edit_print { local $_ = shift; tr/a-z/n-za-m/; print }
and use the following sub to create a new parser:
sub create_parser {
  my @tags;
  my $start = sub {
    my($text,$tagname) = @_;
    push @tags => $tagname;
    print $text;
  };
  my $end = sub {
    my($text,$tagname) = @_;
    die "$0: expected </$tags[-1]>, got </$tagname>"
      unless $tagname eq $tags[-1];
    pop @tags;
    print $text;
  };
  my $edit_print = sub {
    if (grep /^(head|script)$/, @tags) { print @_ }
    else                               { edit_print @_ }
  };
  HTML::Parser->new(
    unbroken_text => 1,
    default_h     => [ sub { print @_ }, "text" ],
    text_h        => [ $edit_print,      "text" ],
    start_h       => [ $start,           "text,tagname" ],
    end_h         => [ $end,             "text,tagname" ],
  );
}
The reason for creating it inside a sub is the handler callbacks are closures that share private state in @tags. This implementation allows you to instantiate multiple parsers without worrying about them stomping on each other's data.
my $p = create_parser;
$p->parse_file(\*DATA);
__DATA__
foo
<html>
<head>
<title>My Title</title>
<style type="text/css">
  /* don't change me */
</style>
</head>
<body>
<script type="text/javascript">
  // or me
</script>
<h1>My Document</h1>
<p>Yo.</p>
</body>
</html>
Output:
sbb
<html>
<head>
<title>My Title</title>
<style type="text/css">
  /* don't change me */
</style>
</head>
<body>
<script type="text/javascript">
  // or me
</script>
<h1>Ml Dbphzrag</h1>
<p>Yb.</p>
</body>
</html>
Looking at your existing code, I'm not sure where you're stuck:
add a stack of Booleans
my @do_edit = (0)in edit_print, don't edit if $do_edit[0] is 0
add start_h and end_h handlers to shift/unshift values for certain element names
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        
 加载中,请稍侯......
      
精彩评论