2010-09-15 115 views
0

我正在使用PHP的DOMDocument和相關類來處理XML。 XML包含處理指令,必須按照特定順序從上到下,從最深到最淺處理。PHP:遞歸進程然後從DOMDocument中刪除DOME元素

我正在使用一個遞歸函數,它接受整個DOMDocument,然後調用它自己的子節點,一直向下。

我需要在處理它們後刪除其中的一些子節點。問題是,只要刪除一個子節點,看起來foreach是「失控」,我不能刪除任何更多的子節點。

示例XML文檔:

<root id="1"> 
    <instruction id="2"> 
     <inner id="3"/> 
    </instruction> 
    <instruction id="4"> 
     <inner id="5"/> 
    </instruction> 
</root> 

我需要處理inner[@id=3]第一,然後將其刪除。然後我需要處理instruction[id=2]並將其刪除。一直到這裏,一切都很好。

接下來我需要處理inner[@id=5]並將其刪除。我可以讀取/處理它,但是當我嘗試刪除它時:

$parentNode=$inner->parentNode; 
$parentNode->removeChild($inner); 

沒有任何反應。看起來,刪除第一個指令節點讓PHP對文檔中包含哪些元素感到困惑。

我知道有可能從底部到頂部處理XML並按順序刪除所有節點,但我有一個特殊的需求,即從頂部到底部。

另一個信息在這裏 - 我還在處理它時添加一些新的節點到文檔中,以防改變我的選項。

我需要做些什麼才能使其發揮作用?

回答

2

許多DOM結構在內部只是數組。由於存儲在返回的NODElist對象中的鍵/指針將引用不再存在的數組偏移量,或者包含完全不同的東西,因此刪除元素會將事物轉移。

要正確處理刪除DOM節點而不擾亂這些各種指針,您必須從數組的末尾開始工作。不是在原地刪除節點,而是將它們存儲在堆棧式結構中,並且在完成樹的任何特定級別上的操作後,可以將所有內容從堆棧中彈出,然後執行刪除操作。在這一點上,任何懸掛的指針都會在你已經完成工作的時候進行討論。

+0

你說的沒錯,Marc。我也在考慮在處理過的元素上放置一個標記,以便在刪除元素後重新加載整個文檔。重新加載會重置所有的數組。該標誌將允許我跳過處理過的元素,並從我離開的地方開始排序。 – Tex 2010-09-20 07:46:24