Php DOMDocument: элемент заканчивается внутри другого

У меня есть HTML-код, который содержит (среди прочего) p-теги и figure-теги, содержащие один img-тег.
Для простоты я определю пример того, что можно найти в HTML здесь, в переменной PHP:

$content = '<figure class = "image image-style-align-left">
<img src = "https://placekitten.com/g/200/300"></figure>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</p>';

Я использую DOMDocument для получения $content, и в этом примере я изменю атрибут src всех img-элементов внутри figure-элемента:

$dom = new DOMDocument();
libxml_use_internal_errors(true);

// this needs to be encoded otherwise special characters get messed up.
$domPart = mb_convert_encoding($content, 'HTML-ENTITIES', "UTF-8");
$dom->loadHTML($domPart, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

$domFigures = $dom->getElementsByTagName('figure');

foreach ($domFigures as $domFigure) {

    $img = $domFigure->getElementsByTagName('img')[0];
    if ($img) {
        $img->setAttribute('src', "https://placekitten.com/g/400/500");
    }

}

$result = $dom->saveHTML();

Результат:

<figure class = "image image-style-align-left">
<img src = "https://placekitten.com/g/400/500">
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</p>
</figure>

Каким-то образом мой p-элемент переместился в мой figure-элемент. Почему это происходит и что я могу сделать, чтобы предотвратить это?

Живая ДЕМО

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
0
78
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Перестановка выполняется с помощью опции LIBXML_HTML_NOIMPLIED, которую вы используете. Похоже, он недостаточно стабилен для вашего случая.

Посмотрите на этот ответ: loadHTML LIBXML_HTML_NOIMPLIED для фрагмента html генерирует неправильные теги А также Как сохранить HTML из DOMDocument без HTML-оболочки?

Примечание: в PHP 5.4 и Libxml 2.6 loadHTML теперь имеет параметр $option, который указывает Libxml, как следует анализировать содержимое.

Ответ принят как подходящий

DomDocument должен иметь один корневой элемент, поэтому он будет перемещать всех следующих братьев и сестер внутри первого элемента верхнего уровня.

Вы можете проще всего решить эту проблему, добавив в свой контент тег контейнера, например.

$content = '<div><figure class = "image image-style-align-left">
<img src = "https://placekitten.com/g/200/300"></figure>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</p></div>';

Другие вопросы по теме