2011-07-17 51 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)'...可能需要根据“需要删除”代码的智能程度来捕获“已删除”异常。 –

相关问题