Как вставить HTML в PHP DOMNode?
Есть ли способ вставить HTML-шаблон в существующий DOMNode без кодирования содержимого?
Я попытался сделать это с помощью
$dom->createElement('div', '<h1>Hello world</h1>');
$dom->createTextNode('<h1>Hello world</h1>');
Вывод практически такой же, с той лишь разницей, что первый код обернет его в div.
Я попытался загрузитьHTML из строки, но я понятия не имею, как добавить его содержимое тела в другой DOMDocument.
В javascript этот процесс кажется довольно простым и очевидным.
Ответы
Ответ 1
Он работает с другим DOMDocument для анализа кода HTML. Но вам нужно импортировать узлы в основной документ, прежде чем вы сможете использовать их в нем:
$newDiv = $dom->createElement('div');
$tmpDoc = new DOMDocument();
$tmpDoc->loadHTML($str);
foreach ($tmpDoc->getElementsByTagName('body')->item(0)->childNodes as $node) {
$node = $dom->importNode($node, true);
$newDiv->appendChild($node);
}
И как удобная функция:
function appendHTML(DOMNode $parent, $source) {
$tmpDoc = new DOMDocument();
$tmpDoc->loadHTML($source);
foreach ($tmpDoc->getElementsByTagName('body')->item(0)->childNodes as $node) {
$node = $parent->ownerDocument->importNode($node, true);
$parent->appendChild($node);
}
}
Тогда вы можете просто сделать это:
$elem = $dom->createElement('div');
appendHTML($elem, '<h1>Hello world</h1>');
Ответ 2
Вы можете использовать
Пример:
// just some setup
$dom = new DOMDocument;
$dom->loadXml('<html><body/></html>');
$body = $dom->documentElement->firstChild;
// this is the part you are looking for
$template = $dom->createDocumentFragment();
$template->appendXML('<h1>This is <em>my</em> template</h1>');
$body->appendChild($template);
// output
echo $dom->saveXml();
Вывод:
<?xml version="1.0"?>
<html><body><h1>This is <em>my</em> template</h1></body></html>
Если вы хотите импортировать из другого DOMDocument, замените три строки на
$tpl = new DOMDocument;
$tpl->loadXml('<h1>This is <em>my</em> template</h1>');
$body->appendChild($dom->importNode($tpl->documentElement, TRUE));
Использование TRUE
в качестве второго аргумента importNode
сделает рекурсивный импорт дерева node.
Если вам нужно импортировать (искаженный) HTML, измените loadXml
на loadHTML
. Это запустит HTML-парсер libxml (что внутреннее приложение ext/DOM):
libxml_use_internal_errors(true);
$tpl = new DOMDocument;
$tpl->loadHtml('<h1>This is <em>malformed</em> template</h2>');
$body->appendChild($dom->importNode($tpl->documentElement, TRUE));
libxml_use_internal_errors(false);
Обратите внимание, что libxml попытается исправить разметку, например. он изменит неправильное закрытие </h2>
на </h1>
.
Ответ 3
Как я не хочу бороться с XML, потому что он быстрее порождает ошибки, и я не поклонник префикса @для предотвращения вывода ошибок. НагрузкаHTML делает лучшую работу, на мой взгляд, и это довольно просто:
$doc = new DOMDocument();
$div = $doc->createElement('div');
// use a helper to load the HTML into a string
$helper = new DOMDocument();
$helper->loadHTML('<a href="#">This is my HTML Link.</a>');
// now the magic!
// import the document node of the $helper object deeply (true)
// into the $div and append as child.
$div->appendChild($doc->importNode($helper->documentElement, true));
// add the div to the $doc
$doc->appendChild($div);
// final output
echo $doc->saveHTML();
Ответ 4
Вот простой пример, используя DOMDocumentFragment:
$doc = new DOMDocument();
$doc->loadXML("<root/>");
$f = $doc->createDocumentFragment();
$f->appendXML("<foo>text</foo><bar>text2</bar>");
$doc->documentElement->appendChild($f);
echo $doc->saveXML();
Вот вспомогательная функция для замены DOMNode:
/**
* Helper function for replacing $node (DOMNode)
* with an XML code (string)
*
* @var DOMNode $node
* @var string $xml
*/
public function replaceNodeXML(&$node, $xml) {
$f = $this->dom->createDocumentFragment();
$f->appendXML($xml);
$node->parentNode->replaceChild($f,$node);
}
Источник: некоторая старая статья на основе PHP5 на основе сайта.
И вот еще одно предложение, опубликованное Pian0_M4n, чтобы использовать атрибут value в качестве обходного пути:
$dom = new DomDocument;
// main object
$object = $dom->createElement('div');
// html attribute
$attr = $dom->createAttribute('value');
// ugly html string
$attr->value = "<div> this is a really html string ©</div><i></i> with all the © that XML hates!";
$object->appendChild($attr);
// jquery fix (or javascript as well)
$('div').html($(this).attr('value')); // and it works!
$('div').removeAttr('value'); // to clean-up
Не идеален, но, по крайней мере, он работает.
Ответ 5
Gumbo code отлично работает! Просто небольшое улучшение, добавляющее параметр TRUE, чтобы он работал с вложенными фрагментами html.
$node = $parent->ownerDocument->importNode($node);
$node = $parent->ownerDocument->importNode($node, **TRUE**);