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 „ &”?


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


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.


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


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.


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)


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ść!


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?


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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.