Home > Back-end >  Iterating through table eventually throws a Stale Element Exception
Iterating through table eventually throws a Stale Element Exception

Time:01-04

I have a selenium C# script that iterates through a table and collects all the data in the rows. However after the third time I page down through the table, I receive a stale element exception. One thing to note is that this table is in an Iframe, and the data doesn't load unless you scroll down through the table. I got around this by collecting the TD and once I receive a blank TD, then page down to the next set of data in the table. How do I keep tdCollection = row.FindElements(By.TagName"tr") from going stale?

 do
    {
        IList<IWebElement> tdCollection;
        IWebElement table = driver.FindElement(By.Id("isc_Jtable"));
        var rows = table.FindElements(By.TagName("tr"));
        foreach (var row in rows)
        {
            tdCollection = row.FindElements(By.TagName("td"));
            if (tdCollection[0].Text == "")
            {
                CurrentFrame.ActiveElement().SendKeys(Keys.PageDown);
            }
            else
            {
                Logger.WriteLog(logName, String.Format("{1}{0}", " PCI ID: "   tdCollection[0].Text, DateTime.Now.ToLocalTime()));
                tdCount  ;

            }

        }
    }

CodePudding user response:

The expression tdCollection = row.FindElements(By.TagName"tr") is throwing StaleElementReference because it tries to access the row element which after couple of iterations has went stale, perhaps because the HTML elements rows represents have changed.

You should try to iterate dynamically through the table instead of getting a fixed list of rows which probably changes as you described.

IWebElement table = driver.FindElement(By.Id("isc_Jtable"));
int tableRowIndex = 1;
while (true) {
    try {
        var tableRow = table.FindElement(By.Xpath("tr["   tableRowIndex   "]"));
        tableRowIndex  ;
        IList<IWebElement> tdCollection = tableRow.FindElements(By.TagName("td"))
        // Do something with tdCollection
    }
    catch (NoSuchElementException ex) {
        // Last iteration
        break;
    }
}

You can see that I only keep a reference to the 'active' row and when I'm done processing its data, I'm finding the next one.

Also if you don't like the while (true) you can swap the break for a boolean flag which will be checked.

  • Related