如何用小胡子表达式替换文档中的 img src 和 link href?
How to replace img src and link href in a document with a mustache expression?
我尝试替换 src
、href
值,但使用 regex
进行了小的修改
简单示例
//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... */
现在这是我的正则表达式:
//Find:
src\s*=\s*"(.+?)"
//Replace to:
src="{{ asset('') }}"
它的工作实际上非常好,但它仅适用于 src
而不是 [href
,src
],而且我想排除包含 {{asset
[ 的任何值=20=]
有什么想法吗?提前致谢
您可以使用交替来匹配 src
或 href
,然后使用否定前瞻来断言 src/href 不以 {{asset
开头:
((?:src|href)\s*=\s*")((?!{{\s*asset)[^"]+)
这还将更改 <a>
标签内或其他地方的 href
属性。如果这是一个问题,请改用 DOMDocument
解决方案。请注意,如果您的 HTML 不仅仅是一个片段,那么您不需要在对 loadHTML
的调用中在其周围添加 div
标记,并且最后一行应更改为 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"/>
Nick 是正确的 can/should 使用 DomDocument 完成。
另外值得一提的是 a buggy side-effect when adding curly braces to the attribute strings (they get encoded) when using saveHTML()
访问变异文档。要解决此问题,请使用 saveXML()
并 trim 去掉文档前面的 xml 标签。
我将您的示例标签包装在父标签中,这样 DomDocument 就可以正常运行,而不会破坏您的文档结构。这对您的项目来说可能是不必要的预防措施。
我的代码片段使用 XPath 直接定位符合条件的属性,并在没有任何正则表达式的情况下替换它们的值。我的 xpath 表达式中的管道 (|
) 表示 "or" - 因此它针对 img 标签的 src 属性或 link 标签的 href 属性。
代码:(Demo)
$html = <<<HTML
<div>
<img src="icons/example.svg">
<a href="http://www.example.com">a link</a>
<link href="css/example.css">
<iframe src="http://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="http://www.example.com/default.htm"/>
</div>
糟糕,我刚刚看到你问题中的最后一个请求。
not()
和 starts-with()
的实施应用于这两个标记,以取消已转换为小胡子代码的元素的资格。
新的 xpath 表达式:(Demo)
//img[not(starts-with(@src,"{{asset"))]/@src | //link[not(starts-with(@href,"{{asset"))]/@href
我尝试替换 src
、href
值,但使用 regex
简单示例
//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... */
现在这是我的正则表达式:
//Find:
src\s*=\s*"(.+?)"
//Replace to:
src="{{ asset('') }}"
它的工作实际上非常好,但它仅适用于 src
而不是 [href
,src
],而且我想排除包含 {{asset
[ 的任何值=20=]
有什么想法吗?提前致谢
您可以使用交替来匹配 src
或 href
,然后使用否定前瞻来断言 src/href 不以 {{asset
开头:
((?:src|href)\s*=\s*")((?!{{\s*asset)[^"]+)
这还将更改 <a>
标签内或其他地方的 href
属性。如果这是一个问题,请改用 DOMDocument
解决方案。请注意,如果您的 HTML 不仅仅是一个片段,那么您不需要在对 loadHTML
的调用中在其周围添加 div
标记,并且最后一行应更改为 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"/>
Nick 是正确的 can/should 使用 DomDocument 完成。
另外值得一提的是 a buggy side-effect when adding curly braces to the attribute strings (they get encoded) when using saveHTML()
访问变异文档。要解决此问题,请使用 saveXML()
并 trim 去掉文档前面的 xml 标签。
我将您的示例标签包装在父标签中,这样 DomDocument 就可以正常运行,而不会破坏您的文档结构。这对您的项目来说可能是不必要的预防措施。
我的代码片段使用 XPath 直接定位符合条件的属性,并在没有任何正则表达式的情况下替换它们的值。我的 xpath 表达式中的管道 (|
) 表示 "or" - 因此它针对 img 标签的 src 属性或 link 标签的 href 属性。
代码:(Demo)
$html = <<<HTML
<div>
<img src="icons/example.svg">
<a href="http://www.example.com">a link</a>
<link href="css/example.css">
<iframe src="http://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="http://www.example.com/default.htm"/>
</div>
糟糕,我刚刚看到你问题中的最后一个请求。
not()
和 starts-with()
的实施应用于这两个标记,以取消已转换为小胡子代码的元素的资格。
新的 xpath 表达式:(Demo)
//img[not(starts-with(@src,"{{asset"))]/@src | //link[not(starts-with(@href,"{{asset"))]/@href