Używanie XPATH do wyszukiwania tekstu zawierającego & nbsp;

120

Używam XPather Browser sprawdzić moje wyrażeń XPath na stronie HTML.

Moim końcowym celem jest użycie tych wyrażeń w Selenium do testowania moich interfejsów użytkownika.

Mam plik HTML o treści podobnej do tej:

<tr>
  <td> abc </td>
  <td> & nbsp; </td>
</tr>

Chcę wybrać węzeł z tekstem zawierającym ciąg „ &nbsp;”.

Z normalnym ciągiem znaków, takim jak „abc”, nie ma problemu. Używam XPATH podobnego do //td[text()="abc"].

Kiedy próbuję z XPATH, jak //td[text()="&nbsp;"]nic nie zwraca. Czy istnieje specjalna zasada dotycząca tekstów ze znakiem „ &”?

Bergeroy
źródło
Czy Twoja rzeczywista transformacja XSL nic nie zwraca? A może tylko Xpather?
Zack The Human

Odpowiedzi:

89

Wygląda na to, że OpenQA , twórcy Selenium, już rozwiązali ten problem. Zdefiniowali pewne zmienne, aby wyraźnie dopasować białe spacje. W moim przypadku muszę użyć XPATH podobnego do //td[text()="${nbsp}"].

Przedstawiłem tutaj tekst z OpenQA dotyczący tego problemu (znaleziony tutaj ):

HTML automatycznie normalizuje białe znaki w elementach, ignorując początkowe / końcowe spacje i konwertując dodatkowe spacje, tabulatory i znaki nowej linii w jedną spację. Kiedy Selenium odczytuje tekst ze strony, próbuje powielić to zachowanie, więc możesz zignorować wszystkie tabulatory i znaki nowej linii w kodzie HTML i wykonywać potwierdzenia na podstawie tego, jak tekst wygląda w przeglądarce po renderowaniu. Robimy to, zastępując wszystkie niewidoczne białe znaki (w tym nierozdzielającą spację „ &nbsp;”) pojedynczą spacją. Wszystkie widoczne znaki nowej linii ( <br>, <p>i <pre>sformatowane nowe linie) powinny być zachowane.

Używamy tej samej logiki normalizacji w tekście tabel przypadków testowych HTML Selenese. Ma to wiele zalet. Po pierwsze, nie musisz zaglądać do źródła HTML strony, aby dowiedzieć się, jakie powinny być twoje twierdzenia; &nbsp;Symbole „ ” są niewidoczne dla użytkownika końcowego, więc nie powinieneś się o nie martwić pisząc testy seleńskie. (Nie musisz umieszczać &nbsp;znaczników „ ” w swoim przypadku testowym, aby assertText w polu zawierającym „ &nbsp;”.) Możesz także umieścić dodatkowe znaki nowej linii i spacje w swoich <td>tagach seleńskich ; ponieważ używamy tej samej logiki normalizacji w przypadku testowym, co w przypadku tekstu, możemy zapewnić, że potwierdzenia i wyodrębniony tekst będą dokładnie pasować.

Stwarza to pewien problem w tych rzadkich przypadkach, gdy naprawdę chcesz / musisz wstawić dodatkowe białe znaki w swoim przypadku testowym. Na przykład może być konieczne wpisanie tekstu w takim polu: „ foo ”. Ale jeśli po prostu napiszesz <td>foo </td>w swoim przypadku testowym Selenese, zastąpimy Twoje dodatkowe spacje tylko jedną spacją.

Ten problem ma proste obejście. W Selenese zdefiniowaliśmy zmienną ${space}, której wartością jest pojedyncza spacja. Można użyć ${space}, aby wstawić spację, które nie zostaną automatycznie przycięte, tak: <td>foo${space}${space}${space}</td>. Dołączyliśmy również zmienną ${nbsp}, której można użyć do wstawienia nierozdzielającej spacji.

Zwróć uwagę, że XPath nie normalizują białych znaków tak jak my. Jeśli trzeba napisać XPath jak //div[text()="hello world"]ale HTML linku jest naprawdę „ hello&nbsp;world”, trzeba włożyć prawdziwy „ &nbsp;” do swojego Selenese przypadku testowego, aby ją dopasować, tak: //div[text()="hello${nbsp}world"].

Bergeroy
źródło
1
Link do OpenQA nie ładuje się już pomyślnie
kjosh
1
Chcę tylko zauważyć, że $ {nbsp} nie działa dla mnie w narzędziach programistycznych Selenium ani Chrome \u00a0. To, co zadziałało, to wpisanie nieprzerwanej spacji na Macu Alt+Shift+Space. Wyszukiwanie w sieci mówi Alt+0160w systemie Windows
Cynic,
25

Zauważyłem, że mogę dopasować, kiedy wprowadzam zakodowaną na stałe niezłamującą spację (U + 00A0), wpisując Alt + 0160 w systemie Windows między dwoma cudzysłowami ...

//table[@id='TableID']//td[text()=' ']

pracował dla mnie ze specjalnym char.

Z tego, co zrozumiałem, standard XPath 1.0 nie obsługuje ucieczki znaków Unicode. Wygląda na to, że w XPath 2.0 są funkcje do tego, ale wygląda na to, że Firefox ich nie obsługuje (albo coś źle zrozumiałem). Musisz więc zrobić z lokalną stroną kodową. Brzydkie, wiem.

