我如何preg_match脚本标签src,但避免影响img标签src?

时间:2013-01-10 11:53:14

标签: php preg-replace preg-match

我必须匹配本地src并通过网络加载它们。例如:

src="/js/my.js">

变为:

src="http://cdn.example.com/js/my.js">

这就是我现在所拥有的:

if (!preg_match("#<script(.+?) src=\"http#i",$page)){ 
$page = preg_replace("#<script(.+?) src=\"#is", "<script$1 src=\"$workingUrl", $page); 
}

遇到类似这样的事情时,它可以正常工作:

<script type='text/javascript' src='/wp-includes/js/jquery/jquery.js?ver=1.8.3'></script>

遇到类似的事情时失败了:

<script language="JavaScript">
window.moveTo(0,0);
window.resizeTo(screen.width,screen.height);
</script>

如果脚本标记不包含src,它将找到第一个图像标记的src并切换其URL。

我需要知道如何让它终止脚本标记上的匹配和/或如何更好地执行替换。

2 个答案:

答案 0 :(得分:2)

除非使用DOMDocument :: loadHTML并使用DOM,否则不要使用。只接受第一个&gt;之前的所有内容因为后备可能会更好(尽管不完美,因为在理论情况下可能包含&lt; script&gt;的其他属性包含&gt;)。

使用:

#<script([^>]+?) src=\"#is

因为你的模式会使模式在遇到第一个&gt;时停止匹配在&lt; script。

之后

答案 1 :(得分:1)

绝对使用DOM解析器。带有DOMDocument的Xpath将干净,可靠地替换以下脚本标记:

  1. 具有src属性,并且
  2. src属性不是以http开头。

我本可以进一步开发xpath查询表达式来检查前导http子字符串,但我不想用更多语法吓you您。

代码:(Demo

$html = <<<HTML
<html>
<head>
<script type='text/javascript' src='/wp-includes/js/jquery/jquery.js?ver=1.8.3'></script>
<script language="JavaScript">
window.moveTo(0,0);
window.resizeTo(screen.width,screen.height);
</script>
</head>
</html>
HTML;

$workingUrl = 'https://www.example.com';

$dom = new DOMDocument; 
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new DOMXPath($dom);
foreach ($xpath->query("//script[@src]") as $node) {
    if (strpos($node->getAttribute('src'), 'http') !== 0) {
        $node->setAttribute('src', $workingUrl);        
    }
}
echo $dom->saveHTML();

输出:

<html>
<head>
<script type="text/javascript" src="https://www.example.com"></script>
<script language="JavaScript">
window.moveTo(0,0);
window.resizeTo(screen.width,screen.height);
</script>
</head>
</html>