PHP DOM操作で別ドキュメントからのノードをコピーする方法 Uncaught DOMException: Wrong Document Error in

DOMDocumentを使ってHTMLの特定要素を抽出し別ドキュメントにコピーしようとした際に以下のエラーが発生した。

PHP Fatal error: Uncaught DOMException: Wrong Document Error in

エラーになったソースは以下の通りです。
エラー
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//HTMLファイルをdomで読込む
$htmlTo = file_get_contents($htmlpathTo);
$docTo = new DOMDocument;
libxml_use_internal_errors( true );                     //Warning: DOMDocument::loadHTML() を抑制する
$docTo->loadHTML('<?xml encoding="UTF-8">'.$htmlTo);    //xmlでラップ(UTF-8で読むため)
libxml_clear_errors();                                  //Warning: DOMDocument::loadHTML() を抑制する
$xpTo = new DOMXPath($docTo);
$xyz = $xp1->query('//*[@class="xyz"]');                //xyzのクラス名を持つ要素を抽出
$parent = $xyz->parentNode;
 
$htmlFm = file_get_contents($htmlpathFm);
$docFm = new DOMDocument;
libxml_use_internal_errors( true );                     //Warning: DOMDocument::loadHTML() を抑制する
$docFm->loadHTML('<?xml encoding="UTF-8">'.$htmlFm);    //xmlでラップ(UTF-8で読むため)
libxml_clear_errors();                                  //Warning: DOMDocument::loadHTML() を抑制する
$xpFm = new DOMXPath($docFm);
$target = $xpFm->query('//*[@class="abc"]');            //abcのクラス名を持つ要素を抽出
foreach ($target as $item) {
    $newNode = $item->cloneNode(true);
    $parent->insertBefore($newNode, $xyz);              //$xyzノードの前に$newNodeを挿入
}

やりたい事
$htmlpathFmにあるhtmlファイルから、abcというクラス名を持つ要素を抽出します。それを$htmlToにあるhtmlファイルのxyzというクラス名を持つ要素の前に挿入する。(よくないのですが、xyzのクラス名を持つ要素は一つだけという前提です。)
上記コードを実行すると"PHP Fatal error: Uncaught DOMException: Wrong Document Error in …"というエラーが発生します。$itemをコピーした$newNodeは$docFm所有のノードなので、ことなるドキュメント$docToのノードに挿入することは出来ないようです。それで上記のエラーが発生するようです。知識不足でした。
解決策としてはimportNodeメソッドを使用するようです。
解決策
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//HTMLファイルをdomで読込む
$htmlTo = file_get_contents($htmlpathTo);
$docTo = new DOMDocument;
libxml_use_internal_errors( true );                     //Warning: DOMDocument::loadHTML() を抑制する
$docTo->loadHTML('<?xml encoding="UTF-8">'.$htmlTo);    //xmlでラップ(UTF-8で読むため)
libxml_clear_errors();                                  //Warning: DOMDocument::loadHTML() を抑制する
$xpTo = new DOMXPath($docTo);
$xyz = $xp1->query('//*[@class="xyz"]');                //xyzのクラス名を持つ要素を抽出
$parent = $xyz->parentNode;
 
 
$htmlFm = file_get_contents($htmlpathFm);
$docFm = new DOMDocument;
libxml_use_internal_errors( true );                     //Warning: DOMDocument::loadHTML() を抑制する
$docFm->loadHTML('<?xml encoding="UTF-8">'.$htmlFm);    //xmlでラップ(UTF-8で読むため)
libxml_clear_errors();                                  //Warning: DOMDocument::loadHTML() を抑制する
$xpFm = new DOMXPath($docFm);
$target = $xpFm->query('//*[@class="abc"]');            //abcのクラス名を持つ要素を抽出
foreach ($target as $item) {
    $newNode = $docTo->importNode($item, true);         //$docToに$itemノードをインポートする
    $parent->insertBefore($newNode, $xyz);              //$xyzノードの前に$newNodeを挿入
}
これで無事に解決しました。

コメント

人気の投稿