Właściwie wygląda na to, że standard opiera się na języku programowania używającym XPath, aby zapewnić prawidłową sekwencję ucieczki Unicode ... Więc jakoś postąpiłem właściwie.

PhiLho
źródło
Korzystanie z Xpather 1.4.1 w przeglądarce Firefox 2 // td [text () = ''] nie daje żadnych wyników.
Zack The Human
Przepraszam. Na mnie to nie działa. Moim końcowym celem jest użycie go w Selenium do testów moich interfejsów internetowych. Sam selen zachowuje wyrażenia testowe w strukturze XML, a typowanie w Alt Windows wydaje się być zagubione. Ponadto mój & # 160; zwraca jako plik XML.
Bergeroy
Zack, jak napisałem, musisz zastąpić spację między dwoma cudzysłowami znakiem utworzonym przez Alt + 0160 (na klawiaturze numerycznej).
PhiLho
4
Muszę też z powodzeniem pracować z PHP:$col = $xpath->query("//p[text()=\"\xC2\xA0\"]");
hakre
@Bergory Działa to przy użyciu Protractora ze sterownikiem Selenium
Damian Green
4

Spróbuj użyć jednostki dziesiętnej &#160;zamiast nazwanej jednostki. Jeśli to nie zadziała, powinieneś być w stanie po prostu użyć znaku Unicode dla nierozdzielającej spacji zamiast &nbsp;jednostki.

(Uwaga: nie próbowałem tego w XPather, ale wypróbowałem to w Oxygen).

James Sulak
źródło
1

Należy pamiętać, że procesor XML zgodnych ze standardami będzie zastąpiły żadnych odniesień podmiotu innego niż XML standardowych pięciu z nich ( &amp;, &gt;, &lt;, &apos;, &quot;) z odpowiednim znaku w kodowaniu docelowym do czasu wyrażenia XPath są oceniane. Biorąc pod uwagę to zachowanie, sugestie PhiLho i jsulak są drogą do zrobienia, jeśli chcesz pracować z narzędziami XML. Po wprowadzeniu &#160;wyrażenia XPath należy je przekonwertować na odpowiednią sekwencję bajtów przed zastosowaniem wyrażenia XPath.

ChuckB
źródło
1
Nie, jeśli spróbujesz / użyjesz XPath w XPather (GUI) lub JavaScript (bez automatycznego zastępowania jednostek, ponieważ nie jesteśmy w XML). Dobra rada w innych środowiskach XML (XSTL?).
PhiLho
1

Zgodnie z podanym kodem HTML:

<tr>
  <td>abc</td>
  <td>&nbsp;</td>
</tr>

Aby zlokalizować węzeł za pomocą ciągu &nbsp;, możesz użyć jednego z poniższych rozwiązania oparte na:

  • Używając text():

    "//td[text()='\u00A0']"
  • Używając contains():

    "//td[contains(., '\u00A0')]"

Najlepiej jednak byłoby uniknąć znaku BEZ PRZERWY SPACJI i użyć jednej z następujących strategii lokalizacji :

  • Korzystanie z <tr>węzła nadrzędnego i following-sibling:

    "//tr//following-sibling::td[2]"
  • Używając starts-with():

    "//tr//td[last()]"
  • Korzystanie z poprzedzającego <td>węzła i followingnode andnastępującego-rodzeństwa ":

    "//td[text()='abc']//following::td[1]"

Odniesienie

Odpowiednie szczegółowe omówienie można znaleźć w:


tl; dr

Znak Unicode „SPACJA BEZ PRZERW” (U + 00A0)

DebanjanB
źródło
0

Nie mogę znaleźć dopasowania za pomocą Xpather, ale poniższe działały dla mnie ze zwykłymi plikami XML i XSL w Notatniku XML firmy Microsoft:

<xsl:value-of select="count(//td[text()='&nbsp;'])" />

Zwracana wartość to 1, co jest poprawną wartością w moim przypadku testowym.

Jednak musiałem zadeklarować nbsp jako jednostkę w moim XML i XSL, używając następującego:

<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#160;"> ]>

Nie jestem pewien, czy to pomaga, ale udało mi się rzeczywiście znaleźć nbsp za pomocą wyrażenia XPath.

Edycja: mój przykładowy kod w rzeczywistości zawiera znaki „& nbsp;” ale podświetlanie składni JavaScript konwertuje go na znak spacji. Nie daj się zwieść!

Zack The Human
źródło
Możesz edytować swój przykładowy kod, tak jak to zostało zrobione dla przykładu w moim pytaniu. Zastąp encję nbsp przez & amp; nbsp ;.
Bergeroy
0

Wyszukaj &nbsp;czy tylko nbsp- próbowałeś tego?

Nakilon
źródło
Zdaję sobie sprawę, że to powinno działać, ale nie jest do końca pewne, co znajdę. W XPATH musi istnieć sposób, aby zakodować określony sposób, aby dopasować to, czego szukam.
Bergeroy
Może powinienem spojrzeć na wyrażenie regularne.
Bergeroy