web-dev-qa-db-fra.com

Comment utiliser XPath contient () ici?

J'essaie d'apprendre xpath. J'ai regardé l'autre contient () des exemples ici, mais rien qui utilise un opérateur AND. Je n'arrive pas à faire fonctionner ça:

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

Sur:

...
<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>
...
136
ryeguy

Vous ne regardez que le premier enfant li dans la requête que vous avez au lieu de rechercher un élément enfant li pouvant contenir le texte, 'Model'. Ce dont vous avez besoin est une requête comme celle-ci:

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

Cette requête vous donnera les éléments qui ont une class sur featureList avec un ou plusieurs enfants li qui contiennent le texte, 'Model'.

191
Jeff Yates

J'ai déjà donné mon +1 à la solution de Jeff Yates.

Voici une explication rapide pour laquelle votre approche ne fonctionne pas. Cette:

// ul [@ class = 'featureList' et contient (li, 'Model')]

rencontre une limitation de la fonction contains() (ou de toute autre fonction de chaîne dans XPath, d'ailleurs).

Le premier argument est censé être une chaîne. Si vous lui fournissez une liste de noeuds (en lui donnant "li"), une conversion en chaîne doit avoir lieu. Mais cette conversion est effectuée uniquement pour le premier nœud de la liste.

Dans votre cas, le premier noeud de la liste est <li><b>Type:</b> Clip Fan</li> (converti en chaîne: "Type: Clip Fan"), ce qui signifie que:

// ul [@ class = 'featureList' et contient (li, 'Type')]

serait effectivement sélectionner un noeud!

57
Tomalak

Ceci est une nouvelle réponse à une vieille question sur un idée fausse commune à propos de contains() dans XPath ...

Résumé: contains() signifie contient une sous-chaîne, pas contient un nœud.

Explication détaillée

Ce XPath est souvent mal interprété:

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

Mauvaise interprétation: Sélectionnez ces ul éléments qui contiennent ​​un li élément avec Model dedans.

C'est faux parce que

  1. contains(x,y) s'attend à ce que x soit une chaîne, et
  2. la règle XPath pour convertir plusieurs éléments en une chaîne est this :

    Un ensemble de nœuds est converti en une chaîne en renvoyant la valeur valeur-chaîne du nœud de l'ensemble de nœuds ayant la première position dans ordre du document . Si l'ensemble de nœuds est vide, une chaîne vide est renvoyée.

Interprétation correcte: Sélectionnez ces ul éléments dont premierli enfant a un chaîne-valeur que contient ​​ une sous-chaîne Model.

Exemples

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')] sélectionne l'élément oneul.

    Remarque: L'élément twoul n'est pas sélectionné car la valeur de chaîne du premier li enfant de la twoul est Foo, qui ne contient pas la sous-chaîne Model.

  • //ul[li[contains(.,'Model')]] sélectionne les éléments one et twoul.

    Remarque: Les deux éléments ul sont sélectionnés car contains() est appliqué à chaque li individuellement. (Ainsi, la règle de conversion délicate de plusieurs éléments en chaînes est évitée.) Les deux éléments ul ont un enfant li dont la valeur de chaîne contient la chaîne Model. li l'élément n'a plus d'importance.

Voir également

6
kjhughes
//ul[@class="featureList" and li//text()[contains(., "Model")]]
0
runrig