如何将HTML插入PHP DOMNode?

Naz*_*riy 28 html php dom domdocument

有没有什么方法可以在没有内容编码的情况下将HTML模板插入现有DOMNode?

我试过这样做:

$dom->createElement('div', '<h1>Hello world</h1>');
$dom->createTextNode('<h1>Hello world</h1>');
Run Code Online (Sandbox Code Playgroud)

输出几乎相同,唯一的区别是第一个代码将它包装在div中.我试图从字符串加载HTML,但我不知道如何将它的正文内容附加到另一个DOMDocument.

在javascript中,这个过程看起来非常简单明了.

Gor*_*don 41

您可以使用

例:

// 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();
Run Code Online (Sandbox Code Playgroud)

输出:

<?xml version="1.0"?>
<html><body><h1>This is <em>my</em> template</h1></body></html>
Run Code Online (Sandbox Code Playgroud)

如果要从另一个DOMDocument导入,请将三行替换为

$tpl = new DOMDocument;
$tpl->loadXml('<h1>This is <em>my</em> template</h1>');
$body->appendChild($dom->importNode($tpl->documentElement, TRUE));
Run Code Online (Sandbox Code Playgroud)

使用TRUE第二个参数importNode将对节点树进行递归导入.


如果您需要导入(格式错误的)HTML,请更改loadXmlloadHTML.这将触发libxml的HTML解析器(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);
Run Code Online (Sandbox Code Playgroud)

需要注意的是的libxml将设法改正的标记,例如,它会改变错误的收盘</h2></h1>.

  • @Nate`appendXml`期望格式良好的XML.如果你想附加格式错误的html,你必须调整第二种方法来使用html加载器.与流行的看法相反,libxml可以在很大程度上解析格式错误的标记. (2认同)
  • @AaronGillion我不确定你的意思.[这适用于"嵌套HTML"](http://codepad.org/1BdMONzX).你能提供一个你觉得它不起作用的小例子吗?我会帮你搞清楚的. (2认同)

Gum*_*mbo 28

它与另一个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);
}
Run Code Online (Sandbox Code Playgroud)

并作为一个方便的功能:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以简单地这样做:

$elem = $dom->createElement('div');
appendHTML($elem, '<h1>Hello world</h1>');
Run Code Online (Sandbox Code Playgroud)

  • foreach中的代码不起作用..因为importNode()返回对属于原始DOMDocument的NEW节点的引用,因此,为了能够追加它,你应该保留该引用..你当前在做什么正在使用该节点并尝试将tmpDoc的节点附加到属于原始文档的$ parent.正确的过程是:`$ importedNode = $ parent-> ownerDocument-> importNode($ node,TRUE); $父 - >的appendChild($ importedNode);` (9认同)
  • [DOMDocument::loadHTML()](http://www.php.net/manual/en/domdocument.loadhtml.php#88864) 的评论中提到了我在使用此解决方案时遇到的一个问题,如果`$ str`(或 `$source`,在你的第二个例子中)包含任何 **not** 包含在 HTML 元素中的文本,它将被包裹在 `&lt;p&gt;` 标签中。有什么方法可以阻止`loadHTML()` 在实际文本节点上放置`&lt;p&gt;` 标签? (2认同)

Mar*_*ler 5

因为我不想与XML斗争,因为它会更快地抛出错误而且我不喜欢为@添加前缀以防止错误输出.在我看来,loadHTML做得更好,而且非常简单:

$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();
Run Code Online (Sandbox Code Playgroud)

  • 与“LIBXML_HTML_NODEFDTD |”一起正常工作 LIBXML_HTML_NOIMPLIED` (2认同)