Как выбрать первые ячейки столбцов (tds) в веб-драйвере Selenium? - PullRequest
5 голосов
/ 30 ноября 2011

Я использую Selenium 2.12.Используя API WebDriver, допустим, у меня есть WebElement, который представляет таблицу (<table>).Используя этот элемент, как мне выбрать все тд в первом столбце?Я предполагаю, что выражение xpath здесь в порядке.

Чтобы лучше понять структуру таблицы, если я получу HTML из моего tableElement WebElement ...

String html = (String)((JavascriptExecutor)driver).executeScript("return arguments[0].innerHTML;", tableElt); 

Я получу беспорядокниже.Главное, на что нужно обратить внимание, это то, что есть 6 т.р. и 16 т.д. ...

<thead><tr><th colspan="1" class="GCSPOWVGE GCSPOWVEE GCSPOWVEF GCSPOWVFF"><div style="padding-left: 17px;position:relative;zoom:1;"><div style="left:0px;margin-top:-4px;position:absolute;top:50%;line-height:0px;"><img onload='this.__gwtLastUnhandledEvent="load";' src="http://localhost:9080/cme-productplus-web/productplus/clear.cache.gif" style="width: 11px; height: 7px; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAHCAYAAADebrddAAAAiklEQVR42mNgwALyKrumFRf3iDAQAvmVXVVAxf/zKjq341WYV95hk1fZ+R+MK8C4HqtCkLW5FZ2PQYpyK6AaKjv/5VV1OmIozq3s3AFR0AXFUNMrO5/lV7WKI6yv6mxCksSGDyTU13Mw5JV2qeaWd54FWn0BRAMlLgPZl/NAuBKMz+dWdF0H2hwCAPwcZIjfOFLHAAAAAElFTkSuQmCC) no-repeat 0px 0px;" border="0"></div><div>GUID</div></div></th><th colspan="1" class="GCSPOWVGE GCSPOWVEF">Fung Ratio</th><th colspan="1" class="GCSPOWVGE GCSPOWVEF">Fung type</th><th colspan="1" class="GCSPOWVGE GCSPOWVEF">Fung Date Offset</th><th colspan="1" class="GCSPOWVGE GCSPOWVEF  GCSPOWVOE">Days To Retain</th></tr></thead><colgroup><col><col><col><col><col></colgroup><tbody><tr onclick="" class="GCSPOWVAE"><td class="GCSPOWVPD GCSPOWVBE GCSPOWVCE"><div style="outline:none;" tabindex="0">      DSSUAQR6IE6E    </div></td><td class="GCSPOWVPD GCSPOWVBE"><div style="outline:none;">      10      </div></td><td class="GCSPOWVPD GCSPOWVBE"><div style="outline:none;">              </div></td><td class="GCSPOWVPD GCSPOWVBE"><div style="outline:none;">      </div></td><td class="GCSPOWVPD GCSPOWVBE GCSPOWVME"><div style="outline:none;">            </div></td></tr><tr onclick="" class="GCSPOWVAF"><td class="GCSPOWVPD GCSPOWVBF GCSPOWVCE"><div style="outline:none;">      ETTUAQR6IE6E    </div></td><td class="GCSPOWVPD GCSPOWVBF"><div style="outline:none;">      30      </div></td><td class="GCSPOWVPD GCSPOWVBF"><div style="outline:none;">              </div></td><td class="GCSPOWVPD GCSPOWVBF"><div style="outline:none;">      </div></td><td class="GCSPOWVPD GCSPOWVBF GCSPOWVME"><div style="outline:none;">            </div></td></tr><tr onclick="" class="GCSPOWVAE"><td class="GCSPOWVPD GCSPOWVBE GCSPOWVCE"><div style="outline:none;">      FCCUAQR6IE6E    </div></td><td class="GCSPOWVPD GCSPOWVBE"><div style="outline:none;">      20      </div></td><td class="GCSPOWVPD GCSPOWVBE"><div style="outline:none;">              </div></td><td class="GCSPOWVPD GCSPOWVBE"><div style="outline:none;">      </div></td><td class="GCSPOWVPD GCSPOWVBE GCSPOWVME"><div style="outline:none;">            </div></td></tr></tbody><tbody style="display: none;"><tr><td colspan="5" align="center"><div><div style="width: 100%; height: 100%; padding: 0px; margin: 0px; display: none;"><div style="width: 100%; height: 100%; display: none;"></div></div><div style="width: 100%; height: 100%; padding: 0px; margin: 0px; display: none;"><div class="GCSPOWVPE" style="width: 100%; height: 100%; display: none;"><img class="gwt-Image" onload='this.__gwtLastUnhandledEvent="load";' src="http://localhost:9080/cme-productplus-web/productplus/clear.cache.gif" style="width: 43px; height: 11px; background: url(data:image/gif;base64,R0lGODlhKwALAPEAAP///0tKSqampktKSiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAKwALAAACMoSOCMuW2diD88UKG95W88uF4DaGWFmhZid93pq+pwxnLUnXh8ou+sSz+T64oCAyTBUAACH5BAkKAAAALAAAAAArAAsAAAI9xI4IyyAPYWOxmoTHrHzzmGHe94xkmJifyqFKQ0pwLLgHa82xrekkDrIBZRQab1jyfY7KTtPimixiUsevAAAh+QQJCgAAACwAAAAAKwALAAACPYSOCMswD2FjqZpqW9xv4g8KE7d54XmMpNSgqLoOpgvC60xjNonnyc7p+VKamKw1zDCMR8rp8pksYlKorgAAIfkECQoAAAAsAAAAACsACwAAAkCEjgjLltnYmJS6Bxt+sfq5ZUyoNJ9HHlEqdCfFrqn7DrE2m7Wdj/2y45FkQ13t5itKdshFExC8YCLOEBX6AhQAADsAAAAAAAAAAAA=) no-repeat 0px 0px;" border="0"></div></div></div></td></tr></tbody><tfoot style="display: none;"><tr><th colspan="5" class="GCSPOWVFE GCSPOWVDE  GCSPOWVNE"></th></tr></tfoot>

