How to replace img src and link href in a document with a mustache expression?

让人想犯罪 __ 提交于 2021-02-11 16:29:29

问题


I trying to replace the src,href value but with a small modified using regex

Simple example

//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... */

Now this is my regex:

//Find:
src\s*=\s*"(.+?)" 
//Replace to:
src="{{ asset('$1') }}"

And its work very great actually but its only for src not [href,src], also I want to exclude any value that contains {{asset

Any idea? Thanks in advance


回答1:


You can use an alternation to match src or href, and then a negative lookahead to assert that the src/href doesn't start with {{asset:

((?:src|href)\s*=\s*")((?!{{\s*asset)[^"]+)

Demo on regex101

This will also change href attributes inside <a> tags or elsewhere. If that is an issue, use a DOMDocument solution instead. Note that if your HTML is not just a snippet then you don't need to add the div tag around it in the call to loadHTML and the last line should be changed to 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);

Output:

//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"/>

Demo on 3v4l.org




回答2:


Nick is correct that this can/should be done with DomDocument.

Also worth mentioning is a buggy side-effect when adding curly braces to the attribute strings (they get encoded) when using saveHTML() to access the mutated document. To workaround this, use saveXML() and just trim away the xml tag that is prepended to the document.

I am wrapping your sample tags in a parent tag so that DomDocument can function normally and not mangle your document structure. This might be an unnecessary precaution for your project.

My snippet directly targets the qualifying attributes using XPath and replaces their values without any regex. The pipe (|) in my xpath expression means "or" -- so it targets the img tags' src attribute OR the link tags' href attribute.

Code: (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

Output:

<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>

Whoops, I just saw the last request in your question.

The implementation of not() and starts-with() are applied to both tags to disqualify elements that are already converted to mustache code.

New xpath expression: (Demo)

//img[not(starts-with(@src,"{{asset"))]/@src | //link[not(starts-with(@href,"{{asset"))]/@href


来源:https://stackoverflow.com/questions/61966467/how-to-replace-img-src-and-link-href-in-a-document-with-a-mustache-expression

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!