我有一个可怕的算法,“删除一个节点”,将它的内部内容移动到它的父节点(见下文)......但我认为可以开发一个更好的算法,使用DOMDocumentFragment (而不是使用 saveXML/loadXML)。
下面的算法受到renameNode()的启发。
/**
* Move the content of the $from node to its parent node.
* Conditions: parent not a document root, $from not a text node.
* @param DOMElement $from to be removed, preserving its contents.
* @return true if changed, false if not.
*/
function moveInner($from) {
$to = $from->parentNode;
if ($from->nodeType==1 && $to->parentNode->nodeType==1) {
// Scans $from, and record information:
$lst = array(); // to avoid "scan bugs" of DomNodeList iterator
foreach ($to->childNodes as $e)
$lst[] = array($e);
for($i=0; $i<count($lst); $i++)
if ($lst[$i][0]->nodeType==1 && $from->isSameNode($lst[$i][0])) {
$lst[$i][1] = array();
foreach ($lst[$i][0]->childNodes as $e)
$lst[$i][1][] = $e;
}
// Build $newTo (rebuilds the parent node):
$newTo = $from->ownerDocument->createElement($to->nodeName);
foreach ($to->attributes as $a) {
$newTo->setAttribute($a->nodeName, $a->nodeValue);
}
foreach ($lst as $r) {
if (count($r)==1)
$newTo->appendChild($r[0]);
else foreach ($r[1] as $e)
$newTo->appendChild($e);
}
// Replaces it:
$to->parentNode->replaceChild($newTo, $to);
return true;
} else
return false;
}
例子
输入
<html id="root">
<p id="p1"><i>Title</i></p>
<p id="p2"><b id="b1">Rosangela<sup>1</sup>, Maria<sup>2</sup></b>,
<b>Eduardo<sup>4</sup></b>
</p>
</html>
的输出moveInner($dom->getElementById('p1'))
... <p id="p1">Title</p> ...
的输出moveInner($dom->getElementById('b1'))
... <p id="p2">Rosangela<sup>1</sup>, Maria<sup>2</sup>,
<b>Eduardo<sup>4</sup></b>
</p> ...
没有变化moveInner($dom->getElementById('root'))
,或moveInner($dom->getElementById('p1'))
首次使用后。
PS:就像一个“TRIM TAG”功能。