How To Work With Tables In Selenium PHP?
Tags: php, selenium, testing
Published: 2021-02-01 10:30:22

Web tables or data tables are a common sight in many web-based applications. And these tables are predominantly used for displaying information in a tabular format. Rows and columns are the key identifiers of web tables in Selenium. If you’re using tables in Selenium PHP, you can perform several operations on the table, e.g., fetching data from a specific row-column combination, searching for a particular key string in the table, etc. Selenium web automation should be used for automating the operations on the web tables.

![](https://www.lambdatest.com/blog/wp-content/uploads/2020/12/image4.gif)

A simple yet effective usage of web tables can be seen in e-commerce websites where detailed product information is displayed in a tabular format since it offers better readability. The information in the table can either be static or dynamically populated through some scripts.

In this Selenium WebDriver PHP Tutorial, we deep dive into the usage of web tables in Selenium PHP and how Selenium web automation can be used for automating various operations on web tables.

 
## What Are Web Tables In Selenium?

Web Table is a type of web element primarily used for displaying information in a tabular format. Popular web elements like radio boxes, drop-down menus, checkboxes, etc., have data available in each cell of the web table that can be accessed using the WebElement functions.

As web tables in Selenium PHP comprise rows and columns, the WebElement functions are used along with the locators that identify the corresponding row (and/or column) on which Selenium test automation operation has to be performed.

Shown below is a web table with (8\*3) configuration, i.e., number of rows = 8 and number of columns = 3.

![jenins vs gitlabcicd](https://www.lambdatest.com/blog/wp-content/uploads/2020/12/jenins-vs-gitlabcicd.png)

Here are some of the important HTML tags that are used in the construction of tables in Selenium PHP:

| HTML Tag | Description |
| --- | --- |
| `Table` | Defines a _Table_ in HTML |
| `th` | Contains the information related to the _Header_ in the table |
| `tr` | Defines a _Row_ in the table |
| `td` | Defines a _Column_ in the table |

As seen below, the content inside the `th` tag defines the Header. Hence, the headers in the table are FEATURE, JENKINS, and GITLAB CI/CD.

![](https://www.lambdatest.com/blog/wp-content/uploads/2020/12/image8-3.png)

Here is an example usage of where we have highlighted the contents of:

**First row**? R-1, C-0: Open-Source or Commercial, R-1, C-1: Open Source, and R-1, C-2: Open Source.

**Second row**?R-2, C-0: Product Type, R-2, C-1: Self-hosted/On-Premise, and R-2, C-2: Self-hosted/On-Premise.

Here is a sample usage of `td` where we have highlighted the contents of Row 1 and Column 1, i.e., R – 1, C – 1 ? Open-Source or Commercial

![](https://www.lambdatest.com/blog/wp-content/uploads/2020/12/unnamed-11.png)

The content of Row 2 and Column 1, i.e., R – 2, C – 0 ? Product Type.

![LambdaTest inspect](https://www.lambdatest.com/blog/wp-content/uploads/2020/12/LambdaTest-inpect.png)

## Handling Web Tables In Selenium PHP
 

There are two broad categories of web tables in Selenium – Static Table and Dynamic Table. **Static Web Table** is where the data (or information) in the table is static (i.e., it is not fetched dynamically via queries or other mechanisms). We showcased an example of a Static Web Table in the previous section.

On the other hand, the content in a **Dynamic Web Table** is not fixed. For example, when buying a laptop on an e-commerce website, the table’s contents (that shows the configuration) will change depending on the user’s configuration ‘customized.’

For demonstrating the handling of web tables in Selenium PHP, we would be using these [web tables](https://www.w3schools.com/html/html_tables.asp). You might face cross browser issues when dealing with web tables, particularly with the browser versions where there is no support for handling HTML Table APIs.

![](https://www.lambdatest.com/blog/wp-content/uploads/2020/12/1111.png)

In the upcoming sections of this Selenium WebDriver PHP tutorial, we look at some of the widely used operations on web tables in Selenium PHP. The HTML code of the web table used for demonstration is available [here](https://www.w3schools.com/html/tryit.asp?filename=tryhtml_table_intro).

![](https://www.lambdatest.com/blog/wp-content/uploads/2020/12/image2-3.png)

We would be using the PHPUnit framework for executing the tests. The necessary packages (or dependencies) have to be downloaded before we move ahead with the implementation. For downloading the dependencies, we create `composer.json` in the project root folder.

```
{
   "require":{
      "php":"&gt;=7.1",
      "phpunit/phpunit":"^9",
      "phpunit/phpunit-selenium": "*",
      "php-webdriver/webdriver":"1.8.0",
      "symfony/symfony":"4.4",
      "brianium/paratest": "dev-master"
   }
}
```

Run the following command on the terminal to download the dependencies.

```
composer require
```

Press the ‘Enter’ button twice to proceed with the installation of the downloaded packages.

![](https://www.lambdatest.com/blog/wp-content/uploads/2020/12/image11-2.png)

After the download and installation process, the PHPUnit framework will be present in the vendor\bin folder. With the completion of the basic setup, we proceed with the demonstration of handling web tables in Selenium PHP.

The tests are executed on LambdaTest’s cloud-based Selenium Grid. These [web tables](https://www.w3schools.com/html/html_tables.asp) will be used for all the demonstrations.

### How To Compute The Number Of Rows and Columns In A Web Table?
 

The `tr` tag in HTML indicates rows and `td` tag indicates columns in a web table. The row tag i.e. `tr` is used for getting information about the number of rows in the table.

We used the POM Builder extension in Chrome instead of the Inspect tool for getting information about the required web element (i.e., R-1, C- 1). Hence, the XPath [//\*[@id=’customers’]/tbody/tr[2]/td] is used for calculating the number of columns in the table.

![](https://www.lambdatest.com/blog/wp-content/uploads/2020/12/image9-1.png)

The `th` tag can be used for calculating the number of columns in the table. The XPath //\*[@id=’customers’]/tbody/tr/th is used for computing the number of columns in the table.

Alternatively, the XPath //table//th can also be used for computing the columns since all column headings are marked with the `th` tag.

**Implementation**

```php
<?php
require 'vendor/autoload.php';
 
use PHPUnit\Framework\TestCase;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\WebDriverBy;
 
$GLOBALS['LT_USERNAME'] = "user-name";
$GLOBALS['LT_APPKEY'] = "access-key";
 
class WebTable_Get_Rows_ColsTest extends TestCase
{
  protected $webDriver;
 
  public function build_browser_capabilities(){
    /* $capabilities = DesiredCapabilities::chrome(); */
    $capabilities = array(
      "build" => "[PHP-1] Counting number of rows and columns in WebTable",
      "name" => "[PHP-1] Counting number of rows and columns in WebTable",
      "platform" => "Windows 10",
      "browserName" => "Chrome",
      "version" => "85.0"
    );
    return $capabilities;
  }
  
  public function setUp(): void
  {
    $url = "https://". $GLOBALS['LT_USERNAME'] .":" . $GLOBALS['LT_APPKEY'] ."@hub.lambdatest.com/wd/hub";
    $capabilities = $this->build_browser_capabilities();
    /* $this->webDriver = RemoteWebDriver::create('http://localhost:4444/wd/hub', $capabilities); */
    $this->webDriver = RemoteWebDriver::create($url, $capabilities);
  }
 
  public function tearDown(): void
  {
    $this->webDriver->quit();
  }
  /*
  * @test
  */ 
  public function test_SwitchToNewWindow()
  {
    $test_url = "https://www.w3schools.com/html/html_tables.asp";
    $title = "HTML Tables";
 
    $this->webDriver->get($test_url);
    $this->webDriver->manage()->window()->maximize();
    sleep(5);
  
    $driver = $this->webDriver;
    $this->webDriver->wait()->until(
      function () use ($driver) {
      $elements = $this->webDriver->findElements(WebDriverBy::className('w3-example'));
          return count($elements) > 0;
      },
      'Error locating W3 example element'
    );
 
    $num_rows = count ($this->webDriver->findElements(WebDriverBy::xpath("//*[@id='customers']/tbody/tr")));
    echo ("\nRows in table are " . $num_rows);
    
    $num_cols = count ($this->webDriver->findElements(WebDriverBy::xpath("//*[@id='customers']/tbody/tr[2]/td")));
    print("\nColumns in table are " . $num_cols);
    
    $this->assertEquals($title, $this->webDriver->getTitle());
  }
}
?>
```

**Code WalkThrough**

**Lines (4 – 7)**: Import (or use) all the necessary classes (or packages) whose methods would be used in the code.

```
use PHPUnit\Framework\TestCase;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\WebDriverBy;
```

**Lines (9 – 11)**: Two global variables are used to store user-name and access-key. Username and access key are available in your profile section on LambdaTest.

 
```
$GLOBALS['LT_USERNAME'] = "user-name";
# accessKey:  AccessKey can be generated from automation dashboard or profile section
$GLOBALS['LT_APPKEY'] = "access-key";
```

**Lines (17 – 27)**: The browser capabilities array that was generated using the LambdaTest capabilities generator is used for testing.

```
public function build_browser_capabilities(){
    /* $capabilities = DesiredCapabilities::chrome(); */
    $capabilities = array(
      "build" =&gt; "[PHP-1] Counting number of rows and columns in WebTable",
      "name" =&gt; "[PHP-1] Counting number of rows and columns in WebTable",
      "platform" =&gt; "Windows 10",
      "browserName" =&gt; "Chrome",
      "version" =&gt; "85.0"
    );
    return $capabilities;
  }
```

**Line (34)**: The create method of the RemoteWebDriver class takes two parameters – LambdaTest Grid URL, i.e. [@hub.lambdatest.com/wd/hub] and browser capabilities.

```
$this-&gt;webDriver = RemoteWebDriver::create($url, $capabilities);
```

**Lines (53 – 60)**: An explicit wait is triggered for ensuring the loading of the web table with CLASS\_NAME = w3-example. The default wait duration is 30 seconds, post which [Selenium framework](https://www.lambdatest.com/selenium?utm_source=dev&utm_medium=Blog&utm_campaign=Himanshu-1022021&utm_term=Himanshu) raises an ElementNotVisibleException exception.

If the element is loaded within the designated time-frame, the count operation will return a non-zero value.

 
```
$driver = $this-&gt;webDriver;
$this-&gt;webDriver-&gt;wait()-&gt;until(
function () use ($driver) {
      $elements = $this-&gt;webDriver-&gt;findElements(WebDriverBy::className('w3-example'));
          return count($elements) &gt; 0;
},
'Error locating W3 example element'
);
```
 

**Lines (62 – 63)**: The XPath [//\*[@id=’customers’]/tbody/tr] is used to get details about the number of rows in the table. Instead of the XPath used in the code, the XPath [//table//tr] can also be used to get all tr elements in the table.

```
$num_rows = count ($this-&gt;webDriver-&gt;findElements(WebDriverBy::xpath("//*[@id='customers']/tbody/tr")));
echo ("\nRows in table are " . $num_rows);
```

**Lines (65 – 66)**: The XPath [//\*[@id=’customers’]/tbody/tr[2]/td] is used to get details about the number of columns in the table. Alternatively, the //table//th XPATH can also be used to get the number of columns.

```
$num_cols = count ($this-&gt;webDriver-&gt;findElements(WebDriverBy::xpath("//*[@id='customers']/tbody/tr[2]/td")));
echo("\nColumns in table are " . $num_cols);
```

**Execution**

For counting the number of rows and columns in Selenium PHP, run the following command on the terminal:

```
vendor\bin\phpunit WebTable_Get_Rows_ColsTest.php
```

Here is the execution snapshot which outputs the number of rows (i.e., 7) and columns (i.e., 3) present in the [table:](https://www.w3schools.com/html/html_tables.asp)

![](https://www.lambdatest.com/blog/wp-content/uploads/2020/12/image3.png)

### How To Print The Content Of Web Tables In Selenium PHP?
 

We iterate through the rows (i.e., `tr`) in the table for accessing the contents in each row and column of the web table. Post this, the tags under the corresponding row (`tr`) are also iterated.

Since the number of rows and columns are dynamic, they are computed dynamically. The following XPaths are used for accessing the data available in specific (row + column) combination:

- XPath for accessing R:2, C:1 – //\*[@id=”customers”]/tbody/tr[2]/td[1]
- XPath for accessing R:3, C:2 – //\*[@id=”customers”]/tbody/tr[3]/td[1]

**Implementation**

```php
<?php
require 'vendor/autoload.php';
 
use PHPUnit\Framework\TestCase;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\WebDriverBy;
 
$GLOBALS['LT_USERNAME'] = "user-name";
$GLOBALS['LT_APPKEY'] = "access-key";
 
class WebTable_Print_Rows_ColsTest extends TestCase
{
  protected $webDriver;
 
  public function build_browser_capabilities(){
    /* $capabilities = DesiredCapabilities::chrome(); */
    $capabilities = array(
      "build" => "[PHP-2] Print the data available in rows and columns",
      "name" => "[PHP-2] Print the data available in rows and columns",
      "platform" => "Windows 10",
      "browserName" => "Chrome",
      "version" => "85.0"
    );
    return $capabilities;
  }
  
  public function setUp(): void
  {
    $url = "https://". $GLOBALS['LT_USERNAME'] .":" . $GLOBALS['LT_APPKEY'] ."@hub.lambdatest.com/wd/hub";
    $capabilities = $this->build_browser_capabilities();
    $this->webDriver = RemoteWebDriver::create($url, $capabilities);
  }
 
  public function tearDown(): void
  {
    $this->webDriver->quit();
  }
  /*
  * @test
  */ 
  public function test_SwitchToNewWindow()
  {
    $test_url = "https://www.w3schools.com/html/html_tables.asp";
    $title = "HTML Tables";
    $before_XPath = "//*[@id='customers']/tbody/tr[";
    $aftertd_XPath = "]/td[";
    $aftertr_XPath = "]";
 
    $this->webDriver->get($test_url);
    $this->webDriver->manage()->window()->maximize();
    sleep(5);
    
    $driver = $this->webDriver;
    $this->webDriver->wait()->until(
    function () use ($driver) {
        $elements = $this->webDriver->findElements(WebDriverBy::className('w3-example'));
        return count($elements) > 0;
    },
    'Error locating W3 example element'
    );
 
    $rows = count ($this->webDriver->findElements(WebDriverBy::xpath("//*[@id='customers']/tbody/tr")));
    echo ("\nRows in table are " . $rows);
    
    $columns = count ($this->webDriver->findElements(WebDriverBy::xpath("//*[@id='customers']/tbody/tr[2]/td")));
    echo("\nColumns in table are " . $columns);
    echo("\n");
    echo("\n");
 
    for($t_row = 2; $t_row <= $rows; $t_row++)
    {
        for($t_column = 1; $t_column <= $columns; $t_column++)
        {
            $FinalXPath = $before_XPath .$t_row. $aftertd_XPath .$t_column. $aftertr_XPath;
            $cell = $this->webDriver->findElement(WebDriverBy::xpath($FinalXPath));
            $cell_text = $cell->getText();
            echo($cell_text);
            echo("\n");
        }
        echo("\n");
    }
    $this->assertEquals($title, $this->webDriver->getTitle());
  }
}
?>
```

**Code WalkThrough**

Most of the implementation is the same as the one used in the previous example.

The test method `test_SwitchToNewWindow` contains the implementation for printing the data available in each cell of the table.

**Lines (46 – 48)**: The XPath for accessing a specific row and column has two variables (i.e., row number and column number).

The XPath (//\*[@id=”customers”]/tbody/tr[row-number]/td[column-number]) is subdivided into multiple strings to accommodate static (i.e. unchanged) and dynamic (i.e. combination of row and column) properties in the XPath.

```
$before_XPath = "//*[@id='customers']/tbody/tr[";
$aftertd_XPath = "]/td[";
$aftertr_XPath = "]";
```

**Lines (71 – 83)**: The sample table has 7 rows and 3 columns. Hence, a nested for loop is executed with rows ranging from 2..7 and columns ranging from 1..3

The final XPath used for fetching the data available in a specific cell (i.e., a combination of row and column) is created using a combination of fixed Path and variable factors like row & column whose data has to be read.

```
for($t_row = 2; $t_row &lt;= $rows; $t_row++)
{
  for($t_column = 1; $t_column &lt;= $columns; $t_column++) { $FinalXPath = $before_XPath .$t_row. $aftertd_XPath .$t_column. $aftertr_XPath; $cell = $this-&gt;webDriver-&gt;findElement(WebDriverBy::xpath($FinalXPath));
    $cell_text = $cell-&gt;getText();
    echo($cell_text);
    echo(" ");
  }
  echo("\n");
}
```

The XPath for reading data in any cell is formed using the following combination:

```
"//*[@id='customers']/tbody/tr[" .$t_row. "]/td[" .$t_column. "]"
```

This is how the XPaths for different cells are generated:

- XPath for (2 , 1) ? //\*[@id=”customers”]/tbody/tr[2]/td[1]
- XPath for (2, 3) ? //\*[@id=”customers”]/tbody/tr[2]/td[3]
- XPath for (7 , 2) ? //\*[@id=”customers”]/tbody/tr[7]/td[2] and so on…

We start the reading from the 2nd row since the first row contains the title and is skipped from the read operation.

**Execution**

As seen in the execution snapshot, the data in every cell is read and printed on the terminal:

![](https://www.lambdatest.com/blog/wp-content/uploads/2020/12/image10-2.png)

### How To Read Data From Rows Of Web Tables In Selenium PHP?

In this section of the Selenium WebDriver PHP Tutorial, we demonstrate how to read the data row-wise from web tables. As we are reading row-wise, rows () would be variable, whereas columns () would remain constant.

Here are the sample XPaths for accessing the information available in (R2, C1), (R2, C2), and (R2, C3).

- XPath for accessing R:2, C:1 – //\*[@id=”customers”]/tbody/tr[2]/td[1]
- XPath for accessing R:2, C:2 – //\*[@id=”customers”]/tbody/tr[2]/td[2]
- XPath for accessing R:3, C:2 – //\*[@id=”customers”]/tbody/tr[3]/td[2]

Since the first row is the title, we start reading from row – 2. A for loop is executed with values ranging from 2..7, with 7 signifying the number of rows in the table. The corresponding column numbers are added to the row numbers to form a row-column (RC) combination.

Here is the XPath that is used for reading data from a particular row:

```
"//*[@id='customers']/tbody/tr[" .$t_row. "]/td[column_number]"
```

For reading the complete data from Row-2, $t\_row will be 2, and the column\_number will vary from 1..3. Here are the XPaths for reading data from Row-2:

| Row and Column number | XPath |
| --- | --- |
| R – 2, C – 1 | //\*[@id=’customers’]/tbody/tr[2]/td[1] |
| R – 2, C – 2 | //\*[@id=’customers’]/tbody/tr[2]/td[2] |
| R – 2, C – 3 | //\*[@id=’customers’]/tbody/tr[2]/td[3] |

**Implementation**

```php
<?php
require 'vendor/autoload.php';
 
use PHPUnit\Framework\TestCase;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\WebDriverBy;
 
$GLOBALS['LT_USERNAME'] = "user-name";
$GLOBALS['LT_APPKEY'] = "access-key";
 
class WebTable_Get_Rows_DataTest extends TestCase
{
  protected $webDriver;
 
  public function build_browser_capabilities(){
    /* $capabilities = DesiredCapabilities::chrome(); */
    $capabilities = array(
      "build" => "[PHP-3] Read data in the rows of a web table",
      "name" => "[PHP-3] Read data in the rows of a web table",
      "platform" => "Windows 10",
      "browserName" => "Chrome",
      "version" => "85.0"
    );
    return $capabilities;
  }
  
  public function setUp(): void
  {
    $url = "https://". $GLOBALS['LT_USERNAME'] .":" . $GLOBALS['LT_APPKEY'] ."@hub.lambdatest.com/wd/hub";
    $capabilities = $this->build_browser_capabilities();
    $this->webDriver = RemoteWebDriver::create($url, $capabilities);
  }
 
  public function tearDown(): void
  {
    $this->webDriver->quit();
  }
  /*
  * @test
  */ 
  public function test_SwitchToNewWindow()
  {
    $test_url = "https://www.w3schools.com/html/html_tables.asp";
    $title = "HTML Tables";
    $before_XPath = "//*[@id='customers']/tbody/tr[";
    $aftertd_XPath_1 = "]/td[1]";
    $aftertd_XPath_2 = "]/td[2]";
    $aftertd_XPath_3 = "]/td[3]";
 
    $this->webDriver->get($test_url);
    $this->webDriver->manage()->window()->maximize();
    sleep(5);
    
    $driver = $this->webDriver;
    $this->webDriver->wait()->until(
    function () use ($driver) {
        $elements = $this->webDriver->findElements(WebDriverBy::className('w3-example'));
        return count($elements) > 0;
    },
    'Error locating W3 example element'
    );
 
    $rows = count ($this->webDriver->findElements(WebDriverBy::xpath("//*[@id='customers']/tbody/tr")));
    echo ("\nRows in table are " . $rows);
    echo("\n");
    
    $cols = count ($this->webDriver->findElements(WebDriverBy::xpath("//*[@id='customers']/tbody/tr[2]/td")));
    print("\nColumns in table are " . $cols);
    echo("\n\n");
    
    $this->assertEquals($title, $this->webDriver->getTitle());
    
    echo("Data present in Rows, Col - 1\n");
    echo("-----------------------------\n");
    echo("\n");
    
    for($t_row = 2; $t_row <= ($rows); $t_row++)
    {
        $FinalXPath = $before_XPath .$t_row. $aftertd_XPath_1;
        $cell = $this->webDriver->findElement(WebDriverBy::xpath($FinalXPath));
        $cell_text = $cell->getText();
        echo($cell_text);
        echo("\n");
    }
    echo("\n\n");
    echo("Data present in Rows, Col - 2\n");
    echo("-----------------------------\n");
    echo("\n");
    
    for($t_row = 2; $t_row <= ($rows); $t_row++)
    {
       $FinalXPath = $before_XPath .$t_row. $aftertd_XPath_2;
        $cell = $this->webDriver->findElement(WebDriverBy::xpath($FinalXPath));
        $cell_text = $cell->getText();
        echo($cell_text);
        echo("\n");
    }
    
    echo("\n\n");
    echo("Data present in Rows, Col - 3\n");
    echo("-----------------------------\n");
    echo("\n");
    
    for($t_row = 2; $t_row <= ($rows); $t_row++)
    {
        $FinalXPath = $before_XPath .$t_row. $aftertd_XPath_3;
        $cell = $this->webDriver->findElement(WebDriverBy::xpath($FinalXPath));
        $cell_text = $cell->getText();
        echo($cell_text);
        echo("\n");
    }
    echo("\n\n");
    echo("Fetched all the records from the table\n");   
  }
}
?>
```

**Code WalkThrough**

**Lines (47 – 50)**: $before\_XPath holds the static part of the XPath. As mentioned earlier, the $before\_XPath will be appended with the Row number (which in our case ranges from 2..7).

The newly formed string will be appended to the XPath of the corresponding column number (i.e. “]/td[1]” for Column-1, “]/td[2]” for Column-2, and so on).

 
```
$before_XPath = "//*[@id='customers']/tbody/tr[";
$aftertd_XPath_1 = "]/td[1]";
$aftertd_XPath_2 = "]/td[2]";
$aftertd_XPath_3 = "]/td[3]";
```

**Lines (79 – 86)**: Here is the implementation for printing values available in rows (2..7) and column (1), i.e. (R-2, C-1), (R-3, C-1), (R-3, C-1) and so on…

In the code shown below, XPath for the column – 1 (i.e., td[1]) is appended to the computed XPath.

```
for($t_row = 2; $t_row &lt;= ($rows); $t_row++) { $FinalXPath = $before_XPath .$t_row. $aftertd_XPath_1; $cell = $this-&gt;webDriver-&gt;findElement(WebDriverBy::xpath($FinalXPath));
    $cell_text = $cell-&gt;getText();
    echo($cell_text);
    echo("\n");
}
```

The for loop will be executed with rows ranging from 2..7. The corresponding column values (td[1]/td[2]/td[3]) are appended depending on the column that has to be accessed.

**Execution**

As seen in the execution snapshot, a ‘row-wise’ read is performed on every cell in the table.

![](https://www.lambdatest.com/blog/wp-content/uploads/2020/12/image12-1.png)

### How to read data from Columns of web tables in Selenium PHP?

In the previous section, we performed a ‘row-wise’ read of the web table. In this section of the Selenium WebDriver PHP Tutorial, we would perform a ‘column-wise’ read operation. For column-wise read, rows would remain constant, whereas the column number is the variable factor (i.e., column number is computed dynamically).

Here are the XPaths used for accessing the information with ‘constant’ rows and ‘variable’ columns:

- XPath for accessing R:2, C:2 – //\*[@id=”customers”]/tbody/tr[2]/td[2]
- XPath for accessing R:2, C:3 – //\*[@id=”customers”]/tbody/tr[2]/td[3]
- XPath for accessing R:2, C:4 – //\*[@id=”customers”]/tbody/tr[2]/td[4]

Shown below is the sample XPath used for reading data from Row-2 and all the columns [i.e. (2,1), (2,2), (2,3)… (2,7)].

```
"//*[@id='customers']/tbody/tr[2]/th[".$t_column. "]"
```

For reading the complete data from Column-1, $t\_column will be 1, and the row\_number will vary from 1..3. Here are the XPaths for reading data from Row-2:

| Row and Column number | XPath |
| --- | --- |
| R – 2, C – 1 | //\*[@id=’customers’]/tbody/tr[2]/td[1] |
| R – 3, C – 1 | //\*[@id=’customers’]/tbody/tr[3]/td[1] |
| R – 4, C – 1 | //\*[@id=’customers’]/tbody/tr[4]/td[1] |

**Implementation**

```php
<?php
require 'vendor/autoload.php';
 
use PHPUnit\Framework\TestCase;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\WebDriverBy;
 
$GLOBALS['LT_USERNAME'] = "user-name";
$GLOBALS['LT_APPKEY'] = "access-key";
 
class WebTable_Get_Cols_DataTest extends TestCase
{
  protected $webDriver;
 
  public function build_browser_capabilities(){
    /* $capabilities = DesiredCapabilities::chrome(); */
    $capabilities = array(
      "build" => "[PHP-4] Read data in the columns of a web table",
      "name" => "[PHP-4] Read data in the columns of a web table",
      "platform" => "Windows 10",
      "browserName" => "Chrome",
      "version" => "85.0"
    );
    return $capabilities;
  }
  
  public function setUp(): void
  {
    $url = "https://". $GLOBALS['LT_USERNAME'] .":" . $GLOBALS['LT_APPKEY'] ."@hub.lambdatest.com/wd/hub";
    $capabilities = $this->build_browser_capabilities();
    /* $this->webDriver = RemoteWebDriver::create('http://localhost:4444/wd/hub', $capabilities); */
    $this->webDriver = RemoteWebDriver::create($url, $capabilities);
  }
 
  public function tearDown(): void
  {
    $this->webDriver->quit();
  }
  /*
  * @test
  */ 
  public function test_SwitchToNewWindow()
  {
    $test_url = "https://www.w3schools.com/html/html_tables.asp";
    $title = "HTML Tables";
    $before_XPath_1 = "//*[@id='customers']/tbody/tr[1]/th[";
    $before_XPath_2 = "//*[@id='customers']/tbody/tr[2]/td[";
    $after_XPath = "]";
 
    $this->webDriver->get($test_url);
    $this->webDriver->manage()->window()->maximize();
    sleep(5);
 
    $driver = $this->webDriver;
    $this->webDriver->wait()->until(
    function () use ($driver) {
        $elements = $this->webDriver->findElements(WebDriverBy::className('w3-example'));
        return count($elements) > 0;
    },
    'Error locating W3 example element'
    );
 
    $rows = count ($this->webDriver->findElements(WebDriverBy::xpath("//*[@id='customers']/tbody/tr")));
    echo ("Rows in table are " . $rows);
 
    $columns = count ($this->webDriver->findElements(WebDriverBy::xpath("//*[@id='customers']/tbody/tr[2]/td")));
    echo("\nColumns in table are " . $columns);
    echo("\n");
    echo("\n");
 
    $this->assertEquals($title, $this->webDriver->getTitle());
 
    echo("\n\n");
    echo("Data present in Col - 1 i.e. Title\n");
    echo("-----------------------------\n");
    echo("\n");
 
    for($t_col = 1; $t_col <= $columns; $t_col++)
    {
        $FinalXPath = $before_XPath_1 .$t_col. $after_XPath;
        $cell = $this->webDriver->findElement(WebDriverBy::xpath($FinalXPath));
        $cell_text = $cell->getText();
        echo($cell_text);
        echo("\n");
    }
 
    echo("\n\n");
    echo("Data present in Col - 2\n");
    echo("-----------------------\n");
    echo("\n");
 
    for($t_col = 1; $t_col <= $columns; $t_col++)
    {
        $FinalXPath = $before_XPath_2 .$t_col. $after_XPath;
        $cell = $this->webDriver->findElement(WebDriverBy::xpath($FinalXPath));
        $cell_text = $cell->getText();
        echo($cell_text);
        echo("\n");
    }   
    echo("\n\n");
    echo("Fetched all the records from the table\n");
  }
}
?>
```

**Code WalkThrough**

**Lines (47 – 49)**: $before\_XPath\_1 holds the static part of the XPath for row 1 (i.e., row with the Header). The variable $before\_XPath\_2 has the static part of the XPath for row 2.

As mentioned earlier, the column-number will be appended to the XPaths to form the resultant XPath, which will be used to navigate the appropriate cell.

```
$before_XPath_1 = "//*[@id='customers']/tbody/tr[1]/th["; 
$before_XPath_2 = "//*[@id='customers']/tbody/tr[2]/td["; 
$after_XPath = "]";
```

**Lines (79 – 86)**: Here is the implementation for printing values available in columns (1..3) with row number being constant (i.e., row number = 1).

In the code shown below, XPath for row – 1 (i.e., tr[1]) is appended to the computed XPath.

```
for($t_col = 1; $t_col <= ($columns); $t_col++) 
{ 
$FinalXPath = $before_XPath_1 .$t_col. $after_XPath; 
$cell = $this->webDriver->findElement(WebDriverBy::xpath($FinalXPath)); $cell_text = $cell->getText(); 
echo($cell_text); 
echo("\n"); }
```

The for loop will be executed with columns ranging from 1..3. The corresponding row values (tr[1]/tr[2]/tr[3]… tr[7]) are appended depending on the row that has to be accessed.

**Execution**

As seen in the execution snapshot, a ‘column-wise’ read is performed on every cell in the table. ![](https://www.lambdatest.com/blog/wp-content/uploads/2020/12/image13-1.png)

### How To Locate An Element In Web Tables In Selenium PHP?

In this test, we look for an element in the table and alert whether the element is present or not. The content in each cell is read, and a case insensitive search is performed to check the element’s presence.

**Implementation**

```php
<?php
require 'vendor/autoload.php';
 
use PHPUnit\Framework\TestCase;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\WebDriverBy;
 
$GLOBALS['LT_USERNAME'] = "user-name";
$GLOBALS['LT_APPKEY'] = "access-key";
 
class WebTable_Search_DataTest extends TestCase
{
  protected $webDriver;
 
  public function build_browser_capabilities(){
    /* $capabilities = DesiredCapabilities::chrome(); */
    $capabilities = array(
      "build" => "[PHP-5] Perform a search for an element in the web table",
      "name" => "[PHP-5] Perform a search for an element in the web table",
      "platform" => "Windows 10",
      "browserName" => "Chrome",
      "version" => "85.0"
    );
    return $capabilities;
  }
  
  public function setUp(): void
  {
    $url = "https://". $GLOBALS['LT_USERNAME'] .":" . $GLOBALS['LT_APPKEY'] ."@hub.lambdatest.com/wd/hub";
    $capabilities = $this->build_browser_capabilities();
    /* $this->webDriver = RemoteWebDriver::create('http://localhost:4444/wd/hub', $capabilities); */
    $this->webDriver = RemoteWebDriver::create($url, $capabilities);
  }
 
  public function tearDown(): void
  {
    $this->webDriver->quit();
  }
  /*
  * @test
  */ 
  public function test_SwitchToNewWindow()
  {
    $test_url = "https://www.w3schools.com/html/html_tables.asp";
    $title = "HTML Tables";
    $before_XPath = "//*[@id='customers']/tbody/tr[";
    $aftertd_XPath = "]/td[";
    $aftertr_XPath = "]";
    $search_text = " Magazzini Alimentari Riuniti";
 
    $this->webDriver->get($test_url);
    $this->assertEquals($title, $this->webDriver->getTitle());
    $this->webDriver->manage()->window()->maximize();
    sleep(5);
    
    $driver = $this->webDriver;
    $this->webDriver->wait()->until(
    function () use ($driver) {
        $elements = $this->webDriver->findElements(WebDriverBy::className('w3-example'));
        return count($elements) > 0;
    },
    'Error locating W3 example element'
    );
 
    $rows = count ($this->webDriver->findElements(WebDriverBy::xpath("//*[@id='customers']/tbody/tr")));
    echo ("\nRows in table are " . $rows);
    
    $columns = count ($this->webDriver->findElements(WebDriverBy::xpath("//*[@id='customers']/tbody/tr[2]/td")));
    echo("\nColumns in table are " . $columns);
    echo("\n");
    echo("\n");
    
    $elem_found = False;
 
    for($t_row = 2; $t_row <= $rows; $t_row++)
    {
        for($t_column = 1; $t_column <= $columns; $t_column++)
        {
            $FinalXPath = $before_XPath . $t_row . $aftertd_XPath . $t_column . $aftertr_XPath;
            $cell = $this->webDriver->findElement(WebDriverBy::xpath($FinalXPath));
            $cell_text = $cell->getText();
            if ((strcasecmp($cell_text, $search_text)) == 0)
            {
                $concat_str = "Search Text " . $search_text . " is present at row " . $t_row . " and column " . $t_column . " in the table";
                echo($concat_str);
                $elem_found = True;
                break;
            }
        }
    }
    
    if ($elem_found == False)
    {
        echo("Search Text " . $search_text ." not found");
    }
  }
}
?>
```

**Code WalkThrough**

**Lines (47 – 50)**: As the search has to be performed on every cell in the web table, the row-numbers and column-numbers would be variable. We break the resultant XPath into three different parts, as shown below: 

![](https://www.lambdatest.com/blog/wp-content/uploads/2020/12/image14-1.png)

A nested for loop will be executed for parsing through the contents of the table. Hence, row-number and column-number will be fetched during run-time.

```
$before_XPath = "//*[@id='customers']/tbody/tr[";
$aftertd_XPath = "]/td[";
$aftertr_XPath = "]";
$search_text = " Magazzini Alimentari Riuniti";
```

**Lines (76 – 80)**: A nested for loop is used for navigating to every cell in the web table. The outer loop is based on the number of rows (i.e., it executes from 2..7), whereas the inner for loop is based on the number of columns (i.e., it executes from 1..3).

As seen in the previous step, the corresponding row and column are added to the variables used for defining the XPath.

For example, the XPath for the following RC combinations will be:

- R-2, C-1 : //\*[@id=”customers”]/tbody/tr[2]/td[1]
- R-6, C-2 : //\*[@id=”customers”]/tbody/tr[6]/td[2]
 
```
for($t_row = 2; $t_row <= $rows; $t_row++) 
{ 
for($t_column = 1; $t_column <= $columns; $t_column++) { $FinalXPath = $before_XPath . $t_row . $aftertd_XPath . $t_column . $aftertr_XPath; ................................ ................................ } }
```

**Lines (81 – 82)**: Using the getText method provided by Selenium in PHP, we read the text (or data) present in the current cell.

```
$cell = $this->webDriver->findElement(WebDriverBy::xpath($FinalXPath)); $cell_text = $cell->getText();
```

**Lines (83 – 89)**: A case-insensitive comparison is performed with the search string, and the cell details are printed if the string present in the current cell matches with the search string. A Boolean variable elem\_found is set to True, and the loop is exited.

```
if ((strcasecmp($cell_text, $search_text)) == 0) 
{ 
$concat_str = "Search Text " . $search_text . " is present at row " . $t_row . " and column " . $t_column . " in the table"; 
echo($concat_str); 
$elem_found = True; 
break; }
```

**Lines (93 – 96)**: If the search term is not found, the Boolean variable elem\_found is False, and we print that the search string is not present in the web table.

```
if ($elem_found == False) { echo("Search Text " . $search_text ." not found"); }
```

**Execution**

We executed the code with two search strings – 1. LambdaTest, and 2. Yoshi tanNamuri.  
As seen in the execution snapshot, the search string ‘LambdaTest’ is not present in the table:

![](https://www.lambdatest.com/blog/wp-content/uploads/2020/12/image15-1.png)

Shown below is the execution snapshot where the search string is Magazzini Alimentari Riuniti. The string is present in the cell (7,1) in the table.

![](https://www.lambdatest.com/blog/wp-content/uploads/2020/12/image16-1.png)  
 ![](https://www.lambdatest.com/blog/wp-content/uploads/2020/12/image17.png)Though there are many more operations possible with web tables in Selenium PHP, we have covered the widely used operations in this Selenium PHP tutorial. Check out the [most detailed Selenium PHP tutorial (with Examples)](https://www.lambdatest.com/blog/selenium-php-tutorial/?utm_source=dev&utm_medium=Blog&utm_campaign=Himanshu-1022021&utm_term=Himanshu)

## Conclusion

![](https://www.lambdatest.com/blog/wp-content/uploads/2020/12/image18.gif)

Web tables are commonly used when information has to be displayed in a tabular format. The data in the cells could either be static or dynamic. Whether it is Selenium PHP or Selenium Python, or any other framework-language combination, web tables’ essentials remain unchanged.

You may face cross browser issues (especially with older browser versions and retired browsers like Internet Explorer) with web tables in Selenium PHP. Hence, it is recommended to verify the functionalities of tables on cross browser platforms like LambdaTest that lets you test tables in Selenium PHP across multiple combinations of browsers, devices (or emulators), and platforms.

_Have you used web tables for Selenium web automation? If yes, what’s your experience with them? Have you learned anything that I’ve missed in this post? I’d love to benefit from your experience too!_