2012-09-17 106 views
1

我想弄清楚如何使用PHP重命名XML中的節點?使用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>。這可以做到,如果是,如何?

回答

1

節點的名稱(分別爲「data」或「invites」)不能通過DOM重命名,因爲Node::nodeName property is read-only

您可以創建一個名爲「invites」的新節點,將它附加到「data」節點之前,將「data」的子節點移動到新的「invites」節點,刪除「data」節點,然後輸出樹來獲得你的結果。

實施例:

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

哇......這聽起來像是一點工作......不能str_replace以某種方式使用? – Mansa

+0

這並不壞。我會用一個例子編輯我的帖子。我不會建議使用'str_replace',除非你絕對肯定''和後面的''只會存在於特定的上下文(罕見)中。 – jimp

+0

好吧,雖然我很確定它會像示例一樣。期待您的例子:-) – Mansa

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

順便說,我此溶液中加入作爲comment PHP文檔爲DOMElement