用Regex或DOM替换包含给定href属性的所有<link />标记

时间:2014-02-24 13:00:53

标签: php html regex preg-replace pattern-matching

我正在努力解决这个问题。我们的想法是替换所有<link>标记,其中包含给定字符串中的特定href属性(来自缓冲区并且它是常规HTML,但有时会出错)。

我尝试使用PHP DOM方法,也是SimpleHTMLDOM解析器库,到目前为止对我没有任何作用(问题是DOM方法只返回<body>内的链接{1}}元素,但不是页面的<head>部分中的那些元素),所以我决定使用正则表达式。 以下是不可用的PHP DOM方法代码:

function remove_css_links($string = "", $css_files = array()) {
        $css_files = array("http://www.example.com/css/css.css?ver=2.70","style.css?ver=3.8.1");
            $xml = new DOMDocument();
        $xml->loadHTML($string);
        $link_list = $xml->getElementsByTagName('link');
        $link_list_length = $link_list->length;
        //The cycle
            for ($i = 0; $i < $link_list_length; $i++) {
          $attributes = $link_list->item($i)->attributes;
          $href = $attributes->getNamedItem('href');
          if (in_array($href->value, $css_files))  {
            //Remove the HTML node
          }                 
        }
        $string = $xml->saveHTML();
        return $string;
}

这是正则表达式代码,但我知道你们所有人都不建议用它来解析HTML,但我们现在不讨论这个:

$html_text = '
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="shortcut icon" href="http://www.example.com/favicon.ico" />
<link rel="alternate" type="application/rss+xml" title="Website &raquo; Feed" href="/feed/" />
<link rel=\'stylesheet\'  href=\'http://www.example.com/css/css.css?ver=2.70\' type=\'text/css\' media=\'all\' /></head>
<body>...some content...
<link rel=\'stylesheet\' id=\'css\'  href=\'style.css?ver=3.8.1\' type=\'text/css\' media=\'all\' />
</body></html>
';
$url = preg_quote("http://www.example.com/css/css.css?ver=2.70");
$pattern = "~<link([^>]+) href=".$url."/?>~";
$link = preg_replace($pattern, "", $html_text);

正则表达式的问题在于href属性可以位于<link>标记内的任何位置,而我使用的这个属性可以检测任何类型的<link>标记,如您可以看到我不想删除它们的shortcut iconalternate类型,以及与href属性的给定网址不同的任何内容。您可以注意到<link>标记包含不同类型的引号,单引号和/或双引号。

但是,我愿意接受建议,如果可以使DOM方法有效,而不是使用正则表达式 - 那就没关系。

1 个答案:

答案 0 :(得分:2)

好的,所以你在这里:

<?php

$html_text = '
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="shortcut icon" href="http://www.example.com/favicon.ico" />
<link rel="alternate" type="application/rss+xml" title="Website &raquo; Feed" href="/feed/" />
<link rel="stylesheet"  href="http://www.example.com/css/css.css?ver=2.70" type="text/css" media="all" /></head>
<body>...some content...
<link rel="stylesheet" id="css"  href="style.css?ver=3.8.1" type="text/css" media="all" />
</body></html>
';

$d = new DOMDocument();
@$d->loadHTML($html_text);
$xpath = new DOMXPath($d);
$result = $xpath->query("//link");

foreach ($result as $link)
{
    $href = $link->getattribute("href");

    if ($href=="whatyouwanttofilter")
    {
          $link->parentNode->removeChild($link);
    }

}

$output= $d->saveHTML();
echo $output;

?>

经过测试和工作。玩得开心! : - )


一般的想法是:

  • 将您的HTML加载到DOMDocument
  • 使用link
  • 查找XPath个节点
  • 循环通过节点
  • 根据节点的href属性,删除节点(实际上,将子节点从其中删除...父节点 - 好吧,是的,这是php方式...大声笑)
  • 完成所有清理后,重新保存HTML并将其恢复为字符串
相关问题