1

How can i get the xpath from a WebElement

Webelement element= driver.findElement(By.xpath("//div//input[@name='q']"));

something like

element.getLocator(); ->> this should be like this "//div//input[@name='q']"

how to do the same? I have created below method and passed xpath as parameter. I want to create same method and pass webElement as parameter:

public boolean isElementPresentAndVisible(String xpath){
    if(driver.findElements(By.xpath(xpath)).size()!=0){
        if(driver.findElement(By.xpath(xpath)).isDisplayed()){
            System.out.println(xpath+" present and Visible");
            return true;
        }else{
            System.err.println(xpath+" present but NOT Visible");
            return false;
        } 
    }else{
        System.err.println(xpath+" NOT present");
        return false;
    } 

}
Amittech3
  • 49
  • 1
  • 2
  • 4
  • 4
    What is the point of locating element by XPath and use some kind of method to return you exactly the same XPath? How Selenium "should know" that `"//div//input[@name='q']"` is the exact XPath that you're searching for, but not `//div[@id="some_id"]/input`...? – Andersson May 29 '18 at 08:05
  • @Andersson I have updated my question. I have created isElementPresentAndVisible(String xpath) and want to create isElementPresentAndVisible(WebElement element) – Amittech3 May 29 '18 at 09:26

3 Answers3

3

Get WebElement by id or name then call the method generate generateXPATH() passing the element.It will return the Xpath.Find the code:

 String z=generateXPATH(webElement, "");//calling method,passing the element

 public static String generateXPATH(WebElement childElement, String current) {
        String childTag = childElement.getTagName();
        if(childTag.equals("html")) {
            return "/html[1]"+current;
        }
        WebElement parentElement = childElement.findElement(By.xpath("..")); 
        List<WebElement> childrenElements = parentElement.findElements(By.xpath("*"));
        int count = 0;
        for(int i=0;i<childrenElements.size(); i++) {
            WebElement childrenElement = childrenElements.get(i);
            String childrenElementTag = childrenElement.getTagName();
            if(childTag.equals(childrenElementTag)) {
                count++;
            }
            if(childElement.equals(childrenElement)) {
                return generateXPATH(parentElement, "/" + childTag + "[" + count + "]"+current);
            }
        }
        return null;
    }
  • This code worked perfectly for me. It's not fast, but that's to be expected. The only modification I made to it was to do a `.replace("[1]","")` to the output since the [1]'s were unnecessary. This is useful for scenarios where you read in an entire list of webelements, say with //a and want to get/save each element's xpath. – Bill Hileman Feb 12 '19 at 21:28
0

There is no method to do what you are asking but you don't need it anyway. You are making this more complicated than it needs to be. If an element is visible, it's also present so there's no need to check for present.

Instead of passing in an XPath as a string, instead pass a By locator. Now you can use any locator type you want. I've rewritten and simplified your code and then written the similar function that takes in a WebElement parameter.

public boolean isVisible(By locator)
{
    List<WebElement> e = driver.findElements(locator);
    if (e.size() != 0)
    {
        return isVisible(e.get(0));
    }

    return false;
}

public boolean isVisible(WebElement e)
{
    try
    {
        return e.isDisplayed();
    }
    catch (Exception)
    {
        return false;
    }
}
JeffC
  • 22,180
  • 5
  • 32
  • 55
  • Thanks JeffC, second method using isDisplayed() will work but It will return false in both cases 1) if element present and not visible 2) if element not present. Can you suggest any way by we can check if element is not displayed but present in DOM by using webElement as parameter? – Amittech3 May 31 '18 at 06:07
  • You can't have a bool return 3 different values. The code behaves the same as the code you posted. Returns `true` if it's visible and false otherwise. The name of the method is `isVisible()`. It should return `false` if the element is present but is not visible. If you want to detect if an element is present, you should write a method called `isPresent()` or maybe `exists()` and follow the code [here](https://stackoverflow.com/questions/7991522/selenium-webdriver-test-if-element-is-present). – JeffC May 31 '18 at 13:09
0

Python version of @shamsher Khan's answer -- it works.

def gen_xpath(child: WebElement, curr: str=''):
    if (child.tag_name == 'html'): return f'/html[1]{curr}'

    parent = child.find_element(By.XPATH, '..')
    children = parent.find_elements(By.XPATH, '*')
    i = 0
    for c in children:
        if c.tag_name == child.tag_name: i += 1
        if c == child: return gen_xpath(parent, f'/{child.tag_name}[{i}]{curr}')
ben
  • 1
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 15 '23 at 20:25