3

我最近一直在搞乱 DOMDocument,我注意到为了将元素从一个文档传输到下一个文档,我必须调用$DOMDocument->importNode()target DOMDocument

但是,我遇到了奇怪的问题,一旦原始文档被破坏,克隆的元素就会行为不端。


例如,这里有一些可爱的工作代码:

$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"

这是一个演示:http ://codepad.viper-7.com/pjd9Ty


当我在原始文档超出范围后尝试使用这些元素时,就会出现问题:

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;

以上导致以下错误:

PHP 警告:无法获取DOMElement。节点不再存在于...
PHP 注意:未定义的属性:DOMElement::$tagName在...

这是一个演示:http ://codepad.viper-7.com/c0kqOA


我的问题是双重的:

  1. 即使在原始文档被销毁后,返回的元素是否应该存在,因为它们被克隆到当前文档中?

  2. 一种解决方法。由于各种原因,我必须在原始文档被销毁之后,但在我真正将它们插入到另一个 DOM 之前,对元素进行操作DOMDocument。有没有办法做到这一点?


澄清:我知道如果将元素插入到 DOM 中,它会按预期运行。但是,如上所述,我的设置要求在插入 DOM 之前对元素进行操作(长篇大论)。鉴于这里的第一个示例有效 - 并且在 DOM 之外操作元素是 JavaScript 中的标准过程 - 这难道不应该在这里也是可能的吗?

4

1 回答 1

0

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

So, use code like this (static keyword will prevent garbage collector from destroying your variable):

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;
于 2013-03-06T01:40:48.087 回答