在 PHP 中,如何用旧 documentElement 的新元素父元素替换 DOMDocument::documentElement?

In PHP, how to replace the DOMDocument::documentElement with a new element parent of the old documentElement?

问题:

如何创建包含上一个文档元素的超级根节点?

示例场景:

鉴于 PHP 中的以下片段,encapsulateRootNode 函数必须创建一个新的根节点,其中包含旧的完整 dom 结构:

示例:

<anyContent>...</anyContent>

成为

<newRoot><anyContent>...</anyContent></newRoot>

以下代码无法更改,而且必须尽可能快,因此我放弃了任何序列化、连接和解析。我还想避免克隆完整的 DOM 结构。

$doc = new \DOMDocument();
if(!@$doc->loadXML($xmlContent))
{
    $myLibrary->encapsulateRootNode($doc, 'newRoot');
}

我的问题是如何创建以下函数:

public function encapsulateRootNode( $doc, $tagName )
{
    ...
}

信息搜索:

通常,replaceChild 用于这种操作,但由于没有父对象可以调用此函数,我发现自己不知道如何执行此操作。

我运行dom尝试了一些没有成功的可能性:

$newXml = $doc->createElement( $tagName);
$newXml->appendChild($doc->documentElement);
// strange behaviours / warning using the resulting DOM

$newXml = $doc->createElement( $tagName);
$old = $doc->documentElement;
$doc->documentElement = $newXml;
$newXml->appendChild($old);
// documentElement is read only

甚至:

$fragment = $doc->createDocumentFragment();
$newXml = $doc->createElement( $tagName);
$fragment->appendChild($newXml);
$newXml->appendChild($doc->documentElement);
// How to convert this fragment back to the normal domDocument?

经过一番搜索,我找到了这个解决方案:

replaceChild 甚至在 root 上工作,因为 DOMDocument 扩展了 DomNode。

旧的根节点必须追加到新的根节点之后才能替换它,因为如果之前完成,documentElement 将变为 null 并且无法再替换它。

$newXml = $doc->createElement( $tagName);
$old = $doc->documentElement;
doc->replaceChild($newXml, $old);
$newXml->appendChild($old);