I'm having a weird issue trying to append an image element to a noscript element using php DomDocument.
If I create a new div node I can append it without issue to the noscript element but as soon as a try to append an image element the script just times out.
What am I doing wrong?
<?php
$html = '<!DOCTYPE html><html><head><title>Sample</title></head><body><img src="https://example.com/images/example.jpg"></body></html>';
$doc = new DOMDocument();
$doc->loadHTML($html);
$images = $doc->getElementsByTagName('img');
foreach ($images as $image) {
$src = $image->getAttribute('src');
$noscript = $doc->createElement('noscript');
$node = $doc->createElement('div');
//$node = $doc->createElement('img'); If a uncomment this line the script just times out
$node->setAttribute('src', $src);
$noscript->appendChild($node);
$image->setAttribute('x-data-src', $src);
$image->removeAttribute('src');
$image->parentNode->appendChild($noscript);
//$image->parentNode->appendChild($newImage);
}
$body = $doc->saveHTML();
echo $body;
1getElementsByTagName returns a live NodeList, at least according to DOM specification. If that is true for PHP/DomDocuments implementation as well, then I am not sure whether it's a good idea to loop over such a NodeList while moving around elements inside it ... – CBroeMay 23 '17 at 23:09
if you comment that out, the recursion goes away. Notice that when it recurses, the x-data-src is being applied to all but the last one.
I haven't quite figured out what is causing this behaviour, but hopefully being able to visualize it will help you diagnose it further.
**UPDATE
The OP took this and ran with it, and completed the answer with his solution as shown below.
The problem was in fact that getElementsByTagName returns a LiveNodeList so appending an image to the doc will cause the infinite recursion.
I solved it by first collecting all the image tags in a simple array
<?php
$html = '<!DOCTYPE html><html><head><title>Sample</title></head><body><img src="https://example.com/images/example.jpg"></body></html>';
$doc = new DOMDocument();
$doc->loadHTML($html);
$images = $doc->getElementsByTagName('img');
$normal_array = [];
foreach ($images as $image) {
$normal_array[] = $image;
}
// Now we have all tags in a simple array NOT in a Live Node List
foreach ($normal_array as $image) {
$src = $image->getAttribute('src');
$noscript = $doc->createElement('noscript');
$node = $doc->createElement('img'); //If a uncomment this line the script just times out
$node->setAttribute('src', $src);
$noscript->appendChild($node);
$image->setAttribute('x-data-src', $src);
$image->removeAttribute('src');
$image->parentNode->appendChild($noscript);
//$image->parentNode->appendChild($newImage);
}
$body = $doc->saveHTML();