XPath: ¿Cómo seleccionar elementos en función de su valor?

221

Soy nuevo en el uso de XPath y esta puede ser una pregunta básica. Ten paciencia conmigo y ayúdame a resolver el problema. Tengo un archivo XML como este:

<RootNode>
  <FirstChild>
    <Element attribute1="abc" attribute2="xyz">Data</Element>
  <FirstChild>
</RootNode>

Puedo validar la presencia de una <Element>etiqueta con:

// Elemento [@ attribute1 = "abc" y @ attribute2 = "xyz"]

Ahora también quiero verificar el valor de la etiqueta para la cadena "Data". Para lograr esto, me dijeron que usara:

// Elemento [@ attribute1 = "abc" y @ attribute2 = "xyz" y Datos]

Cuando uso la expresión posterior obtengo el siguiente error:

Mensaje de error de aserción: no hay nodos coincidentes //Element[@attribute1="abc" and @attribute2="xyz" and Data]

Por favor, avísenme si la expresión XPath que he usado es válida. Si no, ¿cuál será la expresión XPath válida?

vcosk
fuente

Respuestas:

329

La condición a continuación:

//Element[@attribute1="abc" and @attribute2="xyz" and Data]

comprueba la existencia de los datos del elemento dentro del elemento y no los datos del valor del elemento.

En cambio, puedes usar

//Element[@attribute1="abc" and @attribute2="xyz" and text()="Data"]
Usuario SO
fuente
25
//Element[@attribute1="abc" and @attribute2="xyz" and .="Data"]

La razón por la que agrego esta respuesta es que quiero explicar la relación de .y text().

Lo primero es cuando se usa [], solo hay dos tipos de datos:

  1. [number] seleccionar un nodo del conjunto de nodos
  2. [bool] para filtrar un conjunto de nodos de un conjunto de nodos

En este caso, el valor se evalúa como booleano por función boolean(), y hay una regla:

Los filtros siempre se evalúan con respecto a un contexto.

Cuando necesita comparar text()o .con una cadena "Data", primero usa la string()función para transformarlos al tipo de cadena, que obtiene un resultado booleano.

Hay dos reglas importantes sobre string():

  1. La string()función convierte un conjunto de nodos en una cadena al devolver el valor de cadena del primer nodo en el conjunto de nodos, que en algunos casos puede producir resultados inesperados.

    text()es una ruta relativa que devuelve un conjunto de nodos que contiene todo el nodo de texto del nodo actual (nodo de contexto), como ["Data"]. Cuando es evaluado por string(["Data"]), devolverá el primer nodo del conjunto de nodos, por lo que obtendrá "Datos" solo cuando haya un solo nodo de texto en el conjunto de nodos.

  2. Si desea que la string()función concatene todo el texto secundario, debe pasar un solo nodo en lugar de un conjunto de nodos.

    Por ejemplo, obtenemos un conjunto de nodos ['a', 'b'], puede pasar allí el nodo primario string(parent), esto devolverá 'ab', y por causa string(.)en su caso devolverá una cadena concatenada "Data".

Ambas formas obtendrán el mismo resultado solo cuando haya un nodo de texto.

宏杰 李
fuente