Search code examples
phpdomdomdocumentphp-7

Importing one DOMDocument into another


I am attempting to merge 2 html documents, A and B. A should basically integrate B. Consider the following code:

$domA = new DOMDocument();
$domA->loadHTMLFile('foo/bar/A.html');

$domB = new DOMDocument();
$domB->loadHTMLFile('foo/bar/B.html');

$elementToReplace = /*some element in $domA*/;

$domA->importNode($domB, true); /*<-- error occuring here: Node Type Not Supported*/
$domA->replaceChild($domB, $elementToReplace);

I don't really understand why importNode wouldn't work on a DOMDocument object as it is a subclass of DOMNode in PHP, which the importNode()-function requires as an argument. (importNode(), DOMDocument)

I have already been looking at some of the similar questions but wasn't able to find anything that would have helped me in this situation.


Solution

  • You are trying to use the DOMDocument $domB as the imported node, instead you need to import the content - $domB->documentElement is the root element.

    A quick example (with comments) as to how to use it...

    $domA = new DOMDocument();
    $domA->loadHTMLFile('a.html');
    $domB = new DOMDocument();
    $domB->loadHTMLFile('b.html');
    
    // Find the point to replace with new content
    $elementToReplace = $domA->getElementById("InsertHere");
    
    // Import the base of the new document as $newNode
    $newNode = $domA->importNode($domB->documentElement, true);
    // Using the element to replace, move up a level and replace
    $elementToReplace->parentNode->replaceChild($newNode, $elementToReplace);
    echo $domA->saveHTML();
    

    with a.html...

    <html>
    <head></head>
    <body>
      <div id="InsertHere" />
    </body>
    </html>
    

    and b.html

    <div>New content to insert</div>
    

    Will give ...

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
    <html><head></head><body>
      <html><body><div>New content to insert</div></body></html>
    </body></html>
    

    Note as you are using loadHTMLFile() it has wrapped even the small fragment of HTML into a full page. If instead you use...

    $domB->load('b.html');
    

    the result is...

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
    <html><head></head><body>
      <div>New content to insert</div>
    </body></html>
    

    Note that using load() though is loading XML and is much less forgiving of the document structure than it's loadHTML() counterpart.