use warnings;
use strict;
# ##### Version with Mojo::DOM #####
# nicer API but less strict on parsing (useful for HTML)
use Mojo::DOM;
sub strip_tags_mojo {
my ($str, $activetags) = @_;
my %active = map {($_=>1)} @$activetags;
my $dom = Mojo::DOM->new->xml(1)->parse($str);
$dom->find('*')->grep(sub{ not $active{$_->tag} })->map('remove');
my $text = $dom->all_text;
$text =~ s/\s+/ /g;
return $text;
}
# ##### Version with XML::LibXML #####
# generally a more verbose API but strict XML-compliant parsing
# (in the following I've tried to shorten the code quite a bit)
use XML::LibXML;
sub strip_tags_xml {
my ($str, $activetags) = @_;
my %active = map {($_=>1)} @$activetags;
my $dom = XML::LibXML->new->parse_balanced_chunk($str);
$active{$_->nodeName} or $_->parentNode->removeChild($_)
for $dom->findnodes('*');
my $text = $dom->textContent;
$text =~ s/\s+/ /g;
return $text;
}
# ##### Tests #####
use Test::More;
sub exception (&) { eval { shift->(); 1 } ? undef : ($@ || die) } # poor man's Test::Fatal
my $input = 'word1 word2 word3 word4 word5 word6 word7 word8 word9 word10 word11';
my @tests = (
{ in=>['tag0', 'tag1'], exp=>'word1 word2 word3 word4 word5 word6 word9 word11' },
{ in=>['tag3'], exp=>'word1 word6 word9 word10 word11' },
{ in=>['tag1', 'tag2', 'tag3'], exp=>'word1 word6 word7 word8 word9 word10 word11' },
);
plan tests => (@tests+1)*2;
for my $t (@tests) {
is strip_tags_mojo($input, $t->{in}), $t->{exp};
is strip_tags_xml($input, $t->{in}), $t->{exp};
}
ok not exception { strip_tags_mojo('foo bar ') };
ok exception { strip_tags_xml('foo bar') };