2015-01-15 19 views
-1

然後我嘗試使用第一置換循環後,這個代碼後循環的回採 $Autos->length = 10XML DOM爲下一站的replaceChild

$Autos = $dom->getElementsByTagName('cars'); // Find Sections 
$NewElement = $dom->createElement('hello','hi'); 
for ($i = 0; $i < $Autos->length; $i++) 
{ 

    $Autos->item($i)->parentNode->replaceChild($NewElement, $Autos->item($i)); 
    echo $Autos->length . " i= " .$i; 
} 

所以$我總是= 0 爲什麼這個hapens?

回答

2

DOMNode :: getElementsByTagName()返回一個「活動」列表。如果文檔發生更改,它會發生變化。您替換節點,這樣列表也會改變。

這裏有三種方法可以解決這個問題。

  1. 角色節點列表到一個數組:

    $Autos = iterator_to_array($dom->getElementsByTagName('cars'));

  2. 循環列表中從最後一個節點到第一:

    for ($i = $Autos->length - 1; $i >= 0; $i--) {

  3. 使用XPath取節點:

    $xpath = new DOMXPath($dom);
    $Autos = $xpath->evaluate('//cars');

XPath表達式很多更加靈活和強大然後將DOM方法來獲取節點和結果不是「活」。例如,您可以執行如下操作:

$Autos = $xpath->evaluate('//cars[@manufacturer = "SomeCompanyName"]'); 

這是您源中的另一個問題。您只用一個創建的節點替換該節點。因此,它取代了第一個節點,然後同一個節點替換了第二個節點,直到它取代了列表中的最後一個節點。

您將需要克隆創建的節點:

$Autos->item($i)->parentNode->replaceChild(
    $NewElement->cloneNode(TRUE), $Autos->item($i) 
); 

節點列表實現Traversable接口的。你可以使用foreach()。

foreach ($xpath->evaluate('//cars') as $i => $car) { 
    $car->parentNode->replaceChild($NewElement->cloneNode(TRUE), $car); 
    echo " i= " .$i; 
} 

作爲一個側面說明。構建新的目標XML文檔並將節點複製到它然後操縱現有文檔通常會更容易。 XSLT是專門用於此任務的特定語言。