我希望xml文档的所有节点都不是节点X的后代。
(我的实际问题有点复杂,但我现在仍然坚持“不是后代”部分。)
答案 0 :(得分:61)
如果您将“不是后代”翻译为“没有祖先”,则会得到表达式//*[not(ancestor::X)]
。这将返回文档中的所有节点,这些节点不是名为“X”的节点的后代。
答案 1 :(得分:19)
jarnbjo指出了使用//*[not(ancestor::X)]
的直观方式。无论文档的结构如何,它都具有非常大的优点,并且它是您在大多数情况下应该使用的。
但是如果你有一个非常大的文件,它可能是非常低效的。这是一个非常昂贵的查询。它告诉XPath处理器访问文档中的每个节点并检查其祖先节点是否存在名为X的元素。虽然XPath处理器可能足够聪明,知道它不需要访问X的后代为了评估该查询,它不太可能。
如果您有关于X元素的位置的一些信息,并且您需要小心,那么您可以编写更有效的查询。例如,如果X是顶级元素的子元素,并且它有很多后代,那么这将更快:
/* | /*/* | /*/*[not(name()='X')]//*
找到顶级元素,它的所有直接子元素,以及任何未命名为X的直接子元素的后代。它不会检查X的任何后代。
同样,如果您知道X接近树的底部,则此查询可能更有效:
//*[not(ancestor::*[position() <= 3][X])]
因为它不会检查它测试的每个节点的整个祖先轴,只检查它的最后三个元素。 (除非XPath处理器足够愚蠢以检查轴上的每个节点,当它执行使用position()
的测试时,它可能是。)
正如我所说的那样,大多数时候最简单的版本是最好的,而且大部分时间都是我自己使用的版本。