Skip to content Skip to sidebar Skip to footer

How To Replace Img Src And Link Href In A Document With A Mustache Expression?

I trying to replace the src,href value but with a small modified using regex Simple example //Find: //Replace to:

Solution 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> tagecho substr($doc->saveXML(), 44, -6);

Output:

//Find:
<img src="{{asset('icons/google-icon.svg)'}}"/> 
//Replace to: <imgsrc="{{asset('icons/google-icon.svg')}}"/>//Find:<linkhref="{{asset('css/style.css)'}}"/>//Replace to: <linkhref="{{asset('css/style.css')}}"/>/** etc... */<ahref="http://www.example.com"/>

Demo on 3v4l.org

Solution 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><imgsrc="{{asset('icons/example.svg')}}"/><ahref="http://www.example.com">a link</a><linkhref="{{asset('css/example.css')}}"/><iframesrc="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

Post a Comment for "How To Replace Img Src And Link Href In A Document With A Mustache Expression?"