Java selenium xpath - получение всех элементов под конкретный элемент

1

это упрощенная структура HTML, которую я просматриваю:

<div class="main">
...other stuff...
       <td class="child">44</td>
       <td class="child">59</td>
       <td class="child">11</td>
</div>
<div class="main">
...other stuff...
       <td class="child">5</td>
       <td class="child">14</td>
       <td class="child">98</td>
</div>
...this kind of structure repeats with similar numbers a few more times but with identical class names

Мне нужно извлечь все числа под первым найденным основным классом, поэтому я сделал запрос для поиска первого основного и всего td с определенным классом под ним. Может кто-нибудь дать мне подсказку, что я делаю неправильно, так как этот запрос дает мне все числа из всех td с классом "child" во всех "главных" div's:

List<WebElement> koefi = driver.findElements(By.xpath("//div[@class='main'][1]//td[@class='child']"));

Что я делаю неправильно или моя логика правильная, но я пропускаю некоторые другие части html, которые я не вставлял здесь, так как структура слишком громоздка..?

Спасибо!!

ps: Я тоже это пробовал, но опять же, я получаю содержимое всех td с "дочерним" классом, а не только с первого "основного".

List<WebElement> koefi = driver.findElements(By.xpath("//*[1][@class='main']//td[@class='child']"));

UPDATE: мне удалось решить мою проблему, сначала получив первое появление "основного" div, которое по умолчанию найдено функцией.findElement:

WebElement element = driver.findElement(By.xpath("//*[1][@id='main']"));

И затем извлечение с помощью.findElements функции "дочерних" классов:

List<WebElement> kk = element.findElements(By.className("child"));

Я все еще не могу понять, почему не работает.findElements с моим xpath или работает слишком хорошо, он извлекает каждый "основной" класс, а не только первый. И оригинальный HTML слишком большой, чтобы вставить сюда, поэтому я не хочу беспокоить вас, ребята!

  • 1
    Вы получаете какую-либо ошибку? Можете ли вы попробовать: java.util.List <WebElement> koefi = driver.findElements (By.xpath ("// div [@class='main'][1]//td[@ class = 'main'] [1] // td [@class='main'][1]//td[@ class = 'child']" ));
  • 2
    Вы уверены, что все <div class="main"> являются братьями и сестрами?
Показать ещё 19 комментариев
Теги:
xpath
selenium

2 ответа

1
Лучший ответ

Более чистое решение состояло бы в том, чтобы сначала захватить все div с main div, например:

List<WebElement> allDivs = driver.findElements(By.className("main"));

Затем, как вы указали, найдите все td с child td класса, например:

List<WebElement> tds = allDivs[0].findElements(By.className("child"));

После этого это всего лишь вопрос повторения всех "tds" и чтения ваших ценностей.

  • 0
    это отличный подход, спасибо за идею. Я сделал это подобным образом, я получил первый «main» с помощью .findelement (), и они получили все «дочерние» td с .findelements (). но большое спасибо за идею !!
0

Вы скажете в комментарии, что

"главные" не являются прямыми братьями и сестрами

поэтому я подозреваю, что вы ошибаетесь в общей ошибке, связанной с определением // в XPath. Путь

//div[@class='main'][1]

не выбирает первый "основной" div в документе. Причиной этого является то, что // является сокращением для /descendant-or-self::node()/ (включая начальную и конечную косые черты), поэтому этот путь на самом деле означает

/descendant-or-self::node()/child::div[@class='main'][1]

Когда вы видите его полностью расширенным, вы понимаете, что [1] относится к child:: step, а не к поиску потомков, то есть вы получите все элементы div в документе, которые имеют класс "main", и являются первыми div-with-class-main под соответствующими родительскими элементами. Если ваш фактический HTML

<div>
  <div class="main">...</div>
</div>
<div>
  <div class="main">...</div>
</div>

то XPath выберет оба из них (они оба являются первыми под родителями). Если вы просто хотите получить первую в документе, тогда вы должны использовать ось descendant::

/descendant::div[@class='main'][1]

который даст вам только первый совпадающий потомок.

  • 0
    не должно ли это: // * [1] [@ class = 'main'] // td [@ class = 'child'] также дать мне первое вхождение "main"?
  • 0
    Предикаты @ Hrvoje85 применяются слева направо - //*[1][@class='main'] означает каждый элемент в документе, который является первым дочерним элементом его родителя и имеет класс main, в отличие от //*[@class='main'][1] который будет каждым элементом, который является первым элементом-с-class-main в его родителе.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню