在selenium中定位WebElements的子节点

时间:2022-08-10 22:17:30

I am using selenium to test my web application and I can successfully find tags using By.xpath. However now and then I need to find child nodes within that node.

我正在使用selenium来测试我的Web应用程序,我可以使用By.xpath成功找到标签。但是,我现在需要在该节点中找到子节点。

Example:

例:

<div id="a">
    <div>
        <span />
        <input />
    </div>
</div>

I can do:

我可以:

WebElement divA = driver.findElement( By.xpath( "//div[@id='a']" ) )

But now I need to find the input, so I could do:

但现在我需要找到输入,所以我可以这样做:

driver.findElement( By.xpath( "//div[@id='a']//input" ) )

However at that point in code I only have divA, not its xpath any more... I would like to do something like this:

但是在代码中我只有divA,而不是它的xpath ...我想做这样的事情:

WebElement input = driver.findElement( divA, By.xpath( "//input" ) );

But such an function does not exist. Can I do this anyhow?

但是这样的功能不存在。我能这样做吗?

BTW: Sometimes I need to find a DIV that has a certain decendent node. How can I ask in xpath for "the div-tag that contains a span with the text 'hello world'"?

顺便说一句:有时候我需要找到一个具有某种后代节点的DIV。我怎样才能在xpath中询问“包含带有文本'hello world'的跨度的div-tag”?

5 个解决方案

#1


69  

According to JavaDocs, you can do this:

根据JavaDocs,您可以这样做:

WebElement input = divA.findElement(By.xpath(".//input"));

How can I ask in xpath for "the div-tag that contains a span with the text 'hello world'"?

我怎样才能在xpath中询问“包含带有文本'hello world'的跨度的div-tag”?

WebElement elem = driver.findElement(By.xpath("//div[span[text()='hello world']]"));

The XPath spec is a suprisingly good read on this.

XPath规范是一个令人惊讶的好读。

#2


1  

If you have to wait there is a method presenceOfNestedElementLocatedBy that takes the "parent" element and a locator, e.g. a By.xpath:

如果你必须等待,则有一个方法presenceOfNestedElementLocatedBy接受“父”元素和定位符,例如By.xpath:

WebElement subNode = new WebDriverWait(driver,10).until(
    ExpectedConditions.presenceOfNestedElementLocatedBy(
        divA, By.xpath(".//div/span")
    )
);

#3


0  

I also found myself in a similar position a couple of weeks ago. You can also do this by creating a custom ElementLocatorFactory (or simply passing in divA into the DefaultElementLocatorFactory) to see if it's a child of the first div - you would then call the appropriate PageFactory initElements method.

几周前我也发现自己处于类似的位置。您也可以通过创建自定义ElementLocatorFactory(或者只是将divA传入DefaultElementLocatorFactory)来查看它是否是第一个div的子项 - 然后您将调用相应的PageFactory initElements方法。

In this case if you did the following:

在这种情况下,如果您执行以下操作:

PageFactory.initElements(new DefaultElementLocatorFactory(divA), pageObjectInstance));
// The Page Object instance would then need a WebElement 
// annotated with something like the xpath above or @FindBy(tagName = "input")

#4


-1  

The toString() method of Selenium's By-Class produces something like "By.xpath: //XpathFoo"

Selenium的By-Class的toString()方法产生类似“By.xpath:// XpathFoo”的东西

So you could take a substring starting at the colon with something like this:

所以你可以从冒号开始使用这样的子字符串:

String selector = divA.toString().substring(s.indexOf(":") + 2);

With this, you could find your element inside your other element with this:

有了这个,你可以在其他元素中找到你的元素:

WebElement input = driver.findElement( By.xpath( selector + "//input" ) );

Advantage: You have to search only once on the actual SUT, so it could give you a bonus in performance.

优点:您只需要在实际SUT上搜索一次,因此它可以为您提供性能奖励。

Disadvantage: Ugly... if you want to search for the parent element with css selectory and use xpath for it's childs, you have to check for types before you concatenate... In this case, Slanec's solution (using findElement on a WebElement) is much better.

缺点:丑陋......如果你想用css selectory搜索父元素并为它的子元素使用xpath,你必须在连接之前检查类型...在这种情况下,Slanec的解决方案(在WebElement上使用findElement)好多了

#5


-2  

For Finding All the ChildNodes you can use the below Snippet

对于查找所有ChildNodes,您可以使用以下代码段

List<WebElement> childs = MyCurrentWebElement.findElements(By.xpath("./child::*"));

        for (WebElement e  : childs)
        {
            System.out.println(e.getTagName());
        }

