Вопрос:
Как создать супер-корневой узел, содержащий предыдущий documentElement?
Пример сценария:
Учитывая следующий фрагмент в PHP, encapsulateRootNode
Функция должна создать новый корневой узел, который содержит старую структуру full 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
используется для операций такого типа, но поскольку нет родителя, для которого вызывается эта функция, я потерял способность выполнять эту операцию.
Я случайно попробовал некоторые возможности без успеха:
$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 становится нулевым, и его невозможно заменить.
$newXml = $doc->createElement( $tagName);
$old = $doc->documentElement;
doc->replaceChild($newXml, $old);
$newXml->appendChild($old);
Других решений пока нет …