Я пытаюсь понять, как переименовать узел в 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
.