Как избежать синтаксического анализа DOM, добавляя HTML doctype и теги?
<?
$string = '
Some photos<br>
<span class="naslov_slike">photo_by_ile_IMG_1676-01</span><br />
<span class="naslov_slike">photo_by_ile_IMG_1699-01</span><br />
<span class="naslov_slike">photo_by_ile_IMG_1697-01</span><br />
<span class="naslov_slike">photo_by_ile_IMG_1695-01</span><br />
';
$dom = new DOMDocument();
$dom->loadHTML($string);
$dom->preserveWhiteSpace = false;
$elements = $dom->getElementsByTagName('span');
$spans = array();
foreach($elements as $span) {
$spans[] = $span;
}
foreach($spans as $span) {
$span->parentNode->removeChild($span);
}
echo $dom->saveHTML();
?>
Я использую этот код для разбора строки. Когда строка возвращается этой функцией, она имеет некоторые добавленные теги:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p>Some photos<br><br><br><br><br></p></body></html>
есть ли способ избежать этого и вернуть чистую строку? Эта входная строка просто, например, в использовании это может быть любая строка html.
5 ответов
Я на самом деле ищу то же самое решение. Я использую метод innerHTML для этого, однако <p>
вокруг текстового узла все равно будет добавлен, когда вы сделаете loadHTML. Я не могу обойти это без использования другого парсера, или есть какой-то скрытый флаг, чтобы сказать ему не делать этого.
этот код:
<?php
function innerHTML($node){
$doc = new DOMDocument();
foreach ($node->childNodes as $child)
$doc->appendChild($doc->importNode($child, true));
return $doc->saveHTML();
}
$string = '
Some photos<br>
<span class="naslov_slike">photo_by_ile_IMG_1676-01</span><br />
<span class="naslov_slike">photo_by_ile_IMG_1699-01</span><br />
<span class="naslov_slike">photo_by_ile_IMG_1697-01</span><br />
<span class="naslov_slike">photo_by_ile_IMG_1695-01</span><br />
';
$dom = new DOMDocument();
$dom->preserveWhiteSpace = false;
$dom->loadHTML($string);
$elements = $dom->getElementsByTagName('span');
$spans = array();
foreach($elements as $span) {
$spans[] = $span;
}
foreach($spans as $span) {
$span->parentNode->removeChild($span);
}
echo innerHTML( $dom->documentElement->firstChild );
вывод:
<p>Some photos<br><br><br><br><br></p>
однако, конечно, это решение не сохраняет разметку 100% неповрежденной, но это закрывать.
после использования loadHTML вы можете сделать следующее:
# loadHTML causes a !DOCTYPE tag to be added, so remove it:
$dom->removeChild($dom->firstChild);
# it also wraps the code in <html><body></body></html>, so remove that:
$dom->replaceChild($dom->firstChild->firstChild->firstChild, $dom->firstChild);
на !DOCTYPE
тег будет удален, а первый тег внутри body
тег заменит html
- тег.
очевидно, это будет работать только если вас интересует только первый тег внутри body
, как и я, когда я столкнулся с этой проблемой. Но этот пример может быть адаптирован для копирования всего внутри body
С небольшим усилием.
Edit: Meh, nevermind. Мне нравится Медера решение.
вы всегда можете просто использовать регулярное выражение, чтобы удалить этот первый бит:
echo preg_replace("/<!DOCTYPE [^>]+>/", "", $dom->saveHTML());
из руководства: http://php.net/manual/en/domdocument.savehtml.php
$html_fragment = preg_replace('/^<!DOCTYPE.+?>/', '', str_replace( array('<html>', '</html>', '<body>', '</body>'), array('', '', '', ''), $dom->saveHTML()));
работает для меня.
Я не уверен, что любой из них будет работать, но вы можете попробовать использовать DOMImplementation::createDocument
при создании DOMDocument
- третий аргумент -DOCTYPE
вы хотите использовать.
кроме того, вместо saveHTML()
, вы могли бы попробовать saveXML()