用Perl中的HTML副本替换特定的内联CSS

时间:2009-11-10 04:54:48

标签: perl

这是我第一次使用Stack Overflow,所以如果我做错了,请告诉我。

我目前正在尝试编写一个“刮刀”,由于缺乏更好的术语,它将提取html并用HTML副本替换某些内联CSS样式。例如,我有这个HTML:

<p style="text-align:center"><span style="font-weight:bold;font-style:italic;">Some random text here. What's here doesn't matter so much as what needs to happen around it.</span></p>

我希望能够将font-weight:bold替换为<b>,将font-style:italic替换为<i>,将text-align:center替换为<center>。之后,我将使用正则表达式删除所有非基本HTML标记和任何属性。 KISS绝对适用于此。

我已经阅读了这个问题:Convert CSS Style Attributes to HTML Attributes using Perl以及其他一些关于使用HTML :: TreeBuilder和其他模块(如HTML :: TokeParser)的问题,但到目前为止,我自己也偶然发现了。

我是Perl的新手,但对于一般的编码并不陌生。它的逻辑是一样的。

这是我到目前为止所拥有的:

#!/usr/bin/perl
use warnings;
use strict;

use HTML::TreeBuilder;

my $newcont = ""; #Has to be set to something? I've seen other scripts where it doesn't...this is confusing.
my $html = <<HTML;
<p style="text-align:center"><span style="font-weight:bold;font-style:italic;">Some random text here. What's here doesn't matter so much as what needs to happen around it.</span> And sometimes not all the text is styled the same.</p>
HTML

my $tb = HTML::TreeBuilder->new_from_content($html);
my @spans = $tb->look_down(_tag => q{span}) or die qq{look_down for tag failed: $!\n};

for my $span (@spans){
    #What next?? A print gives HASH, not really workable. Split doesn't seem to work...I've never felt like such a noobie coder before.
}

print $tb->as_HTML;

希望有人可以帮助我,告诉我我可能做错了什么,等等。我真的很好奇有什么其他可能的方法来做到这一点。或者,如果以前曾经做过。

此外,如果有人可以通过建议我应该使用哪些标签来提供帮助,那就太棒了。我知道肯定会使用的唯一一个是perl。

3 个答案:

答案 0 :(得分:3)

在HTML :: Element文档中,似乎 look_down()返回HTML :: Element对象的列表。 Perl对象通常是对哈希的引用(尽管它们不必是) - 这就是你打印$span时获得HASH的原因。

无论如何,在for-loop中,您应该可以调用

 $span->method()

其中方法是HTML :: Element的任何方法。出于您的目的,方法all_attr()as_text()replace_with()看起来相当有前景。

我尝试链接到每个方法,但SO不喜欢粗糙的CPAN锚定链接,所以这里是一个快速链接到主文档页面以方便:

https://metacpan.org/pod/HTML::Element

答案 1 :(得分:2)

麦克,
问题是,在Perl中,遗憾的是,您无法在调试器中看到元素的类型,因为对象系统只是标准类型的包装器。因此,在查看文档和/或代码时找不到相关的属性/方法是不可能的。 About Objects为您提供了有关此内容的详细信息 每个$ span都是一个HTML :: Element对象 - 本的答案涵盖了这一部分。我想你只需要更改树中的一些属性,并将树保存到新文件中。

答案 2 :(得分:1)

使用HTML::TreeBuilder,你肯定是在正确的轨道上;为了解析CSS,我刚刚找到了CSS::DOM。这是一个非常有趣的模块,它允许您轻松访问属性。

#!/usr/bin/perl
use warnings;
use strict;

use HTML::TreeBuilder;
use CSS::DOM::Style;

my $html = <<HTML;
<p style="text-align:center"><span style="font-weight:bold;font-style:italic;">Some random text here. What's here doesn't matter so much as what needs to ha>
HTML

my $tb = HTML::TreeBuilder->new_from_content($html);


my @replacements = (
    { property => 'font-style', value => 'italic', replacement => 'em' },
    { property => 'font-weight', value => 'bold', replacement => 'strong' },
    { property => 'text-align', value => 'center', replacement => 'center' },
);

# build a sensible list of tag names (or just use sub { 1 })
my @nodes = $tb->look_down(sub { $_[0]->tag =~ /^(p|span)$/ });

for my $el (@nodes) {
    if ($el->attr('style')) {
        my $st = CSS::DOM::Style::parse($el->attr('style'));
        if ($st) {
            foreach my $h (@replacements) {
                if ($st->getPropertyValue($h->{property}) eq $h->{value}) {
                    $st->removeProperty($h->{property});
                    my $new = HTML::Element->new($h->{replacement});
                    foreach my $inner ($el->detach_content) {
                        $new->push_content($inner);
                    }
                    $el->push_content($new);
                }
            }
            $el->attr('style', $st->cssText ? $st->cssText : undef);
        }
    }
}

print $tb->as_HTML(undef, "\t");