php preg_replace_callback删除<script>标记以外的注释

时间:2015-07-13 11:30:36

标签: php html regex minify

我想使用preg_replace_callback删除html注释。但我也希望保留&lt; script&gt; 元素内的注释,例如:

&#xA;&#xA;
  b / w&lt; script&gt ; &lt;! -  Keep Me  - &gt;&lt; / script&gt;&#xA;  
&#xA;&#xA;

我的代码:

&#xA ;&#xA;
  $ str ='&#xA; &LT;脚本&GT;&#XA; &lt;! -  keep1  - &gt;&#xA;保持&lt; / script&gt; &lt;! -  del me1  - &gt; &LT;身体GT; &LT;脚本&GT; &lt;! -  Keep2  - &gt;&lt; / script&gt; &lt;! -  Del me2  - &gt; &lt; script&gt;&lt;! -  Keep3  - &gt;&lt; / script&gt; &lt; / body&gt;&lt;! -  del me 3  - &gt;';&#xA;&#xA;&#xA; $ str = preg_replace_callback('/(&lt;([^ script] \ /?) (\ W | \ d | \ N | \ r | \ v)GT;?!)*((*(小于 -  *  - &GT;)|(\ W | \ d | \ n | \ r | \ v)*)+)(&lt; \ /?[^ script](\ w | \ d)*&gt;)/ s',&#xA; function($ matches){&#xA; print_r( $ matches);&#xA;返回preg_replace('/&lt;! - 。*? - &gt; / s','',$ matches [2]);&#xA;},$ str);& #xA;  
&#XA;

2 个答案:

答案 0 :(得分:2)

从技术上讲,&#34; html评论&#34;脚本标签之间没有更多的HTML评论。如果使用DOM方法,则不会选择这些注释:

$dom = new DOMDocument;
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

$xp = new DOMXPath($dom);
$comments = $xp->query('//comment()');

foreach ($comments as $comment) {
    $comment->parentNode->removeChild($comment);
}

$result = $dom->saveHTML();

关于条件评论:

如果要保留条件注释,则需要检查注释的开头。你可以用两种方式做到这一点。

第一种方法是检查foreach循环中的注释,当测试为否定时,删除节点。

但是,由于您使用XPath方式(包括一劳永逸地选择所需内容),因此要遵循相同的逻辑,您可以将XPath查询更改为:

//comment()[not(starts-with(., "[if") or starts-with(., "[endif]"))]

方括号之间的内容称为&#34;谓词&#34; (当前元素的条件),点表示当前元素或其文本内容(取决于上下文)

但是,如果这种情况在大多数时间都有效,那么最轻微的领先空间就会让它失败。您需要比starts-with更灵活的内容。

可以在XPath查询中注册您自己的php函数,如下所示:

function isConditionalComment($commentNode) {
    return preg_match('~\A(?:\[if\s|\s*<!\[endif])~', $commentNode[0]->nodeValue);
}

$dom = new DOMDocument;
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

$xp = new DOMXPath($dom);

$xp->registerNamespace('php', 'http://php.net/xpath');
$xp->registerPHPFunctions('isConditionalComment');

$comments = $xp->query('//comment()[not(php:function("isConditionalComment", .))]');

foreach ($comments as $comment) {
    $comment->parentNode->removeChild($comment);
}

注意:DOMDocument不支持非HTML注释的默认Microsoft语法(没人使用):

<![if !IE]>
<link href="non-ie.css" rel="stylesheet">
<![endif]>

此语法会导致警告(因为它不是HTML)和&#34;标记&#34;被忽略并从DOM树中消失。

答案 1 :(得分:-1)

您无法尝试使用此代码:

$str= preg_replace('/<!--(\w|\s)*-->/', '', $str);

在您的Javascript中,您可以使用(而不是<!-- -->):

/* Keep me comment */