在销毁原始DOMDocument之后访问导入的元素

时间:2013-02-04 20:44:44

标签: php html html-parsing domdocument xmlnode

我最近一直在搞乱DOMDocument,我注意到为了将元素从一个文档转移到另一个文档,我必须在目标DOMDocument上调用$DOMDocument->importNode()。< / p>

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


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

$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 in ...

以下是演示:http://codepad.viper-7.com/c0kqOA


我的问题有两个:

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

  2. 解决方法。由于各种原因,我必须在原始文档被销毁之后操作元素,但在实际将它们插入到另一个DOMDocument的DOM之前。有没有办法实现这个目标?


  3. 澄清:我知道如果元素插入到DOM中,它的行为与预期的一样。但是,如上所述,我的设置要求在插入DOM之前操纵元素(长篇故事)。鉴于这里的第一个例子是有效的 - 并且DOM之外的操作元素是JavaScript中的标准过程 - 这不应该也可以吗?

1 个答案:

答案 0 :(得分:0)

克隆节点引用$ dom,但$ dom没有。当调用上下文改变时,内部PHP垃圾收集器会破坏这些节点。创建此引用的方法只有一种:$dom->documentElement->appendChild($node)

所以,使用这样的代码(静态关键字会阻止垃圾收集器破坏你的变量):

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;