Есть вот такой код на php. С помощью DOMDocument ищу все теги img потом прохожу в цикле над ними и делаю изменение.
Проблема в том что в html с которым я работаю есть 5 тегов img. А цикл проходит 3 раза.
В чем может быть проблема?
$dom = new DOMDocument();
$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$imgs_t = $dom->getElementsByTagName('img');
$amp_img_src = '/images/front/what_is_dt_video.jpg';
$count_foreach = 0;
foreach( $imgs_t as $img_t ){
$count_foreach++;
$img_alt = '';
$tmp_img_src = $img_t->getAttribute('src');
$img_alt = $img_t->getAttribute('alt');
if($tmp_img_src != $amp_img_src){
$tmp_amp_img = $dom->createElement('amp-img');
$tmp_amp_img->setAttribute('width', 200);
$tmp_amp_img->setAttribute('height', 200);
$tmp_amp_img->setAttribute('src', $tmp_img_src);
$tmp_amp_img->setAttribute('alt', $img_alt);
$img_t->parentNode->replaceChild($tmp_amp_img, $img_t);
}
}
var_dump($count_foreach);
А это именно тот html который входит в переменную $html в начале php кода.
<div class="what_is_dt drop_down_pg">
<div class="drop_down_video drop_down_cont">
<div class="col-sm-7 col-xs-12">
<div class="video_wrap">
<div id="ntx_dt_info_video_link" class="no-padding">
<img src="/images/front/what_is_dt_video.jpg" height="315px" width="481px" alt="Lorem ipsum">
</div>
<div class="what_fx_video_head">
<span>Lorem ipsum</span>
</div>
</div>
</div>
<div class="col-sm-5 col-xs-12 no-padding">
<span class="background_green">
<h2>Lorem ipsum</h2>
<p><em>Lorem ipsum</em></p>
<p><em>Lorem ipsum</em></p>
</span>
[T]CONFIRM_THEORY[/T]
</div>
[T]CONFIRM_THEORY_MOBILE[/T]
<hr />
</div>
<h2 style="margin-top: 40px;"><strong>Lorem ipsum</strong></h2>
<div style="padding-top: 30px;">
<div class="signature-left col-lg-6 col-md-6 col-sm-6 col-xs-12">
<img src="/uploads/docs/th%20Failure%20Swing.png" alt="Lorem ipsum" title="Lorem ipsum" width="200" height="200" />
<span style="font-size: small;"> <strong>Lorem ipsum.</strong></span>
<span style="font-size: small;">Lorem ipsum. </span>
</div>
<div class="signature-left col-lg-6 col-md-6 col-sm-6 col-xs-12">
<img src="/uploads/docs/th%20Nonfailure%20Swing.png" alt="Lorem ipsum" width="200" height="200"/>
<span style="font-size: small;"><strong>Lorem ipsum.</strong> </span>
<span style="font-size: small;">Lorem ipsum.</span>
</div>
</div>
<p style="clear: both; padding-top: 30px;" >Lorem ipsum.</p>
<div style="padding-top: 30px;">
<div class="signature-left col-lg-6 col-md-6 col-sm-6 col-xs-12">
<img src="/uploads/docs/th Failure Swing Bottom.png" alt="" />
<p><span style="font-size: small;"><strong>Failure Swing </strong>Lorem ipsum.</span></p>
</div>
<div class="signature-left col-lg-6 col-md-6 col-sm-6 col-xs-12">
<img src="/uploads/docs/th Nonfailure Swing Bottom.png" alt="Lorem ipsum" width="200" height="200" />
<p><span style="font-size: small;"><strong>Nonfailure Swing</strong>Lorem ipsum.</span></p>
</div>
</div>
<p style="clear: both;"><br /></p>
[T]OUR_LEARNING[/T]
</div>
в общем и целом проблема выглядит вот так, если сократить до минимального примера.
$html = <<<HTML
<div class="what_is_dt drop_down_pg">
<img src="1">
<img src="2">
<img src="3">
<img src="4">
<img src="5">
</div>
HTML;
$dom = new DOMDocument();
$dom->loadHTML($html);
$imgs_t = $dom->getElementsByTagName('img');
print_r($imgs_t);
$amp_img_src = '/images/front/what_is_dt_video.jpg';
$count_foreach = 0;
foreach( $imgs_t as $img_t ){
$count_foreach++;
$tmp_img_src = $img_t->getAttribute('src');
print_r([$count_foreach, $tmp_img_src]);
if($tmp_img_src != $amp_img_src){
$tmp_amp_img = $dom->createElement('amp-img');
$img_t->parentNode->replaceChild($tmp_amp_img, $img_t);
}
}
что тут происходит. вы находите все 5 элементов. начинаете перебор. На первой итерации выполняется условие и вы заменяете первый узел. дальше бы должен быть переход ко второму узлу исходной коллекции, но она у нас изменена, и теперь второй узел измененной коллекции будет соответствовать третьему узлу исходной. таким образом второй узел исходной у нас как бы теряется. Как именно и что ломается я полностью объяснить не могу, но вопрос к реализации итератора.
В целом вы можете менять структуру если будете проходить эту коллекцию в обратном порядке. Тут в принципе такая классическая проблема удаления элементов массиве в цикле, если удаляете, обрабатывайте в обратном порядке, тогда удаление узлов никак не скажется на индексации массива еще не обработанных элементов
$len = $imgs_t->length;
for($i = $len-1; $i >=0 ; $i--){
$count_foreach++;
$img_t = $imgs_t->item($i);
...
}
если представить, что наша коллекция была
A B C D E
выполняем первую итерацию. индекс итератора 0, элемент А. Мы удаляем этот элемент, и коллеакция становится
B C D E
переходим к новой итерации, счетчик итератора ничего не знает, и увеличивается на 1. Извлекаем этот элемент и получаем C.
В итоге получаем, что за счет удаления(замены) первого элемента мы теряем элемент B. В случае обработки коллекции в обратно порядке такой проблемы не возникает.
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости