2010-08-27 50 views
2

我试图在许多网站上重做很多页面。除HTML之外,页面可能包含JavaScript,PHP或ASP代码。我遇到的问题是模块重写了我不想重写的内容。我已设法处理HTML标记(例如script)中的大部分符号(例如,",>),但它们在php部分中变为实体(例如,",>)。另外,php标签同时被剥离出来。使用Perl修改PHP文件(可能使用HTML :: TreeBuilder)

如果我有一个PHP文件看起来像这样:

<html> 
    <head><title>My Page</title></head> 
    <body> 
    <p>Some cruft &nbsp; which I want to repeat</p> 
    <form name="foo"> (form content to be replaced) 
    </form> 
    <script type="JavaScript"> 
     <!-- 
     Some javaScript to be left alone 
     --> 
    </script> 
    <a href="somepage.php">Link to be removed</a> 
    <?php 
     if (strlen($txtKeyword) > 2) 
     { 
      echo " or <a href=\"database_search_keyword.htm\">Search again?</a></p>"; 
      if(isset($_REQUEST['nr'])) 
     { 
      $numRows = $_REQUEST['nr']; 
      .... 
    ?> 
    </body> 
</html> 

我想最后的结果看起来像:

<html> 
    <head><title>My Page</title></head> 
    <body> 
    <p>Some cruft &nbsp; which I want to repeat</p> 
    <ul><li>List replacing form</li> 
    </ul> 
    <script type="JavaScript"> 
     <!-- 
     Some javaScript to be left alone 
     --> 
    </script> 
    <?php 
     if (strlen($txtKeyword) > 2) 
     { 
      echo " or <a href=\"database_search_keyword.htm\">Search again?</a></p>"; 
      if(isset($_REQUEST['nr'])) 
     { 
      $numRows = $_REQUEST['nr']; 
      .... 
    ?> 
    </body> 
</html> 

正如我所说的,我能够得到的一切工作除了php。它得到管理,所以结果

<html> 
    <head><title>My Page</title></head> 
    <body> 
    <p>Some cruft &nbsp; which I want to repeat</p> 
    <ul><li>List replacing form</li> 
    </ul> 
    <script type="JavaScript"> 
     <!-- 
     Some javaScript to be left alone 
     --> 
    </script> 
    <?php 
     if (strlen($txtKeyword) &gt; 2) 
     { 
      echo &quot; or &quot;; 
      if(isset($_REQUEST[&#39;nr&#39;])) 
     { 
      $numRows = $_REQUEST[&#39;nr&#39;]; 
      .... 
    ?> 
    </body> 
</html> 

我一直在使用HTML :: TreeBuilder 3.23。我试过开发​​者版本3.23_3,但由于php代码的原因,它提供了一个错误消息(例如,a has an invalid attribute name '"&section_id' ' . $section_id . ')。

什么我迄今所做(与文件系统散步等切碎出)的示例代码是

#!/usr/bin/perl -w 

use strict; 

use HTML::TreeBuilder; 

# Set up replacement forms 
my $artistSearch = HTML::Element->new ('~literal', 'text', <<EOF); 
<p>Please select from the list below.</p> 
<ul> 
    <li><a href="http://firstlink.com/">item 1</a></li> 
    <li><a href="http://secondlink.com/">item 1</a></li> 
</ul> 
EOF 

my $filename = "AFA.php"; 
my $file = HTML::TreeBuilder->new(); 
$file->store_comments(1); 
$file->ignore_ignorable_whitespace(1); 
$file->no_space_compacting(1); 
my $tree = $file->parse_file($filename); 


my $form = $tree->find_by_tag_name('form'); 
my $fname = $form->attr('name'); 
if ($fname eq 'mainform') { 
    $form->delete; 
} elsif ($fname eq 'artist_search') { 
    $form->replace_with($artistSearch)->delete; 
} else { 
    # It's a form we're not changing 
} 

my $printout = $file->as_HTML("", " ", {}); 
open (PAGE, "> $filename"); 
print PAGE $printout; 
close (PAGE); 
$file->delete; 

我愿意接受任何建议,示例等我不必拘泥于到任何特定的模块,但我不完全是一个专家程序员。

谢谢!

回答

3

这里的问题显然是<?php .. ?>标签。你可以通过预备者来完成。我将使用一个简单的正则表达式是:

use strict; 
use warnings; 
undef $/; 
$_=<>; 
my @phps; 
push @phps, $1 while s/<\?php (.*?) \?>/__PHP_CODE__/; 

use Data::Dumper; 
die Dumper [$_, \@phps]; 

,您可以尝试:

echo "foo<?php phpfoo ?> bar <?php phpbar ?> baz" | filter.pl 


$VAR1 = [ 
      'foo__PHP_CODE__ bar __PHP_CODE__ baz', 
      [ 
      'phpfoo', 
      'phpbar' 
      ] 
     ]; 

现在,当你用它做。你可以做反向得到的PHP代码了@phps阵列并返回到输出正确的顺序:

my $count = 0; 
s/__PHP_CODE__/<?php $phps[$count++] ?>/g; 

请不要误会,这是一个黑客;但是,它会让你的工作非常有效地完成,没有太多的想法。实施起来也相当简单。我可以想出许多更好的方法来做到这一点 - 比如扩展HTML::Element以包含伪<?php .. ?>元素。你不想要的是在TT中用HTML::Element撤销mangling(如字符编码) - 这听起来像是一个远的更糟糕的想法给我。您甚至可以使用Template过滤器实现从__PHP_CODE__令牌到真正的PHP代码的内容。

应该指出的是,这并不考虑短标签(虽然它可以很容易!)并且,我不确定触发PHP解释器的逻辑(例如跳过<?php?>)。很明显,尽管我会透露,这对PHP代码没有这样的支持:

echo '?>'; 
+0

这看起来完全可行......假设我可以把我的头包装起来,让它与代码的其余部分一起工作。感谢您的快速回复,并且在我咀嚼了一阵之后我会更新它。 – tmsilver 2010-08-27 18:02:04

+0

这似乎是工作,但我不得不做很多读/写才能使其工作。我最终1)读取文件,用令牌替换PHP; 2)用令牌写文件; 3)为TreeBuilder读取文件; 4)写入TB更改的文件; 5)读取文件,用代码替换标记; 6)完整更改写入文件。 如果我尝试跳过其中的任何一个,它会省略或覆盖我的一些更改。这可能是一个新手事物... 感谢您的帮助! – tmsilver 2010-08-27 21:46:56

+1

您不必多次“写入文件”。你可以在记忆中完成这一切。您可以(1)* slurp *文件,(2)分配php令牌(3)使用TreeBuilder运行'new_from_content',(4)转换,(5)' - > as_HTML'它,(6)运行正则表达式替换PHP令牌(7)一次写入文件。这仍然是记忆中的许多传球 - 许多理论上不需要,但这仍然不是文件io。 – 2010-08-27 22:07:25