Переименовать узел XML с помощью PHP

Я пытаюсь понять, как переименовать узел в XML с помощью PHP?

Я пришел так далеко:

$dom = new DOMDocument( '1.0' ); $dom->preserveWhiteSpace = false; $dom->formatOutput = true; // load the xml file $dom->loadXML( '<?xml version="1.0" encoding="ISO-8859-1"?> <library> <data> <invite> <username>jmansa</username> <userid>1</userid> </invite> <update>1</update> </data> </library>', LIBXML_NOBLANKS ); $xpath = new DOMXPath($dom); //find all 'data' nodes. $node = $xpath->query("//data"); // if found if( $node->length ) { foreach ($node as $n) { // RENAME HERE? // } } echo "<xmp>". $dom->saveXML() ."</xmp>"; 

Теперь я хочу переименовать <data> в <invites> . Можно ли это сделать, и если да, то как?

Имя узла («данные» или «приглашает» соответственно) не может быть переименовано через DOM, поскольку свойство Node :: nodeName доступно только для чтения .

Вы можете создать новый узел с именем «приглашает», добавить его перед узлом «данные», переместить дочерние «данные» на новый узел «приглашает», удалить узел «данные», а затем вывести дерево, чтобы получить результат.

Пример:

 <?php // Create a test document. $dom = new DOMDocument( '1.0' ); $dom->preserveWhiteSpace = false; $dom->formatOutput = true; // Load the xml file. $dom->loadXML('<?xml version="1.0" encoding="ISO-8859-1"?'.'> <library> <data attr1="1" attr2="2"> <invite> <username>jmansa</username> <userid>1</userid> </invite> <update>1</update> </data> </library>', LIBXML_NOBLANKS ); $xpath = new DOMXPath($dom); // Convert <data> to <invites>. if ($dataNode = $xpath->query("/library/data")->item(0)) { // Create the <invites> node. $invitesNode = $dom->createElement('invites'); $dataAttrs = $dataNode->attributes; foreach ($dataAttrs as $dataAttr) { $invitesNode->setAttributeNodeNS($dataAttr->cloneNode()); } $dom->documentElement->appendChild($invitesNode); // Move the <data> children over. if ($childNodes = $xpath->query("/library/data/*")) { foreach ($childNodes as $childNode) { $invitesNode->appendChild($childNode); } } // Remove <data>. $dataNode->parentNode->removeChild($dataNode); } // Test the result. echo $dom->saveXML(); ?> 

Мое решение, с расширенным тестовым примером:

 // Changes the name of element $element to $newName. function renameElement($element, $newName) { $newElement = $element->ownerDocument->createElement($newName); $parentElement = $element->parentNode; $parentElement->insertBefore($newElement, $element); $childNodes = $element->childNodes; while ($childNodes->length > 0) { $newElement->appendChild($childNodes->item(0)); } $attributes = $element->attributes; while ($attributes->length > 0) { $attribute = $attributes->item(0); if (!is_null($attribute->namespaceURI)) { $newElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:'.$attribute->prefix, $attribute->namespaceURI); } $newElement->setAttributeNode($attribute); } $parentElement->removeChild($element); } function prettyPrint($d) { $d->formatOutput = true; echo '<pre>'.htmlspecialchars($d->saveXML()).'</pre>'; } $d = new DOMDocument( '1.0' ); $d->loadXML('<?xml version="1.0"?> <library> <data a:foo="1" x="bar" xmlns:a="http://example.com/a"> <invite> <username>jmansa</username> <userid>1</userid> </invite> <update>1</update> </data> </library>'); $xpath = new DOMXPath($d); $elements = $xpath->query('/library/data'); if ($elements->length == 1) { $element = $elements->item(0); renameElement($element, 'invites'); } prettyPrint($d); 

Кстати, я добавил это решение в качестве комментария к документации PHP для DOMElement .