В приведенном ниже коде используется модуль HTML :: TreeBuilder , который является подходящим инструментом для анализа HTML. Регулярные выражения не являются.
#! /usr/bin/perl
use warnings;
use strict;
use HTML::TreeBuilder;
Контрольные примеры из вашего вопроса:
my @cases = (
'<font color="#008080"><span style="background: #ffffff"></span></font>',
'<font color="#008080"> s</font>',
'<font></font>',
);
Мы будем использовать is_empty
в качестве предиката для look_down
метода HTML :: Element , чтобы найти <font>
элементов без интересного контента.
sub is_empty {
my($font) = @_;
my $is_interesting = sub {
for ($_[0]->content_list) {
return 1 if !ref($_) && /\S/;
}
};
!$font->look_down($is_interesting);
}
Наконец, основной цикл. Для каждого фрагмента мы создаем новый экземпляр HTML::TreeBuilder
, удаляем пустые элементы <font>
и обрезаем текстовое содержимое первого уровня из оставшихся.
foreach my $html (@cases) {
my $tree = HTML::TreeBuilder->new_from_content($html);
$_->detach for $tree->guts->look_down(_tag => "font", \&is_empty);
my $result = "";
if ($tree->guts) {
foreach my $font ($tree->guts->look_down(_tag => "font")) {
$font->attr($_,undef) for $font->all_external_attr_names;
foreach my $text ($font->content_refs_list) {
next if ref $$text;
$$text =~ s/^\s+//;
$$text =~ s/\s+$//;
}
}
($result = $tree->guts->as_HTML) =~ s/\s+$//;
}
print "$result\n";
}
Выход:
<font>s</font>
Делать два прохода небрежно. Код может быть улучшен:
#! /usr/bin/perl
use warnings;
use strict;
use HTML::TreeBuilder;
my @cases = (
'<font color="#008080"><span style="background: #ffffff"></span></font>',
'<font color="#008080"> s</font>',
'<font></font>',
);
foreach my $fragment (@cases) {
my $tree = HTML::TreeBuilder->new_from_content($fragment);
foreach my $font ($tree->guts->look_down(_tag => "font")) {
$font->detach, next
unless $font->look_down(sub { grep !ref && /\S/ => $_[0]->content_list });
$font->attr($_,undef) for $font->all_external_attr_names;
foreach my $text ($font->content_refs_list) {
next if ref $$text;
$$text =~ s/^\s+//;
$$text =~ s/\s+$//;
}
}
(my $cleaned = $tree->guts ? $tree->guts->as_HTML : "") =~ s/\s+$//;
print $cleaned, "\n";
}