2011-12-07 26 views
1

我有當前具有相同名稱4個節點的XML文件的1個節點: 文件看起來是這樣的:(data.xml中)PHP只替換了一系列

<?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的第一個實例。

任何想法如何我可以更改我的代碼,以允許我單獨替換每個名稱節點?

+0

哈哈你這裏早些時候... :) – rdlowrey

+0

我是。這個網站真的有助於理解事情。 – Ben

+0

檢查更新的代碼。 – rdlowrey

回答

2

如果您只想重命名遇到的第一個節點,請在第一個示例的第一個foreach循環末尾添加break;語句。然而,這是非常低效率的,更好的方法是在底部的第二個(正確)例子中證明。

走錯了路 每次更換這樣的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(); 
} 
+0

我測試了第二個腳本,它正在替換名稱節點;但是,它也會刪除名稱節點的值。 – Ben

+0

@Ben我糾正了這個問題。代碼已更新。 – rdlowrey