Java 过时的元素引用:元素未附加到页面文档

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18225997/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:29:02  来源:igfitidea点击:

stale element reference: element is not attached to the page document

javalistselenium-webdriver

提问by Patil Prashanth

I have list which has multiple links under each section. Each section has same links I need to click a particular link under each section. I have written the below code but when it executes it gives me stale element reference: element is not attached to the page documenterror.

我有一个列表,每个部分下都有多个链接。每个部分都有相同的链接,我需要单击每个部分下的特定链接。我写了下面的代码,但是当它执行时它给了我stale element reference: element is not attached to the page document错误。

This is my code:

这是我的代码:

public static void main(String[] args) throws InterruptedException 
{
    WebDriver driver = new ChromeDriver();
    driver.navigate().to("url......");
        driver.findElement(By.id("Login1_txtEmailID")).sendKeys("[email protected]");
    driver.findElement(By.id("Login1_txtPassword")).sendKeys("Testing1*");
    driver.findElement(By.id("Login1_btnLogin")).click();
    List<WebElement> LeftNavLinks=driver.findElements(By.xpath("//*[@id='sliding-navigation']//a"));
    Thread.sleep(1000);
    String ben="Benefit Status";
    String[] linkTexts = new String[LeftNavLinks.size()];
    int i = 0;
    for (WebElement e : LeftNavLinks) 
    {   
        linkTexts[i] = e.getText();
        System.out.print(i+" " + linkTexts[i]+"\n");
        if(linkTexts[i].equals(ben))
        {
            String BenefitStatLi="//*[@id='sliding-navigation']/li[%s]/a";
            System.out.print(i+" " + linkTexts[i]+"\n");
                driver.findElement(By.xpath(String.format(BenefitStatLi,i))).click();
            driver.findElement(By.xpath("//* [@id='divContentHolder']/div[1]/a[1]")).click();
        }
        i++;
    }
}

}

This is the HTML structure is as below

这是HTML结构如下

<div id="ucAdminMenu_divMenu">
  <ul id="sliding-navigation">
    <li class="sliding-element">
      <a href=" ">Claims Status</a>
    </li>
    <li class="sliding-element">
      <a href=" ">Eligibility Status</a>
    </li>
    <li class="sliding-element">
      <h3>Section-1</h3>
    </li>
    <li class="sliding-element">
      <a href=" ">Forms and Documents</a>
    </li>
    <li class="sliding-element">
      <a href=" HourBank.aspx?id=002">Hour Bank</a>
    </li>
    <li class="sliding-element">
      <h3>Section-2</h3>
    </li>
    <li class="sliding-element">
      <a href=" ">Benefit Status</a>
    </li>
    <li class="sliding-element">
      <a href=" ">Forms and Documents</a>
    </li>
    <li class="sliding-element">
      <h3>Section-3</h3>
    </li>
    <li class="sliding-element">
      <a href=" ">Forms and Documents</a>
    </li>
    <li class="sliding-element">
      <h3>Testing Fund</h3>
    </li>
    <li class="sliding-element">
      <a href=" ">Benefit Status</a>
    </li>
    <li class="sliding-element">
      <a href=" ">Order ID Card</a>
    </li>
  </ul>
</div>

The Error Trace is:

错误跟踪是:

    Exception in thread "main" 
org.openqa.selenium.StaleElementReferenceException: stale element 
reference: element is not attached to the page document

回答by Abhishek Singh

What is the line which gives exception ??

给出异常的行是什么?

The reason for this is because the element to which you have referred is removed from the DOM structure

这样做的原因是因为您所引用的元素已从 DOM 结构中删除

I was facing the same problem while working with IEDriver. The reason was because javascript loaded the element one more time after i have referred so my date reference pointed to an unexisting object even if it was right their on UI. I used the following workaround.

我在使用 IEDriver 时遇到了同样的问题。原因是因为 javascript 在我引用后又加载了一次元素,所以我的日期引用指向一个不存在的对象,即使它在 UI 上是正确的。我使用了以下解决方法。

try {
    WebElement date = driver.findElement(By.linkText(Utility.getSheetData(path, 7, 1, 2)));
    date.click();
}
catch(org.openqa.selenium.StaleElementReferenceException ex)
{
    WebElement date = driver.findElement(By.linkText(Utility.getSheetData(path, 7, 1, 2)));
    date.click();
}

See if the same can help you !

看看能不能帮到你!

回答by kiran

Use this code:

使用此代码:

public class LinkTest 
{   
    public static void main(String[] args) 
    {
        WebDriver driver = new FirefoxDriver();
        driver.navigate().to("file:///C:/Users/vkiran/Desktop/xyz.html");
        List<WebElement> alllinks =driver.findElements(By.xpath("//*[@id='sliding-navigation']//a"));
        String a[]=new String[alllinks.size()];
        for(int i=0;i<alllinks.size();i++)
        {
            a[i]=alllinks.get(i).getText(); 
            if(a[i].startsWith("B"))
            {
                System.out.println("clicking on this link::"+driver.findElement(By.linkText(a[i])).getText());
                driver.findElement(By.linkText(a[i])).click();  

            }
            else
            {
                System.out.println("does not starts with B so not clicking");
            }
        }
}
}

