Я хочу все узлы xml документа, которые не являются потомками узлов X.
(Моя фактическая проблема немного более сложна, но я застреваю с, "не потомки" часть прямо сейчас).
Если вы перевели «не потомки» не имеют предка «нет предка», вы получаете выражение // * [не (Arcestor :: x)]
. Это вернет все узлы в документе, которые не являются потомками узлов, названных «X».
jarnbjo указывает на интуитивно понятный способ сделать это, используя // * [not (ancestor :: X)]
.У этого есть очень большое достоинство, что он будет работать независимо от того, как ваш документ структурирован, и это то, что вам следует использовать в большинстве случаев.
Но если у вас очень большой документ, это может быть крайне неэффективно. Это действительно дорогой запрос. Он сообщает процессору XPath посетить каждый узел в документе и проверить его узел-предок на наличие элемента с именем X. Хотя возможно, что процессор XPath достаточно умен, чтобы знать, что ему не нужно посещать потомков X чтобы оценить этот запрос, это маловероятно.
Если у вас есть информация о том, где находится элемент X, и вы будете осторожны, вы можете написать более эффективный запрос. Например, если X является дочерним элементом элемента верхнего уровня и у него много потомков, это будет намного быстрее:
/* | /*/* | /*/*[not(name()='X')]//*
Это обнаружит элемент верхнего уровня, все его непосредственные дочерние элементы и потомков элемента любой из его непосредственных потомков, не названный X. Он не будет проверять потомков X.
Точно так же, если вы знаете, что X находится близко к нижней части дерева, этот запрос может быть более эффективным:
//*[not(ancestor::*[position() <= 3][X])]
потому что он не будет проверять всю ось предков для каждого проверяемого узла, а только его последние три элемента . (Если только процессор XPath не настолько глуп, чтобы исследовать каждый узел на оси, когда он выполняет тесты, использующие position ()
, что может быть.)
Однако, как я уже сказал, большую часть времени самая простая версия будет лучшей, и большую часть времени я бы использовал ее сам.