Home » Php » How to insert HTML to PHP DOMNode?

How to insert HTML to PHP DOMNode?

Posted by: admin April 23, 2020 Leave a comment


Is there any way I can insert an HTML template to existing DOMNode without content being encoded?

I have tried to do that with:

$dom->createElement('div', '<h1>Hello world</h1>');
$dom->createTextNode('<h1>Hello world</h1>');

The output is pretty much the same, with only difference that first code would wrap it in a div.
I have tried to loadHTML from string but I have no idea how can I append it’s body content to another DOMDocument.

In javascript, this process seems to be quite simple and obvious.

How to&Answers:

It works with another DOMDocument for parsing the HTML code. But you need to import the nodes into the main document before you can use them in it:

$newDiv = $dom->createElement('div');
$tmpDoc = new DOMDocument();
foreach ($tmpDoc->getElementsByTagName('body')->item(0)->childNodes as $node) {
    $node = $dom->importNode($node, true);

And as a handy function:

function appendHTML(DOMNode $parent, $source) {
    $tmpDoc = new DOMDocument();
    foreach ($tmpDoc->getElementsByTagName('body')->item(0)->childNodes as $node) {
        $node = $parent->ownerDocument->importNode($node, true);

Then you can simply do this:

$elem = $dom->createElement('div');
appendHTML($elem, '<h1>Hello world</h1>');


You can use


// just some setup
$dom = new DOMDocument;
$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>');

// output
echo $dom->saveXml();


<?xml version="1.0"?>
<html><body><h1>This is <em>my</em> template</h1></body></html>

If you want to import from another DOMDocument, replace the three lines with

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

Using TRUE as the second argument to importNode will do a recursive import of the node tree.

If you need to import (malformed) HTML, change loadXml to loadHTML. This will trigger the HTML parser of libxml (what ext/DOM uses internally):

$tpl = new DOMDocument;
$tpl->loadHtml('<h1>This is <em>malformed</em> template</h2>');
$body->appendChild($dom->importNode($tpl->documentElement, TRUE));

Note that libxml will try to correct the markup, e.g. it will change the wrong closing </h2> to </h1>.


As I do not want to struggle with XML, because it throws errors faster and I am not a fan of prefixing an @ to prevent error output. The loadHTML does the better job in my opinion and it is quite simple as that:

$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

// final output
echo $doc->saveHTML();


Here is simple example by using DOMDocumentFragment:

$doc = new DOMDocument();
$f = $doc->createDocumentFragment();
echo $doc->saveXML();

Here is helper function for replacing 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(); 

Source: Some old “PHP5 Dom Based Template” article.

And here is another suggestion posted by Pian0_M4n to use value attribute as workaround:

$dom = new DomDocument;

// main object
$object = $dom->createElement('div');

// html attribute
$attr = $dom->createAttribute('value');
// ugly html string
$attr->value = "<div>&nbsp; this is a really html string &copy;</div><i></i> with all the &copy; that XML hates!";

// jquery fix (or javascript as well)
$('div').html($(this).attr('value')); // and it works! 
$('div').removeAttr('value'); // to clean-up

No ideal, but at least it works.


Gumbo’s code works perfectly! Just a little enhancement that adding the TRUE parameter so that it works with nested html snippets.

$node = $parent->ownerDocument->importNode($node);
$node = $parent->ownerDocument->importNode($node, **TRUE**);