使用Perl将CSS样式属性转换为HTML属性

Nat*_*int 4 html css perl

真正的快速背景:我们有一个将html转换为pdf的PDFMaker(HTMLDoc).HTMLDoc并不总是从客户端提供给我们的html中获取我们需要的样式.因此我试图转换诸如style ="width:80px; height:90px;"之类的东西.到高度= 80宽度= 90.

到目前为止,我的尝试揭示了我对后向引用的有限理解以及如何在Perl Regex中正确使用它们.我可以获取一个输入文件并将其转换为输出文件,但它每行只捕获一个"样式",并且只替换该css中的一个名称/值对.

我可能以错误的方式接近这个但我无法找到更快或更聪明的方法来在Perl中执行此操作.任何帮助将不胜感激!

注意:我正在尝试为这个特定脚本更改的唯一属性是"高度","宽度"和"边框",因为我们的客户端使用一个工具自动将样式应用于他们使用WYSIWYG样式编辑器拖动的元素.显然,使用正则表达式从很多地方剥离它们的效果相当不错,因为你只是让表格单元格按其内容调整大小,看起来没问题,但我认为更快的方法来处理这个问题只是为了用"width""height"和"border"属性替换这三个属性,这些属性的行为与它们的css对应物大致相同(除了CSS允许你实际自定义边框的宽度,颜色和样式,但它们都是使用是固定1px,所以我可以添加一个条件来替换"solid 1px"和"border = 1".我意识到这些并不完全等效,但对于这个应用程序来说它将是一个步骤).

这是我到目前为止所得到的:

#!/usr/bin/perl
if (!@ARGV[0] || !@ARGV[1])
{
  print "Usage: converter.pl [input file] [output file] \n";
  exit;
}
open FILE, "<", @ARGV[0] or die $!;
open OUTFILE, ">", @ARGV[1] or die $!;
my $line;
my $guts;
while ( <FILE> ) {
  $line = $_ ;
  $line =~ /style=\"(.+)\"/;
  $guts = $1;
  $guts =~ /([a-zA-Z]+)\:([a-zA-Z0-9]+)\;/;
  $name = $1;
  $value = $2;
  $guts = $name."=".$value;
  $line =~ s/style=\"(.+)\"/$guts/g;
  print OUTFILE $line ;
}

exit;
Run Code Online (Sandbox Code Playgroud)

注意:这不是家庭作业,不,我不是要求你为我做我的工作,这最终会成为一个内部工具,加快格式化我们的传入html的过程,以便在pdf转换器中正常工作我们有.

UPDATE

对于那些感兴趣的人,我得到了一个初始工作版本 这个只替换宽度和高度,我们现在正在废弃的border属性.但如果有人想看看我们是怎么做的,那就看看吧......

#!/usr/bin/perl

## NOTES ##
# This script was made to simply replace style attributes with their name/value pair equivalents as attributes.
# It was designed to replace width and height attributes on a metric buttload of table elements from client data we got.
# As such, it's not really designed to handle more than that, and only strips the unit "PX" from the values. 
# All of these can be modified in the second foreach loop, which checks for height and width. 

if (!@ARGV[0] || !@ARGV[1])
{
  print "Usage: quickvert.pl [input file] [output file] \n";
  exit;
}
open FILE, "<", @ARGV[0] or die $!;
open OUTFILE, ">", @ARGV[1] or die $!;
my $line;
my $guts;
my $count = 1;
while ( <FILE> ) {
  $line = $_ ;
  my (@match) = $line =~ /style=\"(.+?)\"/g;
  my $guts;
  my $newguts;
  foreach (@match) {
    #print $_ ."\n";
    $guts = $_;
    $guts =~ /([a-zA-Z]+)\:([a-zA-Z0-9]+)\;/;
    $newguts = "";
    foreach my $style (split(/;/,$guts)) {
      my ($name, $value) = split(/:/,$style);
      $value =~ s/px//g;
      if ( $name =~ m/height/g || $name =~ m/width/g ) {
      $newguts .= "$name='$value' ";
      } else {
      $newguts .= "";
      }
    }
    #print "replacing $guts with $newguts on line $count \n";
  $line =~ s/style=\"$guts\"/$newguts/i;
  }

  #print $newguts;



  print OUTFILE $line ;
  $count++;
}

exit;
Run Code Online (Sandbox Code Playgroud)

Ada*_*ire 5

由于以下几个原因,你将面临非常困难的时期:

  • 使用CSS可以完成的大多数事情都无法通过HTML属性完成.要处理这个问题,你要么必须忽略或试图补偿边距和填充等等...
  • HTML属性和CSS之间的许多对应实际上表现得略有不同,您需要考虑到这一点.要处理这个问题,你必须为每个差异编写特定的代码......
  • 由于CSS规则的应用方式,您基本上需要使用完整的CSS引擎来解析并应用所有规则,然后才能知道在元素/属性级别需要完成哪些操作.为了解决这个问题,您可以忽略除内联样式之外的任何内容,但......

这项工作几乎与为浏览器编写渲染引擎一样复杂.你可能能够处理一些特定的案例,但即便如此,你的成功率最多也是偶然的.

编辑:鉴于你非常具体的功能集,我可以给你一些关于你的实现的建议:

您希望不区分大小写,并在查找style属性的值时使用非贪婪匹配,即:

$line =~ /style=\"(.+?)\"/i;
Run Code Online (Sandbox Code Playgroud)

因此,您只能查找到下一个双引号的内容,而不是直到最后双引号的整行内容.此外,如果找不到匹配项,您可能希望跳过该行,因此:

next unless ($line =~ /style=\"(.+?)\"/i);
Run Code Online (Sandbox Code Playgroud)

为了解析胆量,我使用split而不是正则表达式:

my $newguts;
foreach my $style (split(/;/,$guts)) {
    my ($name, $value) = split(/:/,$style);
    $newguts .= "$name='$value' ";
}
$line =~ s/style=\"$guts\"/$newguts/i;
Run Code Online (Sandbox Code Playgroud)

当然,这是Perl的有标准的咒语如总是使用严格和警告,尝试使用命名的比赛,而不是$1,$2等等,但我想我的建议限制的东西,它将推动解决方案的时候了.