Accessing the imported element after destroying the original DOMDocument

I've been messing around with DOMDocument lately and I've noticed that in order to transfer elements from one document to another, I have to call $DOMDocument->importNode()

on target DOMDocument

.

However, I am having weird issues where once the original document is destroyed, the cloned element works erroneously.


For example, here's some nice working code:

$dom1 = new DOMDocument;
$dom2 = new DOMDocument;

$dom2->loadHTML('<div id="div"><span class="inner"></span></div>');
$div = $dom2->getElementById('div');

$children = $dom1->importNode( $div, true )->childNodes;

echo $children->item(0)->tagName; // Output: "span"

      

Here is a demo: http://codepad.viper-7.com/pjd9Ty


The problem comes up when I try to use elements after their original document is out of scope:

global $dom;
$dom = new DOMDocument;

function get_div_children () {

    global $dom;

    $local_dom = new DOMDocument;
    $local_dom->loadHTML('<div id="div"><span class="inner"></span></div>');

    $div = $local_dom->getElementById('div');

    return $dom->importNode( $div, true )->childNodes;
}

echo get_div_children()->item(0)->tagName;

      

The above results lead to the following errors:

PHP warning . Failed to get DOMElement

. Node no longer exists in ...
PHP Notification : Undefined property: DOMElement::$tagName

in ...

Here is a demo: http://codepad.viper-7.com/c0kqOA


My question is twofold:

  • Shouldn't the returned items still exist even after the original document has been destroyed, since they were cloned into the current document?

  • Workaround. For various reasons, I have to manipulate elements after destroying the original document, but before I insert them into the DOM of another DOMDocument

    . Is there a way to do this?


Clarification: I understand that if elements are inserted into the DOM, it behaves as expected. But as stated above, my setup requires elements to be processed before being inserted into the DOM (long story). Given that the first example works here, and that manipulating elements outside the DOM is a standard procedure in JavaScript - shouldn't it be here and here?

+3


source to share


1 answer


The cloned node has a reference to $ dom, but $ dom does not. PHP's internal garbage collector destroys such nodes when the call context changes. There is only one way to create this link: $dom->documentElement->appendChild($node)

.

So, use code like this (the static keyword will prevent your variable from being garbage collected by the garbage collector):



global $dom;
$dom = new DOMDocument;

function get_div_children () {

global $dom;

$local_dom = new DOMDocument;
$local_dom->loadHTML('<div id="div"><span class="inner"></span></div>');

$div = $local_dom->getElementById('div');
static $nodes;
$nodes = $dom->importNode( $div, true )->childNodes;
return $nodes;
}

echo get_div_children()->item(0)->tagName;

      

0


source







All Articles