【问题标题】:Selenium Webdriver - Fetching Table DataSelenium Webdriver - 获取表数据
【发布时间】:2012-05-24 16:47:00
【问题描述】:

我想从 UI 中的表中获取数据。我知道使用“tr”和“td”循环遍历行和列。但是我的桌子是这样的:

<table>
 <tbody>
  <tr><td>data</td><th>data</th><td>data</td><td>data</td></tr>
  <tr><td>data</td><th>data</th><td>data</td><td>data</td></tr>
  <tr><td>data</td><th>data</th><td>data</td><td>data</td></tr>
 </tbody>
</table>

如何使我的代码通用,以便可以处理中间出现“TH”的情况。 目前,我正在使用此代码:

// Grab the table
WebElement table = driver.findElement(By.id(searchResultsGrid));

// Now get all the TR elements from the table
List<WebElement> allRows = table.findElements(By.tagName("tr"));
// And iterate over them, getting the cells
for (WebElement row : allRows) {
 List<WebElement> cells = row.findElements(By.tagName("td"));
 for (WebElement cell : cells) {
 // And so on
 }
}

【问题讨论】:

    标签: uitableview selenium webdriver html-table


    【解决方案1】:

    你可以在不区分 td 和 th 的情况下查找 tr 元素的所有子元素。所以不是

    List<WebElement> cells = row.findElements(By.tagName("td"));
    

    我会用

    List<WebElement> cells = row.findElements(By.xpath("./*"));
    

    【讨论】:

    • 但这会给所有的孩子,包括链接 ,或里面的输入等
    • 并非如此。我的示例将仅返回一级子级。这意味着只有 tr 和 th 标签(参考示例)。 和 之间的元素(换句话说,您示例中的“数据”中的任何内容)将返回。
    • @Sky - 提供的 xpath 只会得到孩子,而不是后代。
    • @JacekM,如果一个人需要返回所有级别的孩子,而不仅仅是一级。对于上面的回复,肯定 +1。
    • @anujin 在这种情况下,您可以使用By.xpath(".//*") - 注意双斜杠而不是单斜杠。检查此线程以获取更多信息:stackoverflow.com/questions/14052368/…
    【解决方案2】:

    也许这个问题的所有者为时已晚,但对其他人有帮助。

    List<WebElement> cells = row.findElements(By.xpath(".//*[local-name(.)='th' or local-name(.)='td']"));
    

    【讨论】:

      【解决方案3】:
      // Grab the table
      WebElement table = driver.findElement(By.id("searchResultsGrid"));
      
      // Now get all the TR elements from the table
      List<WebElement> allRows = table.findElements(By.tagName("tr"));
      // And iterate over them, getting the cells
      for (WebElement row : allRows) {
          List<WebElement> cells = row.findElements(By.tagName("td"));
          for (WebElement cell : cells) {
              System.out.println("content >>   " + cell.getText());
          }
      }
      

      使用cell.getText() 就可以了

      【讨论】:

        【解决方案4】:

        您不需要遍历元素。相反,请使用 ByChained 定位器。

        如果你的桌子是这样的:

        <table>
          <tbody>
            <tr><th>Col1</th><th>Col2</th><th>Col3</th></tr>
            <tr><td>data</td><td>data</td><td>data</td></tr>
            <tr><td>data</td><td>data</td><td>data</td></tr>
            <tr><td>data</td><td>data</td><td>data</td></tr>
          </tbody>
        </table>
        

        定位如下:

        By tableBodyLocator = By.xpath(".//table/tbody");
        By headerRowLocator = By.xpath(".//tr[position()=1]");
        By dataRowsLocator = By.xpath(".//tr[not(position()=1)]");
        
        By headerRowLocator = new ByChained(tableBodyLocator, headerRowLocator);
        List<WebElement> weHeaders = driver.findElement(headerRowLocator)
               .findElements(By.xpath(".//th");
        List<WebElement> allRowData = driver.findElements(tableBodyLocator, dataRowsLocator);
        
        WebElement row1Data = allRowData.get(0);
        WebElement row2Data = allRowData.get(1);
        
        etc.
        

        【讨论】:

          【解决方案5】:

          是的,它适用于带有 selenium 的 c#...

          IList<IWebElement> cells = row.findElements(By.xpath(".//*[local-name(.)='th' or local-name(.)='td']"));
          

          【讨论】:

            【解决方案6】:
            IWebElement table = driver.FindElement(By.Id("id"));
            List<IWebElement> allRows = new List<IWebElement> (table.FindElements(By.TagName("tr")));
            
            foreach (var Row in allRows)
            {
                List<IWebElement> cells = new List<IWebElement>( Row.FindElements(By.TagName("td")));
                foreach (var cel in cells)
                {
                    string test = cel.Text;
                }
            }
            

            【讨论】:

              【解决方案7】:

              下面的代码不仅可以获取表格的行和列,还可以获取它们在浏览器中的顺序,如果你在 TD 列中有嵌套结构,这主要是方便的,就像你的案例。

               public DataTable StoreHtmlTableToDataTable(IWebElement tblObj,bool isFirstRowHeader = true)
                      {
                          DataTable dataTbl = new DataTable();
                          int rowIndex = 0;
              
                          try
                          {               
                              //_tblDataCollection = new List<TableDataCollection>();
              
                              var tblRows = ((IJavaScriptExecutor)DriverContext.Driver).ExecuteScript("return arguments[0].rows; ", tblObj);
              
                              if (tblRows != null)
                              {
                                  //Iterate through each row of the table
                                  foreach (IWebElement tr in (IEnumerable)tblRows)
                                  {                        
                                      int colIndx = 0;
                                      DataRow dtRow =  dataTbl.NewRow();
                                      // Iterate through each cell of the table row
                                      var tblCols = ((IJavaScriptExecutor)DriverContext.Driver).ExecuteScript("return arguments[0].cells; ", tr);
                                      foreach (IWebElement td in (IEnumerable)tblCols)
                                      {
                                          //add the header row of the table as  the datatable column hader row
                                          if (rowIndex == 0)
                                          {
                                              dataTbl.Columns.Add("Col" + colIndx.ToString(), typeof(string));
                                          }
              
                                          dtRow["Col"+colIndx.ToString()] = td.Text;
              
                                          //loop through any child or nested table structures if you want using the same approach for example links,radio buttons etc inside the cell
              
                                          //Write Table to List : This part is not done yet                           
                                          colIndx++;
                                      }
                                      dataTbl.Rows.Add(dtRow);
                                      rowIndex++;
                                  }
              
                              }
              
              
                          }
                          catch (Exception)
                          {
                              throw;
                          }
              
                          //if first row is the header row then assign it as a header of the datatable
                          if (isFirstRowHeader)
                          {
                              dataTbl = this.AssignDataTableHeader(dataTbl);
                          }
              
                          return dataTbl;
                      }
              

              【讨论】:

                【解决方案8】:

                TableDriver (https://github.com/jkindwall/TableDriver.Java) 支持带有 td 和 th 标签的单元格。将 TableDriver 与您的示例表一起使用将如下所示:

                Table table = Table.createWithNoHeaders(driver.findElement(By.id(searchResultsGrid), 0);
                List<TableRow> allRows = table.getRows();
                for (TableRow row : allRows) {
                    List<TableCell> cells = row.getCells();
                    for (TableCell cell : cells) {
                        // Access the cell's WebElement like this: cell.getElement()
                    }
                }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-10-19
                  • 1970-01-01
                  • 2018-05-23
                  • 2013-07-17
                  • 1970-01-01
                  • 2020-07-11
                  • 2021-05-14
                  相关资源
                  最近更新 更多