Come usare XPath contiene () qui?


142

Sto cercando di imparare XPath. Ho visto gli altri contains()esempi qui intorno, ma nulla che utilizza un operatore AND . Non riesco a farlo funzionare:

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

Sopra:

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

questo funziona per me, l'ho provato su whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm
mihi,

Risposte:


199

Sei solo alla ricerca al primo libambino nella query si dispone invece di cercare qualsiasi lielemento figlio che può contenere il testo, 'Model'. Ciò di cui hai bisogno è una query come la seguente:

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

Questa query vi darà gli elementi che hanno una classdi featureListcon uno o più lifigli che contengono il testo, 'Model'.


13
+1 - Il "./" è un po 'fuorviante - suggerisce che qualsiasi cosa diversa dal nodo corrente sarebbe presa in considerazione quando lo si lascia fuori, ma in realtà è ridondante: "// ul [@ class =' featureList 'e li [contiene (.,' Modello ')]] "è la stessa cosa.
Tomalak,

4
Sì, ero solo preciso. Molto probabilmente troppo specifico.
Jeff Yates,

Se non è disponibile licon Modelin ul, la andcondizione non riuscirà. Quindi la andcondizione ritorna falsesul set vuoto, è corretta?
damluar,

58

Ho già dato il mio +1 alla soluzione di Jeff Yates.

Ecco una breve spiegazione del perché il tuo approccio non funziona. Questo:

// ul [@ class = 'featureList' e contiene (li, 'Model')]

incontra una limitazione della contains()funzione (o qualsiasi altra funzione di stringa in XPath, per quella materia).

Il primo argomento dovrebbe essere una stringa. Se gli dai un elenco di nodi (dandogli " li" lo fa), deve aver luogo una conversione in stringa. Ma questa conversione viene eseguita solo per il primo nodo nell'elenco.

Nel tuo caso il primo nodo nell'elenco è <li><b>Type:</b> Clip Fan</li>(convertito in una stringa: " Type: Clip Fan"), il che significa che questo:

// ul [@ class = 'featureList' e contiene (li, 'Type')]

selezionerebbe effettivamente un nodo!


1
bello, ho faticato a capire perché domande come: ".//td[contains(.//*,'something ')]" funzionano solo fino a una profondità di 1. Avevo capito come farlo funzionare ma non lo ero sicuro di come funzionasse quanto sopra. Ciò di cui avevo effettivamente bisogno era ".//td[.//*[contains(.,'something ')]]"
JonnyRaa,

11

Questa è una nuova risposta a una vecchia domanda su un malinteso comune su contains()XPath ...

Riepilogo: contains()significa che contiene una sottostringa , non contiene un nodo .

Spiegazione dettagliata

Questo XPath è spesso frainteso:

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

Interpretazione errata: selezionare quegli ulelementi che contengono un lielemento con Modelal suo interno.

Questo è sbagliato perché

  1. contains(x,y)si aspetta xche sia una stringa e
  2. la regola XPath per convertire più elementi in una stringa è questa :

    Un set di nodi viene convertito in una stringa restituendo il valore di stringa del nodo nel set di nodi che è il primo nell'ordine del documento . Se il set di nodi è vuoto, viene restituita una stringa vuota.

Interpretazione corretta: selezionare quegli ulelementi il ​​cui primo li figlio ha un valore stringa che contiene una Modelsottostringa.

Esempi

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')]seleziona l' one ulelemento.

    Nota: L' two ulelemento non è selezionato perché la stringa-valore del primo lifiglio del two ulè Foo, che non contiene la Modelsottostringa.

  • //ul[li[contains(.,'Model')]]seleziona gli elementi onee two ul.

    Nota: entrambi gli ulelementi sono selezionati perché contains()applicati a ciascuno liindividualmente. (Pertanto, viene evitata la complessa regola di conversione da più elementi a stringa.) Entrambi gli ulelementi hanno un lifiglio il cui valore di stringa contiene la Modelsottostringa - la posizione lidell'elemento non conta più.

Guarda anche


-2
//ul[@class="featureList" and li//text()[contains(., "Model")]]

-5

Incolla containsqui il mio esempio:

//table[contains(@class, "EC_result")]/tbody

2
Non ci sono tableelementi o EC_resultvalori di classe nel codice di OP. Questa risposta non ha senso qui e dovrebbe essere eliminata.
kjhughes,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.