php preg_replace_callback 删除 <script> 标签以外的评论
php preg_replace_callback Remove comments except from <script> tag
我想使用 preg_replace_callback 删除 html 评论。但我也想保留 <script>
元素内的注释,例如:
b/w <script> <!-- Keep Me--></script >
我的代码:
$str = '
<script>
<!-- keep1 -->
keep </script> <!-- del me1 --> <body> <script> <!-- Keep2 --></script> <!-- Del me2 --> <script><!-- Keep3 --></script> </body><!-- del me 3 -->';
$str = preg_replace_callback('/(<([^script]\/?)(\w|\d|\n|\r|\v)>)*((.*(<?!--.*-->)|(\w|\d|\n|\r|\v)*)+)(<\/?[^script](\w|\d)*>)/s',
function($matches) {
print_r($matches);
return preg_replace('/<!--.*?-->/s', ' ', $matches[2]);
}, $str);
您不能尝试使用此代码:
$str= preg_replace('/<!--(\w|\s)*-->/', '', $str);
并且在您的 Javascript 中,您可以使用(而不是 <!-- -->
):
/* Keep me comment */
从技术上讲,脚本标签之间的 "html comments" 不再是 html 注释。如果您使用 DOM 方法,这些评论不是 selected:
$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 方式(即 select 您想要的一劳永逸),为了遵循相同的逻辑,您可以将 XPath 查询更改为:
//comment()[not(starts-with(., "[if") or starts-with(., "[endif]"))]
方括号之间的内容称为"predicate"(当前元素的条件),点表示当前元素或其文本内容(取决于上下文)
但是,如果这在大多数情况下都有效,最轻微的前导 space 都会使其失败。您需要比 starts-with
.
更灵活的东西
可以像这样注册您自己的 php 函数以在 XPath 查询中使用:
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)并且 "tag" 会被忽略并从 DOM 树中消失。
我想使用 preg_replace_callback 删除 html 评论。但我也想保留 <script>
元素内的注释,例如:
b/w <script> <!-- Keep Me--></script >
我的代码:
$str = '
<script>
<!-- keep1 -->
keep </script> <!-- del me1 --> <body> <script> <!-- Keep2 --></script> <!-- Del me2 --> <script><!-- Keep3 --></script> </body><!-- del me 3 -->';
$str = preg_replace_callback('/(<([^script]\/?)(\w|\d|\n|\r|\v)>)*((.*(<?!--.*-->)|(\w|\d|\n|\r|\v)*)+)(<\/?[^script](\w|\d)*>)/s',
function($matches) {
print_r($matches);
return preg_replace('/<!--.*?-->/s', ' ', $matches[2]);
}, $str);
您不能尝试使用此代码:
$str= preg_replace('/<!--(\w|\s)*-->/', '', $str);
并且在您的 Javascript 中,您可以使用(而不是 <!-- -->
):
/* Keep me comment */
从技术上讲,脚本标签之间的 "html comments" 不再是 html 注释。如果您使用 DOM 方法,这些评论不是 selected:
$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 方式(即 select 您想要的一劳永逸),为了遵循相同的逻辑,您可以将 XPath 查询更改为:
//comment()[not(starts-with(., "[if") or starts-with(., "[endif]"))]
方括号之间的内容称为"predicate"(当前元素的条件),点表示当前元素或其文本内容(取决于上下文)
但是,如果这在大多数情况下都有效,最轻微的前导 space 都会使其失败。您需要比 starts-with
.
可以像这样注册您自己的 php 函数以在 XPath 查询中使用:
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)并且 "tag" 会被忽略并从 DOM 树中消失。