Проблема кажется простой, но мне трудно получить доступ к имени тега SimpleXMLElement.
Допустим, у меня есть следующая структура XML:
<xml> <oldName>Stuff</oldName> </xml>
И я хочу, чтобы это выглядело так:
<xml> <newName>Stuff</newName> </xml>
Можно ли обойтись без копирования всего объекта?
Я начал понимать ошибки того, как я приближаюсь к этой проблеме. Кажется, что мне нужно преобразовать мой SimpleXMLElement в объект DOM. Поступая таким образом, мне очень трудно манипулировать объектом так, как я хочу (по-видимому, переименование меток в DOM нелегко сделать по какой-то причине).
Итак … Я могу импортировать свой SimpleXMLElement в объект DOM с импортом, но мне трудно сделать клон.
Является ли следующее правильное мышление для клонирования объекта DOM, или я все еще далеко:
$old = $dom->getElementsByTagName('old')->item(0); // The tag is unique in my case $new = $dom->createElement('new'); /* ... some recursive logic to copy attributes and children of the $old node ... */ $old->ownerDocument->appendChild($new); $new->ownerDocument->removeChild($old);
Вот, пожалуй, самый простой способ скопировать дочерние элементы и атрибуты узла без использования XSLT:
function clonishNode(DOMNode $oldNode, $newName, $newNS = null) { if (isset($newNS)) { $newNode = $oldNode->ownerDocument->createElementNS($newNS, $newName); } else { $newNode = $oldNode->ownerDocument->createElement($newName); } foreach ($oldNode->attributes as $attr) { $newNode->appendChild($attr->cloneNode()); } foreach ($oldNode->childNodes as $child) { $newNode->appendChild($child->cloneNode(true)); } $oldNode->parentNode->replaceChild($newNode, $oldNode); }
Что вы можете использовать таким образом:
$dom = new DOMDocument; $dom->loadXML('<foo><bar x="1" y="2">x<baz/>y<quux/>z</bar></foo>'); $oldNode = $dom->getElementsByTagName('bar')->item(0); clonishNode($oldNode, 'BXR'); // Same but with a new namespace //clonishNode($oldNode, 'newns:BXR', 'http://newns'); die($dom->saveXML());
Он заменит старый узел клоном на новое имя.
Внимание, однако, это копия содержимого исходного узла. Если у вас есть какая-либо переменная, указывающая на старые узлы, они теперь недействительны.
Может быть, проще будет заменить теги, используя функции preg для исходной строки XML?
Чистый способ
Создайте файл преобразования XSLT XML и используйте расширение xsl PHP для его перевода.
Для этого см. Этот ответ. Переименуйте узлы с помощью XSLT . Часть кода PHP может быть найдена в документации PHP.
Можно ли обойтись без копирования всего объекта?
Нет, это не так.
Вы можете сделать это в XSLT с помощью «преобразования идентичности». Если вы ищете «переименовать тег» и «преобразование идентичности», вы должны найти несколько примеров, предполагая, что XSLT является опцией.
Скорее поздно, но я придумал решение, заменив ад из xml. Я думал, что это может помочь некоторым людям, так как я не смог найти подходящее решение в Интернете, не копируя всех детей.
function RenameNode(SimpleXMLElement $Entire_XML, SimpleXMLElement $Node, $New_Title) { $Full_XML = $Entire_XML->asXML(); $Old_Title = $Node->getName(); $XML_String = $Node->asXML(); $Replaced = preg_replace("/$Old_Title/", $New_Title, $XML_String, 1); if (count($Node->children())>0) { $Replaced = strrev( preg_replace( strrev("/$Old_Title/"), strrev($New_Title), strrev($Replaced), 1 ) ); } $Full_XML = str_replace($XML_String, $Replaced, $Full_XML); return simplexml_load_string($Full_XML); }
Sidenote: эта функция может быть упрощена, но я быстро переписал эту функцию, чтобы опубликовать ее здесь. Исходная функция, которую я использую, немного отличается