DOMDocument groupping nodes, with clone, nodeClone, importNode, fragment... What the better way?
- by Peter Krauss
A "DOMNodeList grouper" (groupList() function below) is a function that envelopes a set of nodes into a tag. Example:
INPUT
<root><b>10</b><a/><a>1</a><b>20</b><a>2</a></root>
OUTPUT of groupList($dom->getElementsByTagName('a'),'G')
<root><b>10</b>
<G><a/><a>1</a><a>2</a></G>
<b>20</b></root>
There are many ways to implement it, what is the better?
function groupList_v1(DOMNodeList &$list,$tag,&$dom) {
$list = iterator_to_array($list); // to save itens
$n = count($list);
if ($n && $list[0]->nodeType==1) {
$T = $dom->createDocumentFragment();
$T->appendChild($dom->createElement($tag));
for($i=0; $i<$n; $i++) {
$T->firstChild->appendChild( clone $list[$i] );
if ($i) $list[$i]->parentNode->removeChild($list[$i]);
}
$dom->documentElement->replaceChild($T,$list[0]);
}//if
return $n;
}//func
function groupList_v2(DOMNodeList &$list,$tag,&$dom) {
$list = iterator_to_array($list); // to save itens
$n = count($list);
if ($n && $list[0]->nodeType==1) {
$T = $dom->createDocumentFragment();
$T->appendChild($dom->createElement($tag));
for($i=0; $i<$n; $i++)
$T->firstChild->appendChild( clone $list[$i] );
$dom->documentElement->replaceChild($T,$list[0]);
for($i=1; $i<$n; $i++)
$list[$i]->parentNode->removeChild($list[$i]);
}//if
return $n;
}//func
// ... YOUR SUGGESTION ...
// My ugliest
function groupList_vN(DOMNodeList &$list,$tag,&$dom) {
$list = iterator_to_array($list); // to save itens
$n = count($list);
if ($n && $list[0]->nodeType==1) {
$d2 = new DOMDocument;
$T = $d2->createElement($tag);
for($i=0; $i<$n; $i++)
$T->appendChild( $d2->importNode($list[$i], true) );
$dom->documentElement->replaceChild( $dom->importNode($T, true), $list[0] );
for($i=1; $i<$n; $i++)
$list[$i]->parentNode->removeChild($list[$i]);
}//if
return $n;
}//func
Related questions: at stackoverflow, at codereview.