回答by kiran

use this code to wait till the element is attached:

使用此代码等待元素被附加:

boolean breakIt = true;
        while (true) {
        breakIt = true;
        try {
            // write your code here
        } catch (Exception e) {
            if (e.getMessage().contains("element is not attached")) {
                breakIt = false;
            }
        }
        if (breakIt) {
            break;
        }

    }

回答by Adrian Coroi

The thing here is that you're using a for loop outside of your conditional statement.

这里的问题是您在条件语句之外使用了 for 循环。

After the conditions in your IF statement are met you probably navigate to another page, thus when the for loop attempts to iterate once more, you get the stale element error because you're on a different page.

在满足 IF 语句中的条件后,您可能会导航到另一个页面,因此当 for 循环尝试再次迭代时,您会收到过时元素错误,因为您位于不同的页面上。

You can add a breakat the end of your if statement, this worked for me.

您可以在 if 语句的末尾添加一个中断,这对我有用。

回答by ??? ??????

Just break the loop when you find the element you want to click on it. for example:

当您找到要单击的元素时,只需中断循环即可。例如:

  List<WebElement> buttons = getButtonElements();
    for (WebElement b : buttons) {
        if (b.getText().equals("Next"){
            b.click();
            break;
        }

回答by Alisha Raju

To handle it, I use the following click method. This will attempt to find and click the element. If the DOM changes between the find and click, it will try again. The idea is that if it failed and I try again immediately the second attempt will succeed. If the DOM changes are very rapid then this will not work.

为了处理它,我使用以下点击方法。这将尝试查找并单击该元素。如果 DOM 在查找和单击之间发生变化,它将重试。这个想法是,如果它失败了,我立即再试一次,第二次尝试就会成功。如果 DOM 变化非常快,那么这将不起作用。

public boolean retryingFindClick(By by) {
    boolean result = false;
    int attempts = 0;
    while(attempts < 2) {
        try {
            driver.findElement(by).click();
            result = true;
            break;
        } catch(StaleElementException e) {
        }
        attempts++;
    }
    return result;
}

回答by Charan Raz

try {
    WebElement button = driver.findElement(By.xpath("xpath"));
            button.click();
}
catch(org.openqa.selenium.StaleElementReferenceException ex)
{
    WebElement button = driver.findElement(By.xpath("xpath"));
            button.click();
}

This try/catch code actually worked for me. I got the same stale element error.

这个 try/catch 代码实际上对我有用。我得到了同样的陈旧元素错误。

回答by SkorpEN

This could be done in newer versions of selenium in JS( but all supporting stalenessOfwill work):

这可以在 JS 中更新版本的 selenium 中完成(但所有支持stalenessOf都可以):

 const { until } = require('selenium-webdriver');
 driver.wait(
        until.stalenessOf(
          driver.findElement(
            By.css(SQLQueriesByPhpMyAdminSelectors.sqlQueryArea)
          )
        ),
        5 * 1000
      )
      .then( driver.findElement(By.css(SQLQueriesByPhpMyAdminSelectors.sqlQueryArea))
      .sendKeys(sqlString)
  );

回答by Bruno Sanches

This errors have two common causes: The element has been deleted entirely, or the element is no longer attached to the DOM.

此错误有两个常见原因:该元素已被完全删除,或该元素不再附加到 DOM。

If you already checked if it is not your case, you could be facing the same problem as me.

如果您已经检查过这是否不是您的情况,那么您可能面临与我相同的问题。

The element in the DOM is not found because your page is not entirely loaded when Selenium is searching for the element. To solve that, you can put an explicit wait condition that tells Selenium to wait until the element is available to be clicked on.

未找到 DOM 中的元素,因为 Selenium 搜索元素时您的页面未完全加载。为了解决这个问题,你可以设置一个明确的等待条件,告诉 Selenium 等待元素可以被点击。

from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, 'someid')))

See: https://selenium-python.readthedocs.io/waits.html

请参阅:https: //selenium-python.readthedocs.io/waits.html

回答by rohit goudar

Whenever you face this issue, just define the web element once againabove the line in which you are getting an Error.

每当您遇到此问题时,只需在出现错误的行上方再次定义 Web 元素即可

Example:

例子:

WebElement button = driver.findElement(By.xpath("xpath"));
button.click();

//here you do something like update or save 

//then you try to use the button WebElement again to click 
button.click();

Since the DOM has changed e.g. through the update action, you are receiving a StaleElementReferenceError.

由于 DOM 已更改,例如通过更新操作,您将收到StaleElementReference错误。

Solution:

解决方案:

WebElement button = driver.findElement(By.xpath("xpath"));
button.click();

//here you do something like update or save 

//then you define the button element again before you use it
WebElement button1 = driver.findElement(By.xpath("xpath"));
//that new element will point to the same element in the new DOM
button1.click();