2010-02-01 10 views

Respuesta

52

Si traduce "no son descendientes" a "no tienen antecesor", obtiene la expresión //*[not(ancestor::X)]. Esto devolverá todos los nodos en un documento, que no son descendientes de nodos llamados "X".

16

jarnbjo señala la forma intuitiva de hacerlo, usar //*[not(ancestor::X)]. Esto tiene el gran mérito de que funcionará independientemente de cómo esté estructurado su documento, y es lo que debe usar en la mayoría de las circunstancias.

Pero si tiene un documento muy grande, puede ser extremadamente ineficiente. Esa es una consulta realmente costosa. Le dice al procesador XPath que visite cada nodo en el documento y examine su nodo ancestro para detectar la presencia de un elemento llamado X. Si bien es posible que el procesador XPath sea lo suficientemente inteligente como para saber que no necesita visitar a los descendientes de X para evaluar esa consulta, no es probable.

Si tiene alguna información sobre dónde está el elemento X, y tiene cuidado, puede escribir una consulta más eficiente. Por ejemplo, si X es un hijo del elemento de nivel superior, y tiene una gran cantidad de descendientes, esto será mucho más rápido:

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

que encuentra el elemento de nivel superior, todos sus hijos inmediatos, y los descendientes de cualquiera de sus hijos inmediatos no se llaman X. No examinará a ninguno de los descendientes de X.

Del mismo modo, si usted sabe que X está cerca de la parte inferior del árbol, esta consulta puede ser más eficiente:

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

porque no va a examinar todo el eje ancestro para cada nodo se pone a prueba, solo sus últimos tres elementos. (A menos que el procesador XPath sea lo suficientemente tonto como para examinar cada nodo en un eje cuando está realizando pruebas que usan position(), que podría ser).

Como dije, la mayoría de las veces la versión más simple va a ser la lo mejor, y la mayoría de las veces es lo que usaría yo mismo.

Cuestiones relacionadas