使用Perl修改PHP文件(可能使用HTML :: TreeBuilder)

时间:2010-08-27 16:59:04

标签: perl parsing

我正在尝试在许多网站上修改许多网页。除HTML之外,页面可能还包含JavaScript,PHP或ASP代码。我遇到的问题是模块重写了我不想重写的东西。我设法处理了像"这样的HTML标记中的大多数符号(例如>script),但它们变成了实体(例如", {php}部分中的>)。另外,php标签同时被删除。

如果我有一个看起来像这样的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;

我对任何建议,示例等持开放态度。我不一定与任何特定模块绑定,但我不是一个专业的程序员。

谢谢!

1 个答案:

答案 0 :(得分:3)

这里的问题显然是<?php .. ?>标签。你可以用preparser完成这个任务。我将使用一个简单的正则表达式:

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撤消修改(如字符编码) - 对我来说这听起来像是一个更糟糕的想法。您甚至可以使用__PHP_CODE__过滤器实现从Template令牌到真实PHP代码的内容。

应该注意的是,这并没有处理短标签(虽然它很容易!)而且,我不确定触发PHP解释器的逻辑(转义<?php?>例如)。很明显,虽然我会透露,这与PHP代码无关:

echo '?>';