agynr has asked for the wisdom of the Perl Monks concerning the following question:

Hello Everyone, I want to remove all the html tags from a file which is about 8-9 MB in size. The problem is that with HTML:PARSER the spaces are not retained, i.e; the tags are just eliminated, but what I want is that the tags should be converted into spaces, retaining the size of the file as it is.

Replies are listed 'Best First'.
Re: Removing HTML Tags from a file
by graff (Chancellor) on Dec 14, 2004 at 05:08 UTC
    You mean, instead of deleting tags, you want to replace them with strings of spaces, so that the output file is the same size as the input, and just has a lot more space characters (and no html tags) -- have I got that right?

    This would do:

    #!/usr/bin/perl use strict; use HTML::TokeParser::Simple; my $htm = HTML::TokeParser::Simple->new( $ARGV[0] ) or die "oops: $!"; while ( my $token = $htm->get_token ) { if ( $token->is_tag() ) { print " " x length( $token->as_is ); } else { print $token->as_is; } }
    If you look at the perldoc man page for HTML::TokeParser::Simple (and the "less simple" classes it is derived from), you might find it easy to come up with other more useful variants, and/or figure out handy ways to deal with things like scripting and comments that are often included in html files.
      Sir, I am not able to install the pm module for html:tokeparser:simple. I am currently using activestate perl on windows XP. I have simple.pm module in my d:\perl\lib\simple.pm. Please tell me the way to get it installed.
        Yes, you can.

        Open a "DOS" window and type:

        C:\Documents and Settings\Administrador>ppm

        You'll enter PPM's prompt. Then type:

        ppm> install HTML-TokeParser-Simple

        Regards,

        agynr,

        You go through the active state documentation.

        In that they have described how to install a module using ppm.

        You follow the procedure and install it.

        Prasad

Re: Removing HTML Tags from a file
by DaWolf (Curate) on Dec 14, 2004 at 07:23 UTC
    Yes, do as prasadbabu said.

    PPM is a wonderful and very easy to use tool that will help you a lot, trust us on this.

    You can even upgrade your installed modules using it.

    On PPM's prompt you can type 'help' (without the quotes, obviously) to get a quick reference.

    Regards,
Re: Removing HTML Tags from a file
by rrwo (Friar) on Dec 14, 2004 at 20:22 UTC

    It's not worth parsing if you just want to remove the tags. The parser may choke on bad HTML, and it may not tell you how long whitespace between attributes is, in case tags have extra whitespace.

    Your best bet is to use a non-greedy regex. Off the top of my head:

    $str = "<tag>blah</tag> <another>meh</another>"; print "*$str*\n"; $str =~ s/\<(.*?)\>/ " "x(2+length($1)) /eg; print "*$str*\n";

    For what it's worth, there's also various CPAN modules that strip HTML, but they don't do what you need. And I think it may be more work to use them than to use a regex.

    • HTML::Stripper uses HTML::Parser, so I'm not sure how well it would handle bad HTML anyway.
    • HTML::TagFilter might be a userful alternative, though I've not tried it. It also uses HTML::Parser though.
    • HTML::Sanitizer is another tag filter that may be useful. This one does not seem to use HTML::Parser.
    • HTML::Strip does not use the parser, but I don't think it lets you replace text.
      Your regex will fail in all, but the most trivial cases. It fails when < is used to not start a tag, and it fails when > is used inside an attribute value, or inside a comment. If you have to do it with a regex, use something like (untested):
      s{<[a-zA-Z][^>'"]*(?:(?:'[^']*'|"[^"]*")[^>'"]*)*> # Tags |<!(?:--[^-]*(?:-[^-]+)*--\s*)*> # Comments }{" " x length $&}xeg
Re: Removing HTML Tags from a file
by Cody Pendant (Prior) on Dec 14, 2004 at 08:38 UTC
    I really have to know. Why would you want to do that?


    ($_='kkvvttuubbooppuuiiffssqqffssmmiibbddllffss')
    =~y~b-v~a-z~s; print
Re: Removing HTML Tags from a file
by Anonymous Monk on Dec 14, 2004 at 10:25 UTC
    #!/usr/bin/perl use Switch; $/ = \1; $state = 'DOCUMENT'; while (<>) { switch ($state) { case 'DOCUMENT' { $state = 'TAG' if /\x3C/; } case 'TAG' { $state = /\x21/ ? 'DECLARATION' : 'ELEMENT'; } case 'ELEMENT' { $state = 'SINGLE_QUOTE' if /\x27/; $state = 'DOUBLE_QUOTE' if /\x22/; $state = 'DOCUMENT_TO_BE' if /\x3E/; } case 'SINGLE_QUOTE' { $state = 'ELEMENT' if /\x27/; } case 'DOUBLE_QUOTE' { $state = 'ELEMENT' if /\x22/; } case 'DECLARATION' { die "Parse error" unless /\x2D/; $state = 'COMMENT_START'; } case 'COMMENT_START' { die "Parse error" unless /\x2D/; $state = 'COMMENT'; } case 'COMMENT' { $state = 'COMMENT_END' if /\x2D/; } case 'COMMENT_END' { $state = /\x2D/ ? 'COMMENT_TRAIL' : 'COMMENT'; } case 'COMMENT_TRAIL' { die "Parse error" unless /[\x22\x3E\s]/; $state = 'COMMENT_START' if /\x22/; $state = 'DOCUMENT_TO_BE' if /\x3E/; } } print $state eq 'DOCUMENT' ? $_ : " "; $state = 'DOCUMENT' if $state eq 'DOCUMENT_TO_BE' }