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た。Node is no longer exist in ...
PHP 通知: 未定義のプロパティ: DOMElement::$tagNamein ...

ここにデモがあります: http://codepad.viper-7.com/c0kqOA


私の質問は 2 つあります。

  1. 元のドキュメントが破棄された後でも、返された要素は現在のドキュメントに複製されているため、存在するべきではありませんか?

  2. 回避策。さまざまな理由から、元のドキュメントが破棄された後、要素を実際に他の DOM に挿入する前に、要素を操作する必要がありますDOMDocument。これを達成する方法はありますか?


明確化:要素が DOM に挿入されると、期待どおりに動作することを理解しています。しかし、上で概説したように、私のセットアップでは、要素を DOM に挿入する前に操作する必要があります (長い話です)。ここでの最初の例が機能し、DOM の外側で要素を操作することは JavaScript の標準的な手順であることを考えると、これはここでも可能ではないでしょうか?

4

1 に答える 1

0

複製されたノードには $dom への参照がありますが、$dom はありません。内部 PHP ガベージ コレクターは、呼び出しコンテキストが変更されると、そのようなノードを破棄します。この参照を作成する方法は 1 つだけです: $dom->documentElement->appendChild($node).

したがって、次のようなコードを使用します (static キーワードは、ガベージ コレクターが変数を破棄するのを防ぎます)。

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 に答える