Pregunta sobre xpath, xml – ¿Cómo usar XPath contiene () aquí?

127

Estoy tratando de aprender xpath. Miré a los otros ejemplos que contiene () por aquí, pero nada que use un operador AND. No puedo hacer que esto funcione

//ul[@class='featureList' and contains(li, 'Model')]

En:

...
<ul class="featureList">

<li><b>Type:</b> Clip Fan</li><li><b>Feature:</b> Air Moved: 65 ft.
    Amps: 1.1
    Clip: Grips any surface up to 1.63"
    Plug: 3 prong grounded plug on heavy duty model
    Usage: Garage, Workshop, Dorm, Work-out room, Deck, Office & more.</li><li><b>Speed Setting:</b> 2 speeds</li><li><b>Color:</b> Black</li><li><b>Power Consumption:</b> 62 W</li><li><b>Height:</b> 14.5"</li><li><b>Width:</b> Grill Diameter: 9.5"</li><li><b>Length:</b> 11.5"</li>

<li><b>Model #: </b>CR1-0081-06</li>
<li><b>Item #: </b>N82E16896817007</li>
<li><b>Return Policy: </b></li>
</ul>
...
¿Qué te funciona? ryeguy
esto funciona para mí, lo probé enwhitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm mihi

Tu respuesta

4   la respuesta
-5

Pegar micontains ejemplo aquí:

//table[contains(@class, "EC_result")]/tbody
No haytable elemento oEC_result Valor de clase en el código de OP.Esta respuesta no tiene sentido aquí y debe ser eliminada. kjhughes
6

Esta es una nueva respuesta a una vieja pregunta sobre unMalentendido común acerca decontains() en XPath ...

Resumen:contains() mediocontiene una subcadena, no contiene un nodo.

Explicación detallada

Este XPath es a menudo mal interpretado:

//ul[contains(li, 'Model')]

Interpretación errónea: Seleccionar esosul elementos queContiene unli elemento conModel en eso.

Esto esta mal porque

contains(x,y) esperax ser una cadena, y

La regla XPath para convertir múltiples elementos a una cadena esesta:

Un conjunto de nodos se convierte en una cadena devolviendo elvalor de cadena del nodo en el conjunto de nodos que está primero enorden del documento. Si el conjunto de nodos está vacío, se devuelve una cadena vacía.

Interpretación correcta: Seleccionar esosul elementos cuyosprimero li el niño tiene unvalor de cadena esecontiene a Model subcadena

Ejemplos

XML

<r>
  <ul id="one">
    <li>Model A</li>
    <li>Foo</li>
  </ul>
  <ul id="two">
    <li>Foo</li>
    <li>Model A</li>
  </ul>
</r> 

XPaths

//ul[contains(li, 'Model')] selecciona elone ul elemento.

Nota: lostwo ul El elemento no está seleccionado porque el valor de cadena de la primerali hijo deltwo ul esFoo, que no contiene elModel subcadena

//ul[li[contains(.,'Model')]] selecciona elone ytwo ul elementos.

Nota: Ambosul los elementos son seleccionados porquecontains() se aplica a cada unoli individualmente. (Por lo tanto, se evita la regla de conversión de múltiples elementos a cadenas).ul los elementos tienen unali hijo cuyo valor de cadena contiene elModel subcadena - posición de lali El elemento ya no importa.

Ver tambiénPrueba de los nodos de texto () vs valores de cadena en XPath
181

Sólo estás mirando al primero.li Niño en la consulta que tienes en lugar de buscar cualquierli Elemento hijo que puede contener el texto,'Model'. Lo que necesitas es una consulta como la siguiente:

//ul[@class='featureList' and ./li[contains(.,'Model')]]

Esta consulta te dará los elementos que tienen unclass defeatureList con uno o masli niños que contienen el texto,'Model'.

+1 - El "./" es un poco engañoso; sugiere que cualquier otra cosa que no sea el nodo actual se tomará en cuenta cuando la omita, pero en realidad es redundante: "// ul [@ class = ' featureList 'y li [contiene (.,' Modelo ')]] es lo mismo. Tomalak
Si no hayli conModel enul, entonces eland la condición va a fallar. Asi queand condición devuelvefalse en el conjunto vacío, ¿es correcto? damluar
Sí, solo estaba siendo específico. Muy posiblemente demasiado específico. Jeff Yates
55

Aquí hay una explicación rápida de por qué su enfoque no funciona. Esta:

//ul[@class='featureList' and contains(li, 'Model')]

encuentra una limitación de lacontains() función (o cualquier otra función de cadena en XPath, para el caso).

El primer argumento se supone que es una cadena. Si lo alimentas con una lista de nodos (dandolo "li"hace eso), debe tener lugar una conversión a cadena. Pero esta conversión se realiza solo para el primer nodo de la lista.

En su caso, el primer nodo de la lista es<li><b>Type:</b> Clip Fan</li> (convertido a una cadena: "Type: Clip Fan") lo que significa que esto:

//ul[@class='featureList' and contains(li, 'Type')]

¡En realidad seleccionaría un nodo!

bueno, he estado luchando para averiguar por qué las consultas como: ".//td[contains(.//*,'something ')]" solo funcionan a una profundidad de 1. Descubrí cómo hacer que funcione, pero no estaba seguro de cómo funcionaba todo lo anterior. Lo que realmente necesitaba era ".//td[.//*[contains(. ,'something ')]]" JonnyRaa

Preguntas relacionadas