К сожалению, оба эти выражения не дают правильных результатов.

        // This returns zero td's
        final List<WebElement> tds = tableElt.findElements(By.xpath("/tr/td[1]"));

        ...

        // This returns 238 td's (I think that's everything in my document)
        final List<WebElement> tds = tableElt.findElements(By.xpath("//td[1]"));

Ответы [ 4 ]

6 голосов
/ 01 декабря 2011
    // This returns 238 td's (I think that's everything in my document)               
    final List<WebElement> tds = tableElt.findElements(By.xpath("//td[1]"));

Это в точности соответствует спецификации XPath W3c и является одним из наиболее часто задаваемых вопросов в XPath.

Приоритет (приоритет) псевдооператора // меньше, чем у оператора [].

Следовательно, //SomeName[1] выбирает все элементы с именем SomeName, которые являются первым SomeName дочерним элементом своего родителя - и таких элементов может быть много.

Если вы хотите выбрать 1-й элемент SomeName в документе XML, вам необходимо явно переопределить приоритет оператора по умолчанию, используя скобки:

(//SomeName)[1]

В этом случае вам нужен только первый td потомок данного элемента - поэтому в дополнение к вышеуказанному исправлению вы должны исправить свое выражение, чтобы оно было относительно - не абсолютным. Абсолютное выражение XPath (начиная с / всегда оценивается как узел дополнительного контекста с узлом документа).

Используйте

(.//td)[1]

Если вам нужны все td потомков текущего узла, используйте:

.//td

И еще лучше:

.//descendant::td
4 голосов
/ 30 ноября 2011

Точное выражение зависит от фактической структуры вашего документа.

В самом общем случае - при выборе всех ячеек первого столбца из таблицы - вы можете использовать следующее выражение:

<path_to_table>//td[1]

Например, в этом документе:

<table>
    <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
    </tr>
    <tr>
        <td>a</td>
        <td>b</td>
        <td>c</td>
        <td>d</td>
    </tr>
    <tr>
        <td>i</td>
        <td>ii</td>
        <td>iii</td>
        <td>iv</td>
    </tr>
</table>

Это выражение:

/table//td[1]

Дает:

<td>1</td>
<td>a</td>
<td>i</td>

Обратите внимание, что я использую ось потомка или себя (//), поскольку в таблицах HTML допускаются необязательные элементы группировки (например, <tbody>), которые могут присутствовать или не присутствовать. Однако это будет включать и ячейки первого столбца из вложенных таблиц. Рассмотрим этот вход:

<table>
    <tr>
        <td>1</td>
        <td><table><td>test</td></table></td>
        <td>3</td>
        <td>4</td>
    </tr>
    <tr>
        <td>a</td>
        <td>b</td>
        <td>c</td>
        <td>d</td>
    </tr>
    <tr>
        <td>i</td>
        <td>ii</td>
        <td>iii</td>
        <td>iv</td>
    </tr>
</table>

То же выражение сверху возвращает:

<td>1</td>
<td>test</td>
<td>a</td>
<td>i</td>

Если вы знаете больше о вашей конкретной структуре таблицы, вы можете написать более конкретное выражение. Например, на предыдущем входе это выражение:

/table/tr/td[1]

... возвращает только ячейки из самой внешней таблицы:

<td>1</td>
<td>a</td>
<td>i</td>
1 голос
/ 30 ноября 2011

Если каждый tr содержит равное количество td, вы можете сформировать список всех td элементов, используя .findElements(By.tagName("td")), и перебрать каждый n-й элемент этого списка, где n равно числу td элементы в каждом tr

List<WebElement> allTDs = table.findElements(By.tagName("td"));
int n = table.findElements(By.tagName("tr")).size();

List<WebElement> yourTDs = new ArrayList<WebElement>();
for (int i = 0; i < allTDs.size(); i = i + n){
    yourTDs.add(allTDs.get(i));
}
0 голосов
/ 01 декабря 2011

если у вас уже есть таблица, хранящаяся как WebElement, тогда все, что вам нужно сделать, - это проанализировать WebElement так же, как и WebDriver.

//The first part is just a reference for others to see the table element being caught
WebElement TableElement = driver.findElement(By.tagName("table"));

Это создаст список элементов td (выследует использовать xpath, так как вы можете указать относительный xPath элемента и указать, какой конкретный элемент вы хотите, чтобы xPath был немного медленным, поэтому, если вы анализируете большую страницу, вы можете перейти с помощью CssSelector: first-типа

List<WebElement> FirstColumns = TableElement.findElements(By.xPath("//tr/td[1]"));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...