Ich versuche xpath zu lernen. Ich habe mir die anderen enthält () Beispiele hier angesehen, aber nichts, das einen AND-Operator verwendet. Ich kann das nicht zum Laufen bringen:
//ul[@class='featureList' and contains(li, 'Model')]
Auf:
...
<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>
...
Sie suchen nur das erste li
untergeordnete Element in der Abfrage, anstatt nach einem li
untergeordneten Element zu suchen, das möglicherweise den Text 'Model'
Enthält. Was Sie brauchen, ist eine Abfrage wie die folgende:
//ul[@class='featureList' and ./li[contains(.,'Model')]]
Diese Abfrage gibt Ihnen die Elemente mit einem class
von featureList
mit einem oder mehreren li
untergeordneten Elementen, die den Text 'Model'
Enthalten.
Ich habe Jeff Yates 'Lösung bereits meine +1 gegeben.
Hier ist eine kurze Erklärung, warum Ihr Ansatz nicht funktioniert. Diese:
// ul [@ class = 'featureList' und enthält (li, 'Model')]
stößt auf eine Einschränkung der Funktion contains()
(oder einer anderen Zeichenfolgenfunktion in XPath).
Das erste Argument soll eine Zeichenfolge sein. Wenn Sie ihm eine Knotenliste zuführen (wenn Sie dafür "li
" angeben), muss eine Konvertierung in einen String erfolgen. Diese Konvertierung wird jedoch nur für den ersten Knoten in der Liste durchgeführt.
In Ihrem Fall ist der erste Knoten in der Liste <li><b>Type:</b> Clip Fan</li>
(in eine Zeichenfolge umgewandelt: "Type: Clip Fan
") was bedeutet, dass dies:
// ul [@ class = 'featureList' und enthält (li, 'Type')]
würde eigentlich einen knoten auswählen!
Dies ist eine neue Antwort auf eine alte Frage zu einem häufigen Missverständnis über contains()
in XPath ...
Zusammenfassung: contains()
bedeutet enthält einen Teilstring, nicht enthält einen Knoten.
Dieser XPath wird oft falsch interpretiert:
//ul[contains(li, 'Model')]
Falsche Interpretation: Wählen Sie die ul
- Elemente aus, die enthalten ein li
- Element mit Model
drin.
Das ist falsch, weil
contains(x,y)
erwartet, dass x
ein String ist, unddie XPath-Regel zum Konvertieren mehrerer Elemente in einen String lautet this :
Eine Knotenmenge wird in eine Zeichenfolge konvertiert, indem Zeichenfolgenwert des Knotens in der Knotenmenge zurückgegeben wird, der an erster Stelle in Dokumentreihenfolge steht. Wenn der Knotensatz leer ist, wird eine leere Zeichenfolge zurückgegeben.
Richtige Interpretation: Wählen Sie die Elemente ul
aus, deren firstli
Kind hat ein String-Wert dass enthält ein Model
- Teilstring ist.
[~ # ~] 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')]
wählt das Element one
ul
aus.
Hinweis: Das Element two
ul
ist nicht ausgewählt, da der Zeichenfolgenwert des ersten Elements li
untergeordnetes Element von two
ul
ist Foo
, das den Teilstring Model
nicht enthält.
//ul[li[contains(.,'Model')]]
wählt die Elemente one
und two
ul
aus.
Hinweis: Beide ul
- Elemente werden ausgewählt, da contains()
auf jedes li
einzeln angewendet wird. (Somit wird die schwierige Konvertierungsregel von mehreren Elementen in Zeichenfolgen vermieden.) Beide ul
- Elemente haben ein untergeordnetes li
- Element, dessen Zeichenfolgenwert die Unterzeichenfolge Model
enthält. Die Position des Elements li
spielt keine Rolle mehr.
//ul[@class="featureList" and li//text()[contains(., "Model")]]