Note that this will give all the Child Nodes at same level -> Like if you have structure like this :

请注意,这将为所有子节点提供相同级别 - >如果您有这样的结构,请执行以下操作:

<Html> 
<body> 
 <div> ---suppose this is current WebElement 
   <a>
   <a>
      <img>
          <a>
      <img>
   <a>

It will give me tag names of 3 anchor tags here only . If you want all the child Elements recursively , you can replace the above code with MyCurrentWebElement.findElements(By.xpath(".//*"));

它只会在这里给我3个锚标签的标签名称。如果你想递归所有的子元素,你可以用MyCurrentWebElement.findElements(By.xpath(“.//*”))替换上面的代码;

Hope That Helps !!

希望有助于!!

#1


69  

According to JavaDocs, you can do this:

根据JavaDocs,您可以这样做:

WebElement input = divA.findElement(By.xpath(".//input"));

How can I ask in xpath for "the div-tag that contains a span with the text 'hello world'"?

我怎样才能在xpath中询问“包含带有文本'hello world'的跨度的div-tag”?

WebElement elem = driver.findElement(By.xpath("//div[span[text()='hello world']]"));

The XPath spec is a suprisingly good read on this.

XPath规范是一个令人惊讶的好读。

#2


1  

If you have to wait there is a method presenceOfNestedElementLocatedBy that takes the "parent" element and a locator, e.g. a By.xpath:

如果你必须等待,则有一个方法presenceOfNestedElementLocatedBy接受“父”元素和定位符,例如By.xpath:

WebElement subNode = new WebDriverWait(driver,10).until(
    ExpectedConditions.presenceOfNestedElementLocatedBy(
        divA, By.xpath(".//div/span")
    )
);

#3


0  

I also found myself in a similar position a couple of weeks ago. You can also do this by creating a custom ElementLocatorFactory (or simply passing in divA into the DefaultElementLocatorFactory) to see if it's a child of the first div - you would then call the appropriate PageFactory initElements method.

几周前我也发现自己处于类似的位置。您也可以通过创建自定义ElementLocatorFactory(或者只是将divA传入DefaultElementLocatorFactory)来查看它是否是第一个div的子项 - 然后您将调用相应的PageFactory initElements方法。

In this case if you did the following:

在这种情况下,如果您执行以下操作:

PageFactory.initElements(new DefaultElementLocatorFactory(divA), pageObjectInstance));
// The Page Object instance would then need a WebElement 
// annotated with something like the xpath above or @FindBy(tagName = "input")

#4


-1  

The toString() method of Selenium's By-Class produces something like "By.xpath: //XpathFoo"

Selenium的By-Class的toString()方法产生类似“By.xpath:// XpathFoo”的东西

So you could take a substring starting at the colon with something like this:

所以你可以从冒号开始使用这样的子字符串:

String selector = divA.toString().substring(s.indexOf(":") + 2);

With this, you could find your element inside your other element with this:

有了这个,你可以在其他元素中找到你的元素:

WebElement input = driver.findElement( By.xpath( selector + "//input" ) );

Advantage: You have to search only once on the actual SUT, so it could give you a bonus in performance.

优点:您只需要在实际SUT上搜索一次,因此它可以为您提供性能奖励。

Disadvantage: Ugly... if you want to search for the parent element with css selectory and use xpath for it's childs, you have to check for types before you concatenate... In this case, Slanec's solution (using findElement on a WebElement) is much better.

缺点:丑陋......如果你想用css selectory搜索父元素并为它的子元素使用xpath,你必须在连接之前检查类型...在这种情况下,Slanec的解决方案(在WebElement上使用findElement)好多了

#5


-2  

For Finding All the ChildNodes you can use the below Snippet

对于查找所有ChildNodes,您可以使用以下代码段

List<WebElement> childs = MyCurrentWebElement.findElements(By.xpath("./child::*"));

        for (WebElement e  : childs)
        {
            System.out.println(e.getTagName());
        }

Note that this will give all the Child Nodes at same level -> Like if you have structure like this :

请注意,这将为所有子节点提供相同级别 - >如果您有这样的结构,请执行以下操作:

<Html> 
<body> 
 <div> ---suppose this is current WebElement 
   <a>
   <a>
      <img>
          <a>
      <img>
   <a>

It will give me tag names of 3 anchor tags here only . If you want all the child Elements recursively , you can replace the above code with MyCurrentWebElement.findElements(By.xpath(".//*"));

它只会在这里给我3个锚标签的标签名称。如果你想递归所有的子元素,你可以用MyCurrentWebElement.findElements(By.xpath(“.//*”))替换上面的代码;

Hope That Helps !!

希望有助于!!