PHP Conference Japan 2024

DOMNode::cloneNode

(PHP 5, PHP 7, PHP 8)

DOMNode::cloneNode 複製節點

說明

public DOMNode::cloneNode(bool $deep = false): DOMNode|false

建立節點的副本。

參數

deep

指示是否複製所有子節點。此參數預設為 false

回傳值

複製的節點。

新增註解

使用者貢獻的註解 6 則註解

frame at dynamiccreated dot de
12 年前
請記住,DOMNode 總是需要參考父節點或 DOMDocument。

例如,如果您嘗試複製一個節點(複製所有子節點),然後覆寫或刪除保存複製節點的變數,則所有子節點都將失去任何參考並失效。

如果您幸運的話,這會導致出現類似「無法...節點已不存在」的訊息。在大多數情況下,PHP 只會提供「無法擷取 DOM[...]」之類的簡略資訊,這使得根據目前的操作難以找出問題所在。
[montana] at [percepticon] dot [com]
15 年前
<?php

//感謝 @oliver 提供範例程式碼...

/*
cloneNode(false) 並不會忽略
被複製節點的屬性,
要達到此目的,需要進行迭代。
這可能比僅從所需的 nodeName
建立新節點效率低,
但在某些情況下可能很有用。

使用案例:

略過 XML 文件中受保護部分的子節點和屬性,
同時不改變預期的整體結構;
*/
//要使用的 XML

$file="<?xml version='1.0'?>
<book type='paperback'>
<title name='MAP'>Red Nails</title>
<price>$12.99</price>
<author>
<name first='Robert' middle='E' last='Howard'/>
<birthdate disco='false' nirvana='definitely'>
9/21/1977
<month title='september' />
</birthdate>
</author>
<author>
<name first='Arthur' middle='Mc' last='Kayn'/>
</author>
</book>"
;

$doc = new domDocument;

$doc->loadXML($file);

$xpath = new domXPath($doc);

$query = "//author/birthdate";
$xpathQuery = $xpath->query($query);

//在實際程式碼中會是一個迴圈...
$child = $xpathQuery->item(0);

$parent = $child->parentNode;

$doppel = $child->cloneNode(false);

$limit = $doppel->attributes->length;

for (
$a=0;$a<$limit;$a++) {
$doppel->removeAttributeNode($doppel->attributes->item(0));
}
//目前交換為空節點
$parent->replaceChild( $doppel, $child);

print
$doc->saveXML();

?>
cmd at 1xinternet dot de
8 年前
如果您需要複製包含所有子 DOMNode 元素的節點

private function cloneNode($node){

$nd = new DOMNode();

for ($i = 0; $i < $node->childNodes->length; $i++) {
$child = $node->childNodes->item($i);
if ($child->nodeType === XML_TEXT_NODE) {
$nd->appendChild($node->cloneNode(true));
}
}else{
$nd->appendChild($this->cloneNode($child));
}
}

return $nd;
}
cemkalyoncu at gmail dot com
15 年前
如果您需要一個不影響命名空間的節點複製函式,可以使用以下方法。

<?php
private function cloneNode($node,$doc){
$nd=$doc->createElement($node->nodeName);

foreach(
$node->attributes as $value)
$nd->setAttribute($value->nodeName,$value->value);

if(!
$node->childNodes)
return
$nd;

foreach(
$node->childNodes as $child) {
if(
$child->nodeName=="#text")
$nd->appendChild($doc->createTextNode($child->nodeValue));
else
$nd->appendChild(cloneNode($child,$doc));
}

return
$nd;
}
?>
h-fate at gmx dot net
10 年前
如果您有一個物件持有 DOMNode,複製該物件並不會同時複製 DOMNode。如果您只是複製物件或多次新增它的 DOMNode,實際上您只是在樹狀結構中移動 DOMNode,而不是複製它。這看起來可能很明顯,但我花了半天時間才發現。

該物件需要使用 __clone 並手動複製節點

<?php
class containsNode {
public
$node; //從某處設定

public function __clone() {
$this->node = $this->node->cloneNode(TRUE);
}
}
?>
oliver dot christen at camptocamp dot com
20 年前
節點複製的簡單範例

<?xml version="1.0"?>

<book type="paperback">
<title name='MAP'>Red Nails</title>
<price>$12.99</price>
<author>
<name first="Robert" middle="E" last="Howard"/>
<birthdate>9/21/1977</birthdate>
</author>
<author>
<name first="Arthur" middle="Mc" last="Kayn"/>
</author>
</book>

<?php

// 檔案名稱:要使用的 XML 檔案
$file = 'book.xml';

$doc = new domDocument;

if (
file_exists($file)) {
$doc->load($file);
} else {
exit(
'錯誤!');
}

$xpath = new domXPath($doc);

$query = "//author/*";
$xpathQuery = $xpath->query($query);

$size = $xpathQuery->length;
for (
$i=0; $i<$size; $i++){
$node = $xpathQuery->item($i);
if (
$node->nodeName == 'birthdate' && $node->hasChildNodes() && $node->firstChild->textContent != ''){
$clonenode = $node->cloneNode(true);
$refnode = $node;
}
}
for (
$i=0; $i<$size; $i++){
$node = $xpathQuery->item($i);
if (!
$node->isSameNode($refnode)){
$newnode = $node->appendChild($clonenode);
}
}

print
$doc->saveXML();

?>
To Top