Когда мы ищем дочерний элемент в основном элементе, можно ли сочетать xpath и css?
driver.findElement(By.cssSelector("")).findElement(By.xpath()).click()
Когда мы ищем дочерний элемент в основном элементе, можно ли сочетать xpath и css?
driver.findElement(By.cssSelector("")).findElement(By.xpath()).click()
Можно
главное чтобы xpath в этом случае начинался с точки
driver.findElement(By.cssSelector("bla bla")).findElement(By.xpath(".//*")).click()
Не понимаю почему нельзя найти элемент с использованием ancestor
? пишу следующее
WebElement element = driver.findElement(By.cssSelector("[id='row.name']"));
String text = element.findElement(By.xpath(".//ancestor::section[@class='form-group nav-item']/h3/a")).getText()
text
начинает искать с самого начала DOM, а не относительно element
Искать элемент можно только ниже относительно элемента?
P.S. локатор проверил через браузер.
ancestor:: — Возвращает множество предков.
Множество с локатором section[@class='form-group nav-item']/h3/a
- это N элементов, судя по вашей верстке. Ввиду того, что вы используете findElement
, а не findElements
, на выходе получаете первый элемент из множества. Если выберете второй способ, увидите целую пачку нодов. Все логично.
Но я считал что будет выполняться поиск от конкретного элемента. Конечно когда я пишу:
//*[@id='row.name']/ancestor::section[@class='form-group nav-item']/h3/a
поиск выполняется относительно //*[@id='row.name']
В element.findElement
я также пытаюсь найти относительно этого же элемента. Вот в этом и вопрос, почему он не находит относительно заданного локатора?
Ну вообще как бы есть разница между //
и /
.
Если я напишу один слеш, вообще ничего не находит. На скриншоте пример выполнения этой регулярки в браузере:
Начнем с того, что такое @id='row.name'
и где оно на скрине?
Перепутал c row.descriptional, но не суть:
HTML:
<div id='main'>
<div id='first'>
<section>
<h3>
<a>first</a>
</h3>
</section>
</div>
<div id='second'>
<section>
<h3>
<a>second</a>
</h3>
</section>
</div>
<div id='third'>
<section>
<h3>
<a>third</a>
</h3>
<div id='target'></div>
</section>
</div>
</div>
Code:
WebDriver driver = new FirefoxDriver();
driver.get("http://jsfiddle.net/fcf0zvv1");
driver.switchTo().frame("result");
WebElement el1 = driver.findElement(By.cssSelector("[id='target']"));
WebElement el2 = el1.findElement(By.xpath(".//ancestor::section/h3/a"));
System.out.println(el2.getText());
driver.quit();
Output:
third
Такой способ я выше описал, он у меня не срабатывает. Игнорирует el1.
Ну я продемонстрировал, что ничего не игнорируется и данная конструкция вполне себе дееспособная.
Если у вас что-то “не срабатывает” - проблема на вашей стороне. Единственный действенный способ для вас - изолировать проблемное место и предоставить код, который бы мог запустить любой посетитель форума. Так как в таких случаях (“у всех работает, а у меня нет”) дебажить по скриншотам довольно затруднительно.
Понял. Спасибо
Хотел бы спросить вас по поводу точки. Почему локатор должен начинаться именно с точки? Дело в том что вы решили мне сейчас вопрос по вот этой теме. Обычно когда я ищу элемент в элементе, то не использовал точку и команды (click, isDisplayed…) выполнялись верно. Но когда я начал работу с Popup именно один из всех элементов не срабатывал из-за этой точки. Почему?
По спецификации.
http://www.w3.org/TR/xpath/
[quote]
// is short for /descendant-or-self::node()/. For example, //para is short for /descendant-or-self::node()/child::para and so will select any para element in the document (even a para element that is a document element will be selected by //para since the document element node is a child of the root node); div//para is short for div/descendant-or-self::node()/child::para and so will select all para descendants of div children.[/quote]
[quote]
A location step of . is short for self::node(). This is particularly useful in conjunction with //. For example, the location path .//para is short for self::node()/descendant-or-self::node()/child::para and so will select all para descendant elements of the context node.[/quote]
Я думал что в случае такого поиска элементов (//foo
) он будет продолжать поиск от существующего элемента. Походу точка или self::node()
говорит о том что поиск будет начинаться относительно предыдущего найденного элемента. Для примера продемонстрирую следующий скриншот:
На нем можно увидеть, что действительно в DOM находится 2 элемента. Поэтому когда я пытался искать элемент в элементе не используя точку, то локатор использовался относительно body а не последнего элемента:
public class Example{
...
public void testLocator(){
WebElement element = driver.findElement(By.xpath("//*[@additional-view][last()]//section[@name='row.__states.AvalabiltyOnVideoServers']"));
element.findElement(By.xpath("//td[normalize-space(.)='Московский']/input[@ng-model='row.__selected']")).click() // так как на странице 2 элемента с последним локатором, то найдет 2 элемента и выберет 1 который как видно на скриншоте находится за Popup. element учитываться не будет
element.findElement(By.xpath(".//td[normalize-space(.)='Московский']/input[@ng-model='row.__selected']")).click() // точка как я выше указал говорит нам что поиск локатора нужно начать относительно выше найденного элемента
}
...
}