xpath:获取没有X祖先的节点

我想要一个xml文档中不是节点X的后代的所有节点。

(我的实际问题稍微复杂一些,但是我现在被“不是子孙”的部分所困)。

如果你把“不是子孙”翻译成“没有祖先”,你会得到expression式//*[not(ancestor::X)] 。 这将返回文档中的所有节点,这些节点不是名为“X”的节点的后代。

jarnbjo指出了直观的方法来使用//*[not(ancestor::X)] 。 这具有非常大的优点,无论文档的结构如何,它都可以工作,在大多数情况下,这是您应该使用的。

但是,如果你有一个非常大的文件,这可能是非常低效的。 这是一个非常昂贵的查询。 它告诉XPath处理器访问文档中的每个节点,并检查其祖先节点是否存在一个名为X的元素。虽然XPath处理器可能足够聪明,知道它不需要访问X的后代评估该查询,这是不可能的。

如果您有关于X元素的位置的一些信息,并且您非常小心,则可以编写更高效的查询。 例如,如果X是顶层元素的子元素,并且有很多后代,这将会快得多:

 /* | /*/* | /*/*[not(name()='X')]//* 

find顶层元素,它的所有直接子元素,以及任何直接子元素的后代(不是X),它不会检查X的后代。

同样,如果您知道X接近树的底部,则此查询可能更有效:

 //*[not(ancestor::*[position() <= 3][X])] 

因为它不会检查它testing的每个节点的整个祖先轴,只是它的最后三个元素。 (除非XPath处理器在执行使用position()testing时足够愚蠢,以检查轴上的每个节点,这可能是)。

正如我所说,虽然大多数时候最简单的版本将是最好的,大部分时间是我自己使用的。