1

我试图弄清楚如何使用 PHP 重命名 XML 中的节点?

我已经走到这一步了:

$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>. 这可以做到吗?如果可以,怎么做?

4

2 回答 2

1

节点的名称(分别为“数据”或“邀请”)不能通过 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();
?>
于 2012-09-17T16:39:24.813 回答
0

我的解决方案,带有扩展的测试用例:

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

顺便说一句,我将此解决方案作为注释添加到DOMElement.

于 2013-02-26T15:06:01.207 回答