我正在尝试使用lxml
的{{1}}模块来操纵DOM树。我还没想到的一个任务是如何测试特定节点是否仍然是解析树的一部分。如果在etree
期间删除节点,etree
的行为大多未定义,我会分两个阶段进行操作。
首先,我遍历已解析的树并标记一些要删除的节点以及某些其他节点,以便通过将它们放在相应的列表中进行进一步处理。第二阶段包括迭代节点列表以从树中删除和删除它们。此时,我有一个要进一步处理的节点列表,以及自首次解析以来已被大量修剪的树。
我缺少的是测试节点到进程列表中的特定节点是否仍然存在于解析树中的方法。如果它不是树的一部分,那意味着它是我之前删除的一个节点的后代,我想丢弃它。问题是没有一种明显的方法可以廉价地进行这项测试。即使已从该节点上的_ElementTree.iter()
调用_ElementTree
中删除节点,也会返回原始树。
我可以在每个要处理的节点上调用getroottree()
并检查我期望的树内节点的根元素,但这是O(n)并且对于深度DOM不能很好地扩展树。
有人知道给定iterancestors()
和Element
的恒定时间操作,以测试前者是否属于后者?
我意识到向上遍历节点的父链可能是进行此测试的唯一方法,任何更快的方法都需要库实现一些簿记。
答案 0 :(得分: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)