2010-02-01 40 views

回答

52

如果您將「不是後代」翻譯爲「沒有祖先」,您會得到表達式//*[not(ancestor::X)]。這將返回文檔中的所有節點,這些節點不是名爲「X」的節點的後代。

16

jarnbjo指出了直觀的方法來做到這一點,使用//*[not(ancestor::X)]。這具有非常大的優點,無論文檔的結構如何,它都可以工作,並且這是您在大多數情況下應該使用的。

但是,如果你有一個非常大的文件,它可能是非常低效的。這是一個非常昂貴的查詢。它告訴XPath處理器訪問文檔中的每個節點並檢查其祖先節點是否存在名爲X的元素。雖然XPath處理器可能足夠聰明以知道它不需要訪問X的後代要評估該查詢,這不太可能。

如果您有關於X元素位置的一些信息,並且您非常小心,則可以編寫更高效的查詢。例如,如果X是頂級元素的子元素,並且它有很多後代,這將是更快:

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

那找到頂級元素,它的所有直系子的,以及其任何直系子女的後代(不是X),它不會檢查任何X的後代。

同樣,如果你知道X是接近樹的底部,此查詢可能會更有效:

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

,因爲它不會審查它測試每個節點整個祖先軸,只是最後三個元素。 (除非XPath處理器足夠笨重以檢查軸上的每個節點,當它執行使用position()的測試時,可能是這樣。)

正如我所說,雖然大多數時候最簡單的版本將是最好的,大部分時間都是我自己使用的。