Exatamente quando a direção reversa de um eixo se aplica?
Aqueles que estão familiarizados com XPath sabem que alguns eixos, comopreceding::
são eixos invertidos. E se você colocar um predicado posicional em uma expressão construída com um eixo reverso, poderá estar contando para trás em vez de para frente. Por exemplo.
$foo/preceding-sibling::*[1]
retorna o elemento irmão anterior pouco antes$foo
, não o primeiro elemento irmão precedente (na ordem do documento).
Mas então você encontra variações onde esta regra parece estar quebrada, dependendo de quão distante está o predicado posicional do eixo reverso. Por exemplo.
($foo/preceding-sibling::*)[1]
conta para frente a partir do início do documento, não para trás$foo
.
Hoje eu estava escrevendo algum código onde eu tinha uma expressão como
$foo/preceding::bar[not(parent::baz)][1]
Eu queria contar para trás$foo
. Mas foi meu predicado posicional muito longe dopreceding::
eixo? Se a expressão tivesse perdido a direção inversa antes de adicionar o[1]
? Eu pensei que provavelmente não funcionaria, então eu mudei para
$foo/preceding::bar[not(parent::baz)][last()]
mas então eu não tinha certeza da direção, então coloquei parênteses para ter certeza:
($foo/preceding::bar[not(parent::baz)])[last()]
No entanto, os parênteses extras são um pouco confusos, e eu pensei que a expressão pode ser menos eficiente, se realmente tem que contar a partir do início do documento de entrada (grande) em vez de para trás de$foo
. Foi realmente necessário fazer assim?
Finalmente testei a expressão original e descobri, para minha surpresa, que funcionava! Então a intervenção[not(parent::baz)]
não fez a expressão perder a direção inversa, afinal.
Esse problema foi resolvido, mas cheguei ao ponto em que gostaria de ter um melhor controle sobre quando posso esperar que a direção inversa de um eixo seja aplicada. Minha pergunta é:Em que ponto (s) uma expressão XPath usando um eixo reverso perde sua direção inversa?
Eu acredito que encontrei a resposta agora, então responderei a minha própria pergunta. Mas eu não consegui encontrar a resposta no SO, e é algo que me incomoda o tempo suficiente para valer a pena perguntar e responder aqui.