Reputation: 1202
I have an HTML with a number of images inside it. Suppose I have one url which is of one of the images inside the HTML content. What if I have to replace the image inside HTML with some custom text in PHP?
<div>
<p>Some text<img src="a.jpg" class="testclass" alt="image" title="image"/></p>
<p>Some more text<img src="b.jpg" class="testclass2" alt="image2" title="image2"/></p>
</div>
And suppose I have to replace <img src="a.jpg" class="testclass" alt="image" title="image"/>
with some custom text but the only information I have is the image URL i.e "a.jpg". How to do it in PHP?
Upvotes: 1
Views: 1269
Reputation: 351369
Using regular expressions for this is not the ideal solution. Such expressions can become very complicated to deal with quotes, white space, attribute order, scripts,... etc in HTML.
The preferred method is to use a DOM parser, which PHP offers out-of-the-box.
Here is some code you could use to get what you want:
// main function: pass it the DOM, image URL and replacement text
function DOMreplaceImagesByText($dom, $img_src, $text) {
foreach($dom->getElementsByTagName('img') as $img) {
if ($img->getAttribute("src") == "a.jpg") {
$span = $dom->createElement("span", $text);
$img->parentNode->replaceChild($span, $img);
};
}
}
// utility function to get innerHTML of an element
function DOMinnerHTML($element) {
$innerHTML = "";
foreach ($element->childNodes as $child) {
$innerHTML .= $element->ownerDocument->saveHTML($child);
}
return $innerHTML;
}
// test data
$html = '<div>
<p>Some text<img src="a.jpg" class="testclass" alt="image" title="image"/></p>
<p>Some more text<img src="b.jpg" class="testclass2" alt="image2" title="image2"/></p>
</div>';
// create DOM for given HTML
$dom = new DOMDocument();
$dom->loadHTML($html);
// call our function to make the replacement(s)
DOMreplaceImagesByText($dom, "a.jpg", "custom text");
// convert back to HTML
$html = DOMinnerHTML($dom->getElementsByTagName('body')->item(0));
// show result (for demo only, in reality you would not use htmlentities)
echo htmlentities($html);
The above code will output:
<div>
<p>Some text<span>custom text</span></p>
<p>Some more text<img src="b.jpg" class="testclass2" alt="image2" title="image2"></p>
</div>
As stated above, regular expressions are not well-suited for this job, but I will provide you one just for completeness sake:
function HTMLreplaceImagesByText($html, $img_src, $text) {
// escape special characters in $img_src so they work as
// literals in the main regular expression
$img_src = preg_replace("/(\W)/", "\\\\$1", $img_src);
// main regular expression:
return preg_replace("/<img[^>]*?\ssrc\s*=\s*[\'\"]" . $img_src
. "[\'\"].*?>/si", "<span>$text</span>", $html);
}
$html = '<div>
<p>Some text<img src="a.jpg" class="testclass" alt="image" title="image"/></p>
<p>Some more text<img src="b.jpg" class="testclass2" alt="image2" title="image2"/></p>
</div>';
$html = HTMLreplaceImagesByText($html, "a.jpg", "custom text");
echo htmlentities($html);
The output will be the same as with the DOM parsing solution. But it will fail in many specific situations, where the DOM solution will not have any problem. For instance, if a matching image tag appears in a comment or as a string within a script tag, it will make the replacement, while it shouldn't. Worse, when the matching image tag has a greater-than sign in an attribute value, the replacement will produce wrong results.
There are many other instances where it will go wrong.
Upvotes: 3