PHP只替换一个系列的1个节点

时间:2011-12-07 04:50:24

标签: php xml dom

我有一个XML文件,目前有4个具有相同名称的节点: 该文件如下所示:(data.xml)

<?xml version="1.0"?>
<products>
<product>
<ItemId>531670</ItemId>
<modelNumber>METRA ELECTRONICS/MOBILE AUDIO</modelNumber>
<name>Buy</name>
<name>Car, Marine &amp; GPS</name>
<name>Car Installation Parts</name>
<name>Deck Installation Parts</name>
<name>Antennas &amp; Adapters</name>
</product>
</products>

有4个节点具有相同的名称。 (名称节点)。

然后,我使用此PHP代码替换节点名称

 <?php 
/**
 * @param $xml string Your XML
 * @param $old string Name of the old tag
 * @param $new string Name of the new tag
 * @return string New XML
 */
function renameTags($xml, $old, $new)
{
$dom = new DOMDocument();
$dom->loadXML($xml);

$nodes = $dom->getElementsByTagName($old);
$toRemove = array();
foreach ($nodes as $node)
{
    $newNode = $dom->createElement($new);
    foreach ($node->attributes as $attribute)
    {
        $newNode->setAttribute($attribute->name, $attribute->value);
    }

    foreach ($node->childNodes as $child)
    {
        $newNode->appendChild($node->removeChild($child));
    }

    $node->parentNode->appendChild($newNode);
    $toRemove[] = $node;
}

foreach ($toRemove as $node)
{
    $node->parentNode->removeChild($node);
}

return $dom->saveXML();
}

  // Load XML from file data.xml
$xml = file_get_contents('data.xml');

$xml = renameTags($xml, 'name', 'newName');

echo $xml;
?> 

此函数用newName替换所有名称节点;但是,我只想替换名称标签的一个实例,因为我想重命名每个名称标签。 如果我打电话给另一个     $ xml = renameTags($ xml,'name','newName2');

它不会工作,它只会使用$ xml的第一个实例。

任何想法如何更改我的代码以允许我单独替换每个名称节点?

1 个答案:

答案 0 :(得分:2)

如果您只想重命名遇到的第一个节点,请在第一个break;循环的末尾添加foreach语句,如第一个示例所示。然而,这是非常低效的,并且在底部的第二个(正确)示例中演示了更好的方法。

错误的方式 每当你像这样替换XML时,天使就会流下眼泪......

$src = "
<products>
  <product>
    <ItemId>531670</ItemId>
    <modelNumber>METRA ELECTRONICS/MOBILE AUDIO</modelNumber>
    <name>Buy</name>
    <name>Car, Marine &amp; GPS</name>
    <name>Car Installation Parts</name>
    <name>Deck Installation Parts</name>
    <name>Antennas &amp; Adapters</name>
  </product>
</products>
";

function renameTags($xml, $old, $new)
{
  $dom = new DOMDocument();
  $dom->loadXML($xml);

  $nodes = $dom->getElementsByTagName($old);
  $toRemove = array();
  foreach ($nodes as $node)
  {
    $newNode = $dom->createElement($new);

    foreach ($node->attributes as $attribute)
    {
        $newNode->setAttribute($attribute->name, $attribute->value);
    }

    foreach ($node->childNodes as $child)
    {
        $newNode->appendChild($node->removeChild($child));
    }

    $node->parentNode->appendChild($newNode);
    $toRemove[] = $node;
    break;
  }

  foreach ($toRemove as $node)
  {
    $node->parentNode->removeChild($node);
  }

  $dom->formatOutput = TRUE;
  return $dom->saveXML();
}

$xml = renameTags($src, 'name', 'newName');
echo $xml;

正确的方式

function renameTags($xml, $old, $new)
{
  $dom = new DOMDocument();
  $dom->loadXML($xml);

  // find the first node with the specified tag name
  $oldNode = $dom->getElementsByTagName($old)->item(0);

  // clone the node (deep copy)
  $doppelganger = $oldNode->cloneNode(TRUE);

  // import our cloned node to this dom document
  $doppelganger = $dom->importNode($doppelganger, true);

  // Create new node with the value from the copied node
  $newNode = $dom->createElement($new, $doppelganger->nodeValue);

  // update all the attributes of the new node with those from the copy
  foreach ($doppelganger->attributes as $attrName => $attrNode) {
    $newNode->setAttribute($attrName, $attrNode);
  }

  // append the newNode copy to the dom
  $oldNode->parentNode->appendChild($newNode);

  // remove the old node
  $oldNode->parentNode->removeChild($oldNode);

  $dom->formatOutput = TRUE;
  return $dom->saveXML();
}