Piszę zestaw testowy Selenium. A oto wyrażenie xpath, którego używam do dopasowania wszystkich przycisków „Modyfikuj” w tabeli danych.
//img[@title='Modify']
Moje pytanie brzmi: jak mogę odwiedzić dopasowane zestawy węzłów według indeksu? Próbowałem z
//img[@title='Modify'][i]
i
//img[@title='Modify' and position() = i]
Ale to nie działa. Próbowałem też z XPath checker (jedno rozszerzenie firefox). Znaleziono łącznie 13 dopasowań, więc nie mam pojęcia, jak mam wybrać jedno z nich. A może XPath obsługuje określony wybór węzłów, które nie znajdują się w tym samym węźle nadrzędnym?
W
i
XPath nie ma .Albo użyjesz liczb literalnych:
//img[@title='Modify'][1]
Lub możesz budować ciąg wyrażenia dynamicznie:
'//img[@title='Modify']['+i+']'
(ale pamiętaj, że dynamiczne wyrażenia XPath nie działają z poziomu XSLT).Tak:
(//img[@title='Modify'])[13]
Oznacza
//img[@title='Modify'][i]
to „dowolny<img>
z tytułem„ Modyfikuj ”i elementem podrzędnym o nazwie<i>
”.źródło
td
które były szóstym dzieckiem atr
i nie miały pustej treści://tr/td[6][string-length(text()) > 0]
Nie ma
i
w xpath nie jest do końca prawdą. Nadal możesz użyć,count()
aby znaleźć indeks.Rozważ następną stronę
<html> <head> <title>HTML Sample table</title> </head> <style> table, td, th { border: 1px solid black; font-size: 15px; font-family: Trebuchet MS, sans-serif; } table { border-collapse: collapse; width: 100%; } th, td { text-align: left; padding: 8px; } tr:nth-child(even){background-color: #f2f2f2} th { background-color: #4CAF50; color: white; } </style> <body> <table> <thead> <tr> <th>Heading 1</th> <th>Heading 2</th> <th>Heading 3</th> <th>Heading 4</th> <th>Heading 5</th> <th>Heading 6</th> </tr> </thead> <tbody> <tr> <td>Data row 1 col 1</td> <td>Data row 1 col 2</td> <td>Data row 1 col 3</td> <td>Data row 1 col 4</td> <td>Data row 1 col 5</td> <td>Data row 1 col 6</td> </tr> <tr> <td>Data row 2 col 1</td> <td>Data row 2 col 2</td> <td>Data row 2 col 3</td> <td>Data row 2 col 4</td> <td>Data row 2 col 5</td> <td>Data row 2 col 6</td> </tr> <tr> <td>Data row 3 col 1</td> <td>Data row 3 col 2</td> <td>Data row 3 col 3</td> <td>Data row 3 col 4</td> <td>Data row 3 col 5</td> <td>Data row 3 col 6</td> </tr> <tr> <td>Data row 4 col 1</td> <td>Data row 4 col 2</td> <td>Data row 4 col 3</td> <td>Data row 4 col 4</td> <td>Data row 4 col 5</td> <td>Data row 4 col 6</td> </tr> <tr> <td>Data row 5 col 1</td> <td>Data row 5 col 2</td> <td>Data row 5 col 3</td> <td>Data row 5 col 4</td> <td>Data row 5 col 5</td> <td>Data row 5 col 6</td> </tr> <tr> <td><button>Modify</button></td> <td><button>Modify</button></td> <td><button>Modify</button></td> <td><button>Modify</button></td> <td><button>Modify</button></td> <td><button>Modify</button></td> </tr> </tbody> </table> </br> <table> <thead> <tr> <th>Heading 7</th> <th>Heading 8</th> <th>Heading 9</th> <th>Heading 10</th> <th>Heading 11</th> <th>Heading 12</th> </tr> </thead> <tbody> <tr> <td>Data row 1 col 1</td> <td>Data row 1 col 2</td> <td>Data row 1 col 3</td> <td>Data row 1 col 4</td> <td>Data row 1 col 5</td> <td>Data row 1 col 6</td> </tr> <tr> <td>Data row 2 col 1</td> <td>Data row 2 col 2</td> <td>Data row 2 col 3</td> <td>Data row 2 col 4</td> <td>Data row 2 col 5</td> <td>Data row 2 col 6</td> </tr> <tr> <td>Data row 3 col 1</td> <td>Data row 3 col 2</td> <td>Data row 3 col 3</td> <td>Data row 3 col 4</td> <td>Data row 3 col 5</td> <td>Data row 3 col 6</td> </tr> <tr> <td>Data row 4 col 1</td> <td>Data row 4 col 2</td> <td>Data row 4 col 3</td> <td>Data row 4 col 4</td> <td>Data row 4 col 5</td> <td>Data row 4 col 6</td> </tr> <tr> <td>Data row 5 col 1</td> <td>Data row 5 col 2</td> <td>Data row 5 col 3</td> <td>Data row 5 col 4</td> <td>Data row 5 col 5</td> <td>Data row 5 col 6</td> </tr> <tr> <td><button>Modify</button></td> <td><button>Modify</button></td> <td><button>Modify</button></td> <td><button>Modify</button></td> <td><button>Modify</button></td> <td><button>Modify</button></td> </tr> </tbody> </table> </body> </html>
Strona zawiera 2 tabele i 6 kolumn, z których każda ma unikalne nazwy kolumn i 6 wierszy ze zmiennymi danymi. Ostatni wiersz zawiera
Modify
przycisk w obu tabelach.Zakładając, że użytkownik musi wybrać czwarty
Modify
przycisk z pierwszej tabeli na podstawie nagłówkaUżyj xpath
//th[.='Heading 4']/ancestor::thead/following-sibling::tbody/tr/td[count(//tr/th[.='Heading 4']/preceding-sibling::th)+1]/button
count()
Operator jest przydatna w takich sytuacjach.Logika:
Modify
przycisku za pomocą//th[.='Heading 4']
count(//tr/th[.='Heading 4']/preceding-sibling::th)+1
Pobierz wiersze dla odpowiedniego nagłówka za pomocą
//th[.='Heading 4']/ancestor::thead/following-sibling::tbody/tr/td[count(//tr/th[.='Heading 4']/preceding-sibling::th)+1]
Pobierz
Modify
przycisk z wyodrębnionej listy węzłów za pomocą//th[.='Heading 4']/ancestor::thead/following-sibling::tbody/tr/td[count(//tr/th[.='Heading 4']/preceding-sibling::th)+1]/button
źródło
td[count(../preceding-sibling::tr/th[.='Heading 4'])]/following-sibling::td
tego, że nie wpadam zatd[1]
każdym razem, gdy nie mam jakiegoś nagłówka :)jest skrótem od
stąd zwraca i-ty węzeł pod tym samym węzłem macierzystym.
Chcesz
źródło
/descendant::img[@title='Modify'][$index]
będzie działać dobrze. Zwróć również uwagę, że[i]
predykat sprawdza istnieniei
elementu potomnego.(// * [@ atrybut = 'wartość']) [indeks], aby znaleźć cel elementu podczas znajdowania w nim wielu dopasowań
źródło
Oto rozwiązanie dla zmiennej indeksu
Powiedzmy, że znalazłeś 5 elementów z tym samym lokalizatorem i chciałbyś wykonać akcję na każdym elemencie, podając numer indeksu (tutaj zmienna jest używana jako indeks jako „i”)
for(int i=1; i<=5; i++) { string xPathWithVariable = "(//div[@class='className'])" + "[" + i + "]"; driver.FindElement(By.XPath(xPathWithVariable)).Click(); }
Potrzeba XPath:
źródło