Jaka jest poprawna ścieżka XPath do wybierania atrybutów zawierających „foo”?

176

Biorąc pod uwagę ten kod XML, to, co XPath zwraca wszystkie elementy, których propatrybut zawiera Foo(pierwsze trzy węzły):

<bla>
 <a prop="Foo1"/>
 <a prop="Foo2"/>
 <a prop="3Foo"/>
 <a prop="Bar"/>
</bla>
zrywak234
źródło
1
Dlaczego wszyscy patrzą na atrybut „prop”? Przegapiłem coś? Mówi tylko, że pobierz pierwsze trzy węzły.
6
Wszyscy patrzą na atrybut rekwizytu, ponieważ o to pytano. Pobierz wszystkie węzły, w których prop zawiera „Foo”. Dodaj <a prop="Foo5" />, a zobaczysz, dlaczego nie chodzi tylko o „pierwsze trzy węzły”…
erlando,
Pytanie w treści jest słabo sformułowane, niezależnie od tytułu. Czy foo naprawdę może znajdować się w dowolnym atrybucie właściwości, czy naprawdę chcesz tylko pierwszych trzech węzłów?
3
Tak, zapoznaj się z tytułem (i nie krępuj się edytować).
ripper234
Jeśli potrzebujesz wielkości liter porównania Zobacz Find-an-element, którego atrybut-zawiera-a-text-case-insensitively
Michael Freidgeim

Odpowiedzi:

307
//a[contains(@prop,'Foo')]

Działa, jeśli użyję tego XML do odzyskania wyników.

<bla>
 <a prop="Foo1">a</a>
 <a prop="Foo2">b</a>
 <a prop="3Foo">c</a>
 <a prop="Bar">a</a>
</bla>

Edycja: Inną rzeczą wartą uwagi jest to, że chociaż XPath powyżej zwróci poprawną odpowiedź dla tego konkretnego xml, jeśli chcesz zagwarantować, że otrzymasz tylko elementy "a" w elemencie "bla", powinieneś, tak jak inni wspominali, również użyć

/bla/a[contains(@prop,'Foo')]

Spowoduje to przeszukanie wszystkich elementów „a” w całym dokumencie xml, niezależnie od tego, czy są one zagnieżdżone w elemencie „blah”

//a[contains(@prop,'Foo')]  

Dodałem to ze względu na dokładność i w duchu przepełnienia stosu. :)

zły
źródło
3
xmlme.comteraz przekierowuje do innego hosta i nie wydaje się hostować narzędzia ani niczego podobnego.
jpmc26
26

Ta XPath da ci wszystkie węzły, które mają atrybuty zawierające „Foo”, niezależnie od nazwy węzła lub nazwy atrybutu:

//attribute::*[contains(., 'Foo')]/..

Oczywiście, jeśli bardziej interesuje Cię zawartość samego atrybutu, a niekoniecznie jego węzeł nadrzędny, po prostu upuść / ..

//attribute::*[contains(., 'Foo')]
Alex Beynenson
źródło
2
Dla wszystkich węzłów//@*[contains(., 'Foo')]
aliopi
16
descendant-or-self::*[contains(@prop,'Foo')]

Lub:

/bla/a[contains(@prop,'Foo')]

Lub:

/bla/a[position() <= 3]

Rozcięto:

descendant-or-self::

Oś - przeszukaj każdy węzeł pod spodem i sam węzeł. Często lepiej to powiedzieć niż //. Spotkałem kilka implementacji, w których // oznacza gdziekolwiek (decendant lub self z węzła głównego). Inne używają domyślnej osi.

* or /bla/a

Tag - dopasowanie wieloznaczne, a / bla / a to ścieżka bezwzględna.

[contains(@prop,'Foo')] or [position() <= 3]

Stan w []. @prop jest skrótem od attribute :: prop, ponieważ atrybut to kolejna oś wyszukiwania. Alternatywnie możesz wybrać pierwsze 3 za pomocą funkcji position ().

1729
źródło
6

John C jest najbliższy, ale XPath rozróżnia wielkość liter, więc poprawna XPath to:

/bla/a[contains(@prop, 'Foo')]
Metro Smurf
źródło
4

Czy próbowałeś czegoś takiego:

// a [zawiera (@prop, "Foo")]

Nigdy wcześniej nie korzystałem z funkcji zawiera, ale podejrzewam, że powinna działać zgodnie z reklamą ...

toddk
źródło
@toddk ... celujesz w nieistniejący atrybut: @foo. Chciałbyś celować w @prop ;-)
Metro Smurf,
4

Jeśli chcesz również dopasować treść samego linku, użyj text ():

//a[contains(@href,"/some_link")][text()="Click here"]

SomeDudeSomewhere
źródło
2

/ bla / a [zawiera (@prop, "foo")]

David Hill
źródło
1

Dla powyższego kodu ... // * [zawiera (@ prop, 'foo')]

digiguru
źródło
dotyczy to dowolnego elementu z foo in, ale atrybut musi mieć wartość „prop”
digiguru
1

Spróbuj tego:

// a [zawiera (@ prop, 'foo')]

to powinno działać dla wszystkich znaczników „a” w dokumencie

Dani Duran
źródło