2 回答
TA贡献1942条经验 获得超3个赞
您可以使用交替来匹配src
or href
,然后使用否定前瞻来断言 src/href 不以 开头{{asset
:
((?:src|href)\s*=\s*")((?!{{\s*asset)[^"]+)
这也将更改标签href
内<a>
或其他地方的属性。如果这是一个问题,请改用DOMDocument
解决方案。请注意,如果您的 HTML 不仅仅是一个片段,那么您不需要div
在对的调用中在其周围添加标记loadHTML
,并且最后一行应更改为echo substr($doc->saveXML(), 38);
.
$html = <<<EOT
//Find:
<img src="icons/google-icon.svg" >
//Replace to:
<img src="{{asset('icons/google-icon.svg')}}" >
//Find:
<link href="css/style.css">
//Replace to:
<link href="{{asset('css/style.css')}}">
/** etc... */
<a href="http://www.example.com">
EOT;
$doc = new DOMDocument();
$doc->loadHTML("<div>$html</div>", LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new DOMXPath($doc);
foreach ($xpath->query('//img') as $img) {
$src = $img->getAttribute('src');
if (preg_match('/^(?!{{\s*asset).*$/', $src, $m)) {
$img->setAttribute('src', "{{asset('" . $m[0] . ")'}}");
}
}
foreach ($xpath->query('//link') as $link) {
$href = $link->getAttribute('href');
if (preg_match('/^(?!{{\s*asset).*$/', $href, $m)) {
$link->setAttribute('href', "{{asset('" . $m[0] . ")'}}");
}
}
// strip XML header and added <div> tag
echo substr($doc->saveXML(), 44, -6);
输出:
//Find:
<img src="{{asset('icons/google-icon.svg)'}}"/>
//Replace to:
<img src="{{asset('icons/google-icon.svg')}}"/>
//Find:
<link href="{{asset('css/style.css)'}}"/>
//Replace to:
<link href="{{asset('css/style.css')}}"/>
/** etc... */
<a href="http://www.example.com"/>
TA贡献1803条经验 获得超3个赞
这可以/应该用 DomDocument 来完成。
还值得一提的是,在用于访问变异文档时,将花括号添加到属性字符串(它们被编码)时会产生错误的副作用。saveHTML()
要解决此问题,请使用saveXML()
并删除文档前面的 xml 标记。
我将您的示例标签包装在父标签中,以便 DomDocument 可以正常运行,而不会破坏您的文档结构。这可能是您的项目不必要的预防措施。
我的代码片段直接使用 XPath 定位符合条件的属性,并在没有任何正则表达式的情况下替换它们的值。我的 xpath 表达式中的竖线 ( |
) 表示“或”——因此它以 img 标签的 src 属性或链接标签的 href 属性为目标。
代码:
$html = <<<HTML
<div>
<img src="icons/example.svg">
<a href="http://www.example.com">a link</a>
<link href="css/example.css">
<iframe src="//www.example.com/default.htm"></iframe>
</div>
HTML;
$dom = new DOMDocument();
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new DOMXPath($dom);
foreach ($xpath->query('//img/@src | //link/@href') as $attr) {
$attr->value = "{{asset('" . $attr->value . "')}}";
}
echo substr($dom->saveXML(), 38); // remove the auto-generated xml tag from the start
输出:
<div>
<img src="{{asset('icons/example.svg')}}"/>
<a href="http://www.example.com">a link</a>
<link href="{{asset('css/example.css')}}"/>
<iframe src="//www.example.com/default.htm"/>
</div>
哎呀,我刚刚看到你问题中的最后一个请求。
not()
和的实现 starts-with()
应用于两个标签,以取消已经转换为小胡子代码的元素的资格。
新的 xpath 表达式:
//img[not(starts-with(@src,"{{asset"))]/@src | //link[not(starts-with(@href,"{{asset"))]/@href
- 2 回答
- 0 关注
- 93 浏览
添加回答
举报