简体   繁体   中英

Rename an XML node using PHP

I'm trying to figure out how to rename a node in XML using PHP?

I Have come this far:

$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>";

Now, I want to rename <data> to <invites> . Can this be done and if yes, how?

A Node's name ("data" or "invites" respectively) cannot be renamed via the DOM because the Node::nodeName property is read-only .

You can create a new node named "invites", append it before the "data" node, move the children of "data" to the new "invites" node, remove the "data" node, and then output the tree to get your result.

Example:

<?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();
?>

My solution, with extended test case:

// 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);

By the way, I added this solution as a comment to the PHP documentation for DOMElement .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM