7

是否可以返回 WebElement 的 xpath ?

4

8 回答 8

9

不是直接来自 WebDriver,但如果你真的需要,你可以伪造它:

public String getElementXPath(WebDriver driver, WebElement element) {
    return (String)((JavascriptExecutor)driver).executeScript("gPt=function(c){if(c.id!==''){return'id(\"'+c.id+'\")'}if(c===document.body){return c.tagName}var a=0;var e=c.parentNode.childNodes;for(var b=0;b<e.length;b++){var d=e[b];if(d===c){return gPt(c.parentNode)+'/'+c.tagName+'['+(a+1)+']'}if(d.nodeType===1&&d.tagName===c.tagName){a++}}};return gPt(arguments[0]).toLowerCase();", element);
}

Javascript 来自这篇文章,已缩小到一行。它可能并不完美,但可以让你知道去哪里。大多数驱动程序都实现了该JavascriptExecutor接口并具有在浏览器中执行 Javascript 的能力。executeScript可以返回任何原始 JavaScript 类型、HTML 元素或上述任何内容的非嵌套列表。

并非所有浏览器都以相同的方式支持 xpath,因此在使用这些 xpath 选择元素时要小心。此外,并非所有浏览器都支持原生 xpath(咳嗽IE咳嗽),所以在这种情况下它是伪造的。

于 2010-12-09T22:33:29.437 回答
5

如果 WebElement 由 By.xpath: 在 Java 上找到:

public static String GetWebElementXpath(WebElement El) throws AssertionError{
        if ((El instanceof WebElement)){
            Object o = El;
            String text = o.toString();
        /* text is smth like this
        [[FirefoxDriver: firefox on WINDOWS (9170d4a5-1554-4018-adac-f3f6385370c0)] -> xpath: //div[contains(@class,'forum-topic-preview')]//div[contains(@class,'small-human')]]
        */
            text = text.substring( text.indexOf("xpath: ")+7,text.length()-1);
            return text;
        }else   {   Assert.fail("Argument is not an WebElement, his actual class is:"+El.getClass());       }
        return "";
    }
于 2014-12-24T04:27:10.147 回答
4

上述两个答案都存在同样的问题。通过使用.toLowerCase()调用的函数返回完整的 XPath,任何包含带有大写字母的 id 的 XPath 都将不起作用。

示例://div[@id="deviceblock-1111"]不适用于标签<div id="deviceBlock-1111">

但是,您可以只删除.toLowerCase()返回的调用,但最终 XPath 看起来像这样://DIV[@id="deviceBlock-1111"]/DIV[2]/SELECT[1]/OPTION[5]

要解决此问题,请使用以下功能。

public String GetElementXPath(WebElement element, WebDriver driver)
{
    return (String) ((JavascriptExecutor) driver).executeScript(
    "getXPath=function(node)" +
    "{" +
        "if (node.id !== '')" +
        "{" +
            "return '//' + node.tagName.toLowerCase() + '[@id=\"' + node.id + '\"]'" +
        "}" +

        "if (node === document.body)" +
        "{" +
            "return node.tagName.toLowerCase()" +
        "}" +

        "var nodeCount = 0;" +
        "var childNodes = node.parentNode.childNodes;" +

        "for (var i=0; i<childNodes.length; i++)" +
        "{" +
            "var currentNode = childNodes[i];" +

            "if (currentNode === node)" +
            "{" +
                "return getXPath(node.parentNode) + 
                    '/' + node.tagName.toLowerCase() + 
                    '[' + (nodeCount+1) + ']'" +
            "}" +

            "if (currentNode.nodeType === 1 && " +
                "currentNode.tagName.toLowerCase() === node.tagName.toLowerCase())" +
            "{" +
                "nodeCount++" +
            "}" +
        "}" +
    "};" +

    "return getXPath(arguments[0]);", element);
}

这将从您的 WebElement 返回格式正确、唯一的 XPath。

//div[@id="deviceBlock-1111"]/div[2]/select[1]/option[5]

于 2013-02-22T19:50:16.107 回答
1
public String getElementXPath(WebDriver driver, WebElement element) {

    String javaScript = "function getElementXPath(elt){" +
                            "var path = \"\";" +
                            "for (; elt && elt.nodeType == 1; elt = elt.parentNode){" +
                                "idx = getElementIdx(elt);" +
                                "xname = elt.tagName;" +
                                "if (idx > 1){" +
                                    "xname += \"[\" + idx + \"]\";" +
                                "}" +
                                "path = \"/\" + xname + path;" +
                            "}" + 
                            "return path;" +
                        "}" +
                        "function getElementIdx(elt){" +
                            "var count = 1;" +
                            "for (var sib = elt.previousSibling; sib ; sib = sib.previousSibling){" +
                                "if(sib.nodeType == 1 && sib.tagName == elt.tagName){" +
                                    "count++;" +
                                "}" +
                            "}" +
                            "return count;" + 
                        "}" +
                        "return getElementXPath(arguments[0]).toLowerCase();";      

    return (String)((JavascriptExecutor)driver).executeScript(javaScript, element);     

}
于 2012-03-26T17:14:18.410 回答
1

我会直接评论dflems回答,但我没有这样做的声誉。

将整个 xpath 转换为小写是可以的,除非 xpath 包含一个并非全部小写的 id 值。下面是 dflems 的 Javascript 的修改版本,但使用的是 Python 而不是 Java:

def get_xpath_from_element(driver, element):
    return driver.execute_script("gPt=function(c){if(c.id!==''){return'id(\"'+c.id+'\")'}if(c===document.body){return c.tagName}var a=0;var e=c.parentNode.childNodes;for(var b=0;b<e.length;b++){var d=e[b];if(d===c){return gPt(c.parentNode)+'/'+c.tagName.toLowerCase()+'['+(a+1)+']'}if(d.nodeType===1&&d.tagName===c.tagName){a++}}};return gPt(arguments[0]);", element)

于 2016-09-13T18:27:38.963 回答
0

有一种方法可以在不使用 JavaScript 的情况下获取元素 XPath。

  1. 定义外部 XPath 的起点,例如 body 标记。
  2. 用 selenium 检查所有可能的内向标签NoSuchElementException
  3. 检查getText生成的 XPath 列表。
于 2014-08-08T10:18:25.003 回答
0
public static String getXPathFromElement(WebElement element) {
        String elementDescription = element.toString();
        return elementDescription.substring(elementDescription.lastIndexOf("-> ") + 3, elementDescription.lastIndexOf("]"));
}

Web 元素 toString() 如下所示:

'[[FirefoxDriver: WINDOWS 上的 firefox (ceb69f9f-bef4-455d-b626-ab439f195be6)] -> id: pageBeanfundDescription]'

我只是提取 id/xpath。

于 2015-07-02T08:31:40.133 回答
0
/**
 * This method return By reference for the WebElement passed to it as a parameter.
 * @param element
 * @return
 */
public static By convertWebElementToByReference(WebElement element) 
{
    By byLocator = null;
    String elementDescription = element.toString();
    String elementTypeAndValue[] = (elementDescription.substring(elementDescription.lastIndexOf("-> ") + 3, elementDescription.lastIndexOf("]"))).split(":");        

    switch (elementTypeAndValue[0].trim()) 
    {
        case "id": byLocator = By.id(elementTypeAndValue[1].trim());
           break;

        case "xpath": byLocator = By.xpath(elementTypeAndValue[1].trim());
           break;

        case "link text": byLocator = By.linkText(elementTypeAndValue[1].trim());
           break;

        case "tag name": byLocator = By.tagName(elementTypeAndValue[1].trim());
           break;

        case "class name": byLocator = By.className(elementTypeAndValue[1].trim());
           break;

        case "partial link text": byLocator = By.partialLinkText(elementTypeAndValue[1].trim());
           break;

        case "name": byLocator = By.name(elementTypeAndValue[1].trim());
           break;

        case "css selector": byLocator = By.cssSelector(elementTypeAndValue[1].trim());
           break;

        default:
            throw new RuntimeException("Invalid locator type: " + elementTypeAndValue[0].trim());
    }

    return byLocator;
}
于 2016-04-28T07:18:08.080 回答