php preg_replace for html标签内的属性

时间:2013-08-01 21:26:58

标签: php regex tags html-parsing

我的问题是如何替换字符串中src标记的<script>值,就像在这个例子中一样(好吧,我需要在标签内属性的更一般场景中):

$data = <<<EOD
<script language="javascript" src= "../tests/ajax-navigation.js"></script>
...
<img src="../404.jpg" alt="404">
...
EOD;

我在php中使用了这个函数:

class Search{
 public static function replaceProperty($data, $start, $end, $property, $alias, $limit = -1){
   //get blocks formed as: $start $property = "..." $end or $start $property = '...' $end
   $pattern = "!(".$start."){1}(.*?)".$property."\s*=\s*[\"\'](.*?)[\"\'](.*?)(".$end."){1}!s";
   $data = \preg_replace($pattern, "{$start}\${2}{$property}=\"{$alias}\"\${4}{$end}", $data, $limit);
   return $data;
 }
}

我这样称呼:

 $data = Search::replaceProperty($data, "<script", ">", "src", $alias);

真正奇怪的是标签<script><img>都会发生变化! 当然我可以称之为

 $data = Search::replaceProperty($data, "<script", "</script>", "src", $alias);

但这并不能回答一般情况!

只是为了澄清正则表达式的一些观点:

我。要搜索的实际字符串是:

$data = <<<EOD
<script language="javascript" src= "../tests/ajax-navigation.js"></script>
...
<script language="javascript" type="text/javascript">
...
<img src="../404.jpg" alt="404">
...
EOD;

II。正则表达式$pattern = "!(".$start."){1}(.*?)".$property."\s*=\s*[\"\'](.*?)[\"\'](.*?)(".$end."){1}!s";或最简单的$pattern = "%".$start."(.*?)".$property."\s*=\s*[\"\'](.*?)[\"\'](.*?)".$end."%s";(只有3个子图案)标识出第一个<script>,但是......它需要第二个<script>并终止于{ {1}}第一个>更改了它之间找到的<img>属性!

III。通过删除模式末尾的src元字符,导致s按预期运行,但在使用enter键断开标记时失败:

$pattern = "%".$start."(.*?)".$property."\s*=\s*[\"\'](.*?)[\"\'](.*?)".$end."%";

IV。当然,我的意图是替换而不是删除<script language="javascript" src= "../tests/ajax-navigation.js" ></script> 属性的值。

希望这些澄清我的问题。

3 个答案:

答案 0 :(得分:0)

更改此行:

 public static function replaceProperty($data, $start, $end, $property, $alias, $limit = -1){

对此:

 public static function replaceProperty($data, $start, $end, $property, $alias='', $limit = -1){

在$ alias参数中添加默认值''。

也不确定preg_replace前面的反斜杠是做什么的。我也不得不删除它。

答案 1 :(得分:0)

以下是我用preg_match_all查找所有元素的一些代码,我发现preg_match_all比preg_match更好。

$arr = array();
preg_match_all("%[<]script.*?[>](.*?)[<][\/]script[>]%",$f, $arr, PREG_OFFSET_CAPTURE);
var_dump($arr);

或使用preg_replace:

$a = preg_replace("%[<]H3.*?[>].*?[<][\/]H3[>]%", "", $a);

尝试使用preg_match,同时遵循我使用的<>类似[&lt;] $ start而不是将<传递给函数的语法。通过在%之后使用相应的preg_match选项或使用之前使用strtolower转换所有数据,还要确保它不区分大小写。我敢肯定,如果这样可行,你可以自己解决问题。

答案 2 :(得分:0)

正如我所说,我会使用DOMDocument(),但这是一个正则表达式的答案:

class Search{

public function __construct(){}

public static function replaceProperty($data, $tag, $property, $alias, $limit = -1){
   //get blocks formed as: <$tag...$property=["|']...["|']...[/>|>]
   $pattern = '%<\s*'.$tag.'(\s+(\w+)(\s*\=\s*(\'|"|)(.*?)\\4\s*)?)*\s*(\/>|>)%s';
   $result = \preg_match_all($pattern, $data, $matches, PREG_PATTERN_ORDER);
   if(!empty($result)){
      $search = array();
      $replace = array();
      //found them at index = 0!
      foreach($matches[0] as $i=>$found){
         if(($limit >= 0) && ($i >= $limit))
            break;
         if(isset($matches[2]) && isset($matches[5]) && $matches[2][$i] == $property){
            $search[] = $found;
            $replace[] = \str_replace($matches[5][$i], $alias, $found);
         }
      }
      $data = \str_replace($search, $replace, $data);
   }
   return $data;
}
}

并且这样调用:

$data = Search::replaceProperty($data, "script", "src", $alias);

我使用了来自this帖子的Emanuele Del Grande的回答,这可能是对this等帖子的再现! 感谢。