php DomDocument добавляет дополнительные теги - PullRequest
9 голосов
/ 26 января 2011

Я пытаюсь разобрать документ, получить все теги изображений и изменить источник на что-то другое.


    $domDocument = new DOMDocument();

    $domDocument->loadHTML($text);

    $imageNodeList = $domDocument->getElementsByTagName('img');

    foreach ($imageNodeList as $Image) {
      $Image->setAttribute('src', 'lalala');
      $domDocument->saveHTML($Image);
    }

    $text = $domDocument->saveHTML();

Текст $ изначально выглядит так:


<p><p>Hi, this is a test, here is an image<img src="http://mysite.com/beer.jpg" width="60" height="95" /> Because I like Beer!</p></p>

и это вывод $ text:


<p><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"><br /><html><body><p>Hi, this is a test, here is an image<img src="lalala" width="68" height="95"> Because I like Beer!</p></body></html></p>

Я получаю кучу дополнительных тегов (html, body и комментарий вверху), которые мне не нужны. Любой способ настроить DOMDocument, чтобы избежать добавления этих дополнительных тегов?

Спасибо!

Ответы [ 5 ]

15 голосов
/ 15 июля 2015

Вам просто нужно добавить 2 флага в метод loadHTML(): LIBXML_HTML_NOIMPLIED|LIBXML_HTML_NODEFDTD.Т.е.

$domDocument->loadHTML($text, LIBXML_HTML_NOIMPLIED|LIBXML_HTML_NODEFDTD);

См. IDEONE demo :

$text = '<p>Hi, this is a test, here is an image<img src="http://example.com/beer.jpg" width="60" height="95" /> Because I like Beer!</p>';
$domDocument = new DOMDocument;
$domDocument->loadHTML($text, LIBXML_HTML_NOIMPLIED|LIBXML_HTML_NODEFDTD);
$imageNodeList = $domDocument->getElementsByTagName('img');

foreach ($imageNodeList as $Image) {
      $Image->setAttribute('src', 'lalala');
      $domDocument->saveHTML($Image);
}

$text = $domDocument->saveHTML();
echo $text;

Выход:

<p>Hi, this is a test, here is an image<img src="lalala" width="60" height="95"> Because I like Beer!</p>
5 голосов
/ 26 января 2011

DomDocument, к сожалению, отсталый и не позволит вам сделать это.Попробуйте это:

$text = preg_replace('/^<!DOCTYPE.+?>/', '', str_replace( array('<html>', '</html>', '<body>', '</body>'), array('', '', '', ''), $domDocument->saveHTML()));
1 голос
/ 26 января 2011

Если у вас есть возможность взломать, мне удалось обойти это раздражение Загрузите строку как XML и сохраните ее как HTML. :)

0 голосов
/ 13 января 2015

вы можете использовать http://beerpla.net/projects/smartdomdocument-a-smarter-php-domdocument-class/:

DOMDocument имеет крайне плохо разработанную «функцию», при которой, если загружаемый HTML-код не содержит и не содержит тегов, он добавляет их автоматически (да, нет флагов, чтобы отключить это поведение).

Таким образом, когда вы вызываете $ doc-> saveHTML (), ваш недавно сохраненный контент теперь имеет и DOCTYPE в нем. Не очень удобно при работе с фрагментами кода (в XML есть похожая проблема).

SmartDOMDocument содержит новую функцию saveHTMLExact (), которая делает именно то, что вам нужно - она ​​сохраняет HTML без добавления лишнего мусора, который делает DOMDocument.

0 голосов
/ 26 января 2011

Если вы собираетесь сохранить как HTML, вы должны ожидать, что будет создан действительный документ HTML!

Существует еще одна опция: DOMDocument::saveXML имеет необязательный параметр, позволяющий получить доступ к содержимому XML определенного элемента:

$el = $domDocument->getElementsByTagName('p')->item(0);
$text = $domDocument->saveXML($el);

Это предполагает, что ваш контент имеет только один p элемент.

...