2011-07-17 91 views
0

我正在嘗試使用lxmletree模塊來操縱DOM樹。我還沒有想到的一個任務是如何測試某個特定節點是否仍然是分析樹的一部分。由於etree的行爲大多是未定義的,如果在_ElementTree.iter()期間刪除節點,我會分兩個階段進行操作。Python lxml:如何判斷一個元素是否已從樹中刪除?

首先,我遍歷解析樹並將一些節點標記爲刪除,並將其標記爲某些其他節點,以便將它們放置在相應的列表中。第二階段包括遍歷節點列表以從樹中刪除和刪除它們。在這一點上,我有一個進一步處理的節點列表和一個自從第一次被解析以來已經大幅修剪的樹。

我缺乏的是測試節點到進程列表中的特定節點是否仍然存在於分析樹中的方法。如果它不是樹的一部分,那意味着它是我之前刪除的其中一個節點的後代,我想放棄它。問題在於沒有一種明顯的方法可以便宜地進行這種測試。即使在節點已從_ElementTree中刪除後,在該節點上調用getroottree()將返回原始樹。

我可以在每個節點到進程上調用iterancestors(),並檢查我期望的樹中節點的根元素,但是這是O(n),並且不能很好地適應深層DOM樹。

有沒有人知道恆定時間操作,給定Element_ElementTree,以測試前者是否是後者的一部分?

我意識到向上遍歷一個節點的父鏈可能是做這個測試的唯一方法,任何更快的方法都需要圖書館實施一些簿記。

回答

1

第0步:將xml解析爲樹。
第1步:迭代樹,刪除需要刪除的節點。
第2步:遍歷剩餘的節點,處理那些需要它的節點。

如果您有自己的步驟0,你可以使用iterparse()與結束事件,以節省建設一個大型的樹只是後來去除許多節點,形成步驟1簡單得多:

for event, elem in etree.iterparse(input_xml): 
    if elem needs deleting: 
     elem.clear() # remove text, tail, attributes, and descendant elements 
     delete_todo.append(elem) 
+0

你怎麼用做「delete_todo」列表?看來除去實際節點還有一個步驟? – Ramy

+1

@Ramy:不「似乎」;絕對真實。閱讀文檔的iterparse部分 - 在構建分析樹時,不能刪除解析器仍在使用的節點,如當前節點。如何:在delete_todo中爲elem:elem.getparent()。remove(elem)'...可能需要根據「需要刪除」代碼的智能程度來捕獲「已刪除」異常。 –

相關問題