Reputation: 4801
I have an arbitrary number of tiles that have a unique class name. One of them has a unique title so I'm trying to grab that one specifically. Once I've done that, I want a reference to child element rather deep in its structure.
Does the "tile." part of tile.findElement() do anything for me here? I want to be specifically using an xpath relative to tile.
public WebElement getArticleTileByTitle(String title){
By xpath = By.xpath(".//div[contains(., '" + title + "') or @title='" + title + "']");
List<WebElement> tiles = findPresentElements(By.className("articleTile"));
for(WebElement tile : tiles){
if(isElementPresent(tile, xpath))
return tile;
}
return null;
}
public boolean articleTileImageIsVisible(WebElement tile){
WebElement background = tile.findElement(By.xpath("/*[2]/*[2]/*[1]/*[3]")); //This throws NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"/*[2]/*[2]/*[1]/*[3]"}
//figure out stuff about background
}
I know that background is of type img so I've tried
tile.findElement(By.xpath("./img/*[2]/*[2]/*[1]/*[3]"));
tile.findElement(By.xpath("./*/*[2]/*[2]/*[1]/*[3]"));
tile.findElement(By.xpath(".//*/*[2]/*[2]/*[1]/*[3]"));
tile.findElement(By.xpath("./*/*[2]/*[2]/*[1]/*[3]"));
Never the less, I keep getting variations on NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"/[2]/[2]/[1]/[3]"} and That's not a valid xpath.
This question is very similar to Selenium 2 - Can findElement(By.xpath) be scoped to a particular element? but people seem to have either misinterpreted it or my use case is different.
Upvotes: 7
Views: 36528
Reputation: 10329
The API documentation for findElements()
says:
When using xpath be aware that webdriver follows standard conventions: a search prefixed with "//" will search the entire document, not just the children of this current node. Use ".//" to limit your search to the children of this WebElement.
Same rules apply to findElement()
(the singular form). So you should be able to do something like:
WebElement foo = driver.findElement(By.xpath("//*[@title='" + title + "']"));
WebElement bar = foo.findElement(By.xpath(".//img"));
The leading dot in the second xpath makes all the difference, as it will search only for child elements of foo
.
Upvotes: 25
Reputation: 113
Topic with similar question! - XPath to get all child nodes (elements, comments, and text) without parent
this part from that topic can interest you.
child::*
selects all element children of the context node
child::text()
selects all text node children of the context node
child::node()
selects all the children of the context node, whatever their node type
We can identify the child nodes from the parent, by localizing it with the parent and then passing ( ./child::*)
as a parameter to the findElements(By.xpath(""))
var childs = parent.findElements(By.xpath("./child::*"));
then in your code filter/process them...
Upvotes: 2