I am parsing html in the $content
variable with the DOMDocument to replace all iframes with images. The foreach is only replacing the ODD iframes. I have removed all the code in the foreach and found the piece of code causing this is: '$iframe->parentNode->replaceChild($link, $iframe);'
Why would the foreach be skipping all of the odd iframes?
The code:
$count = 1;
$dom = new DOMDocument;
$dom->loadHTML($content);
$iframes = $dom->getElementsByTagName('iframe');
foreach ($iframes as $iframe) {
$src = $iframe->getAttribute('src');
$width = $iframe->getAttribute('width');
$height = $iframe->getAttribute('height');
$link = $dom->createElement('img');
$link->setAttribute('class', 'iframe-'.self::return_video_type($iframe->getAttribute('src')).' iframe-'.$count.' iframe-ondemand-placeholderImg');
$link->setAttribute('src', $placeholder_image);
$link->setAttribute('height', $height);
$link->setAttribute('width', $width);
$link->setAttribute('data-iframe-src', $src);
$iframe->parentNode->replaceChild($link, $iframe);
echo "here:".$count;
$count++;
}
$content = $dom->saveHTML();
return $content;
This is the problem line of code
$iframe->parentNode->replaceChild($link, $iframe);
A DOMNodeList, such as that returned from getElementsByTagName
, is "live":
that is, changes to the underlying document structure are reflected in all relevant NodeList... objects
So when you remove the element (in this case by replacing it with another one) it no longer exists in the node list, and the next one in line takes its position in the index. Then when foreach
hits the next iteration, and hence the next index, one will be effectively skipped.
Don't remove elements from the DOM via foreach
like this.
An approach that works instead would be to use a while
loop to iterate and replace until your $iframes
node list is empty.
while ($iframes->length) {
$iframe = $iframes->item(0);
$src = $iframe->getAttribute('src');
$width = $iframe->getAttribute('width');
$height = $iframe->getAttribute('height');
$link = $dom->createElement('img');
$link->setAttribute('class', 'iframe-'.self::return_video_type($iframe->getAttribute('src')).' iframe-'.$count.' iframe-ondemand-placeholderImg');
$link->setAttribute('src', $placeholder_image);
$link->setAttribute('height', $height);
$link->setAttribute('width', $width);
$link->setAttribute('data-iframe-src', $src);
$iframe->parentNode->replaceChild($link, $iframe);
echo "here:".$count;
$count++;
}
Faced this issue today, and guide by the answer, i make a simple code solution for you guys
$iframes = $dom->getElementsByTagName('iframe');
for ($i=0; $i< $iframes->length; $i++) {
$iframe = $iframes->item($i);
if("condition to replace"){
// do some replace thing
$i--;
}
}
Hope this help.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With