154

各セクションの下に複数のリンクがあるリストがあります。各セクションには同じリンクがあり、各セクションの下にある特定のリンクをクリックする必要があります。以下のコードを書きましたが、実行するとstale element reference: element is not attached to the page documentエラーが発生します。

これは私のコードです:

public static void main(String[] args) throws InterruptedException 
{
    WebDriver driver = new ChromeDriver();
    driver.navigate().to("url......");
        driver.findElement(By.id("Login1_txtEmailID")).sendKeys("hourbank5@....com");
    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++;
    }
}

}

これは、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>

エラー トレースは次のとおりです。

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

13 に答える 13

18

このエラーには 2 つの一般的な原因があります。要素が完全に削除されたか、要素が DOM に関連付けられていません。

それがあなたのケースではないかどうかをすでに確認している場合は、私と同じ問題に直面している可能性があります.

Selenium が要素を検索しているときにページが完全に読み込まれていないため、DOM 内の要素が見つかりません。これを解決するには、要素がクリックできるようになるまで待機するように 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')))

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

Javaで

import org.openqa.selenium.support.ui.ExpectedConditions;

WebDriverWait wait = new WebDriverWait(driver, 10);
element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

参照: https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html

于 2018-09-21T18:29:26.090 に答える
4

ここで重要なのは、条件ステートメントの外で for ループを使用していることです。

IF ステートメントの条件が満たされた後、おそらく別のページに移動するため、for ループがもう一度反復しようとすると、別のページにいるため、古い要素エラーが発生します。

if ステートメントの最後にブレークを追加できます。これは私にとってはうまくいきました。

于 2016-10-16T18:50:06.653 に答える
2

次のコードを使用します。

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");
            }
        }
}
}
于 2013-12-24T07:41:25.833 に答える
0

私の場合、input type='date'ページの読み込み時に参照を取得したページがありましたが、それを操作しようとすると、これが表示され、コントロールを操作exceptionしたため非常に意味がJavascriptあり、ドキュメントから切り離されましたre-getjavascriptがコントロールでその仕事を実行した後、私はその参照をしなければなりませんでした。したがって、これは私のコードが例外の前にどのように見えるかです:

if (elemDate != null)
{ 
    elemDate.Clear(); 
    elemDate.SendKeys(model.Age);
}

例外が発生した後のコード:

int tries = 0;
do
{
    try
    {
        tries++;
        if (elemDate != null)
        {
            // these lines were causing the exception so I had break after these are successfully executed because if they are executed that means the control was found and attached to the document and we have taken the reference of it again.
            elemDate.Clear();
            elemDate.SendKeys(model.Age);
            break;
        }
    }
    catch (StaleElementReferenceException)
    {
        System.Threading.Thread.Sleep(10); // put minor fake delay so Javascript on page does its actions with controls
        elemDate = driver.FindElement(By.Id(dateId));
    }
} while (tries < 3); // Try it three times.

したがって、コードを使用してさらにアクションを実行したり、コントロールを機能させることができなかった場合はドライバーを終了したりできます。

if(tries > 2)
{
   // element was not found, find out what is causing the control detachment.
   // driver.Quit();
   return;
}

// Hurray!! Control was attached and actions were performed.
// Do something with it...

私がこれまでに学んだことは、成功したコード実行について知るために例外をキャッチすることは良い考えではありません.しかし、私はそれをしなければならなかったwork-around.

PS: これをすべて書いた後、このスレッドのタグがjava. このコード サンプルはデモンストレーションのみを目的としており、C#言語に問題がある人に役立つかもしれません。または、特定のコードjavaがあまりないため、簡単に変換できます。C#

于 2019-07-18T02:47:45.953 に答える
-8

このコードを使用して、要素がアタッチされるまで待機します。

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

    }
于 2015-06-25T22:20:29.500 に答える