2012-05-17 2 views
12

Desidero recuperare i dati dalle tabelle nell'interfaccia utente. Conosco il looping su righe e colonne usando "tr" e "td". Ma quella che il tavolo che ho è qualcosa di simile:Selenium Webdriver - Dati della tabella di recupero

<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> 

Come posso fare il mio codice generico, in modo che la presenza di "TH" in mezzo può essere gestito. Attualmente, sto usando questo codice:

// 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 
} 
} 

risposta

14

Si potrebbe guardare per tutti i bambini di tr elemento, senza distinguere tra TD e TH. Così, invece di

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

userei

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

Ma questo darà a tutti i bambini compresi i collegamenti , o di ingresso ecc all'interno – Sky

+0

non proprio. Il mio esempio restituirebbe solo i bambini di primo livello. Questo significa solo tag tr e th (riferendosi all'esempio). Gli elementi tra e (in altre parole qualsiasi cosa proveniente dai "dati" dell'esempio) non saranno ** resi **. – JacekM

+0

@Sky - L'xpath fornito otterrà solo figli, non discendenti. –

8

Mayby è troppo tardi per il proprietario di questa domanda, ma utile per gli altri.

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

sì, sta lavorando per C# con il selenio ...

IList<IWebElement> 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()); 
    } 
} 

utilizzando cell.getText() sarebbe semplicemente lavorare

0
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; 
    } 
} 
+0

funziona in C# –

2

Non è necessario per eseguire il ciclo elementi. Invece, utilizzare un localizzatore ByChained.

Se tabella simile alla seguente:

<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> 

La individuare in questo modo:

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. 
0

Il codice qui sotto è possibile non solo ottenere le righe e le colonne della tabella, ma anche si può ottenere l'ordine in cui si trovano nel browser, è utile soprattutto se nella colonna TD sono presenti strutture nidificate come nel tuo caso.

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; 
     }