按文本查找元素并获取xpath - selenium webdriver junit

时间:2013-08-29 12:08:10

标签: selenium junit selenium-webdriver

我的网页上有一个包含9行和6列的表格。我想搜索文本“MakeGoodDisabled-Programwise_09_44_38_461(n)”并获取单元格的xpath。我使用了以下但它失败了,因为它无法在页面上找到文本。你能帮忙吗?我正在使用Selenium Webdriver Junit对此进行编码。

List < WebElement > links = driver.findElements(By.tagName("td"));

Iterator < WebElement > itr = links.iterator();
while (itr.hasNext()) {
 String test = itr.next().getText();

 if (test.equals("MakeGoodDisabled-Programwise_09_44_38_461(n)")) {
  String xpath = driver.findElement(By.name(test)).getAttribute("xpath");
  System.out.println(xpath);
 }
}

10 个答案:

答案 0 :(得分:22)

您也可以使用它来爬行并生成xpath:

使用

调用以下方法
generateXPATH(element, "");

输出类似于:

/html[1]/body[1]/div[5]/div[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/form[1]/div[2]/div[1]/input[2]

方法

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

答案 1 :(得分:8)

你提出的问题对我没有任何意义。我想你可能有充分理由“想要这样做”!

您的代码行

 String xpath = driver.findElement(By.name(test)).getAttribute("xpath");

不会返回任何内容,因为html元素中没有属性'xpath'。请明确了解xpath的含义?

如果我有一个html元素,如下所示

<input name = "username" value = "Name" readonly ="readonly">

我可以使用

获取属性的值
driver.findElement(By.name("username").getAttribute("value");  // returns 'Name'

这会给我'value'属性的值

driver.findElement(By.name("username").getAttribute("readonly");  // returns 'readonly'

与上述相同!

答案 2 :(得分:7)

元素的XPath不是确定值。许多XPath都可以找到一个元素。

您无法使用Webdriver提取XPath,即使可以,也不可能是最有效或最明智的,只能由自动机定义。

答案 3 :(得分:2)

您可以使用JavaScript生成xpath:

function getPathTo(element) {

    // only generate xpaths for elements which contain a particular text:
    if (element.innerText == "MakeGoodDisabled-Programwise_09_44_38_461(n)") {

        // use id to produce relative paths rather than absolute, whenever possible
        if ((element.id !== '') && (element.id != 'undefined')) {
            return 'id(\"' + element.id + '\")';
        }

        // stop looping when you get to the body tag
        if (element === document.body) {
            return element.tagName;
        }

        // calculate position among siblings
        var ix = 0; 
        var siblings = element.parentNode.childNodes;
        for (var i = 0; i < siblings.length; i++) {
            var sibling = siblings[i];
            if (sibling === element) {
                return getPathTo(element.parentNode) + '/' + element.tagName + '[' + (ix + 1) + ']';
            }
            if (sibling.nodeType === 1 && sibling.tagName === element.tagName) {
                ix++;
            }
        }
    }
}

// put all matching xpaths in an array
var allXPaths = []; 

// if you know the particular tag you are looking for, replace * below to optimize 
var allTags = document.getElementsByTagName('*');
for (i = 0; i < allTags.length; i++) {
    if ((getPathTo(allTags[i]).indexOf('/HEAD') == -1) && (getPathTo(allTags[i]).indexOf('undefined') == -1)) {
        allXPaths.push(getPathTo(allTags[i]));
        console.log(getPathTo(allTags[i]));
    }
}
return allXPaths;

如果你把这个JavaScript放在一个名为getXPaths的字符串中然后在Java中,你就可以像这样执行它:

ArrayList<String> xpaths = (ArrayList<String>) js.executeScript(getXPaths);

它返回一个数组而不是String,因为如果你的页面恰好有更少或更多匹配了tagname / innerText的元素,你就会想知道。你可以通过数组的大小来判断。

答案 4 :(得分:1)

假设您的元素上有一个名为“xpath”的属性,您可以执行以下操作:

WebElement yourElement = driver.findElement(By.xpath("//td[contains(text(),'MakeGoodDisabled-Programwise_09_44_38_461(n)')]");
String xpathAttributeValue = targetButton.getAttribute("xpath");

虽然通过它的声音,你正试图在这里实现其他目的,但你尚未与我们分享。你想让selenium为你创建一个xpath吗?它不能。

答案 5 :(得分:1)

  

我的目的是在表格中找到一个文本并获取相应的下一列值   同一排。我以为我将替换通过获取xpath找到的列号   我想要的列号。有更好的方法吗

当然有办法。这是一种可能的解决方案。

获取所有行:

While (iterate over row)
     While(Iterate over column)
           if(column.Text=='YOUR_MATCH'){
             int voila=column.Index
           }
    }
}

现在您可以简单地移动到其他行的特定索引;或者您可以使用像.../tr/td[voila]这样的xpath来检索该特定列的所有单元格。

我写了一个方法,请不要把它当作实际工作代码!

答案 6 :(得分:1)

对我来说几乎是一样的情况:

我在表中有一个元素,但我不知道它位于哪一列(就像所有用户名中的一些用户名)。我需要找到带有用户名的特定字符串,然后单击“激活”按钮。 (用户名文本位于第2列,即td [2],按钮位于第5列,即td [5])。所以我需要逐个运行所有列来查找用户,然后单击它的按钮:

for (int iter = 1;; iter++) {
                try {
                    if (iter == 1) {
                            if ((username).equals(driver.findElement(By.xpath("/html/body/div[3]/div[4]/div/form/table/tbody/tr/td[2]/a")).getText())) {
                                driver.findElement(By.xpath("/html/body/div[3]/div[4]/div/form/table/tbody/tr/td[5]/a")).click();
                                break;
                            }
                    }
                } catch (Error e) {}
                try {
                    if (iter > 1) {
                            if ((username).equals(driver.findElement(By.xpath("/html/body/div[3]/div[4]/div/form/table/tbody/tr[" + iter + "]/td[2]/a")).getText())) {
                                driver.findElement(By.xpath("/html/body/div[3]/div[4]/div/form/table/tbody/tr[" + iter + "]/td[5]/a")).click();
                                break;
                            }
                        }
                    } catch (Error e) {}
                } 
          }

答案 7 :(得分:1)

在迭代之前,请使用此类。然后,当你找到XPATHIDFromWebElement

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

public class XPATHDriverWrapper {
Map xpathIDToWebElementMap = new LinkedHashMap();
Map webElementToXPATHIDMap = new LinkedHashMap();
public XPATHDriverWrapper(WebDriver driver){
    WebElement htmlElement = driver.findElement(By.xpath("/html"));
    iterateThroughChildren(htmlElement, "/html");
}

private void iterateThroughChildren(WebElement parentElement, String parentXPATH) {
    Map siblingCountMap = new LinkedHashMap();

    List childrenElements = parentElement.findElements(By.xpath(parentXPATH+"/*"));
    for(int i=0;i<childrenElements.size(); i++) {
        WebElement childElement = childrenElements.get(i);
        String childTag = childElement.getTagName();
        String childXPATH = constructXPATH(parentXPATH, siblingCountMap, childTag);
        xpathIDToWebElementMap.put(childXPATH, childElement);
        webElementToXPATHIDMap.put(childElement, childXPATH);
        iterateThroughChildren(childElement, childXPATH);
//          System.out.println("childXPATH:"+childXPATH);
    }
}

public WebElement findWebElementFromXPATHID(String xpathID) {
    return xpathIDToWebElementMap.get(xpathID);
}

public String findXPATHIDFromWebElement(WebElement webElement) {
    return webElementToXPATHIDMap.get(webElement);
}

private String constructXPATH(String parentXPATH,
        Map siblingCountMap, String childTag) {
    Integer count = siblingCountMap.get(childTag);
    if(count == null) {
        count = 1;
    } else {
        count = count + 1;
    }
    siblingCountMap.put(childTag, count);
    String childXPATH = parentXPATH + "/" + childTag + "[" + count + "]";
    return childXPATH;
}
}

另一个从Document生成ID的包装类发布在:http://scottizu.wordpress.com/2014/05/12/generating-unique-ids-for-webelements-via-xpath/

答案 8 :(得分:1)

我认为它们不是用于获取搜索元素的xpath的任何特殊函数。为此,首先需要手动查找元素,然后通过getXpath函数获取xpath。

答案 9 :(得分:1)

我的获取绝对xpath的java方法:

public static String getXpath(WebElement element){
    int n = element.findElements(By.xpath("./ancestor::*")).size();
    String path = "";
    WebElement current = element;
    for(int i = n; i > 0; i--){
        String tag = current.getTagName();
        int lvl = current.findElements(By.xpath("./preceding-sibling::" + tag)).size() + 1;
        path = String.format("/%s[%d]%s", tag, lvl, path);
        current = current.findElement(By.xpath("./parent::*"));
    }
    return "/" + current.getTagName() + path;
}

和相对xpath(这是第一个:)):

public static String getXpath(WebElement self, WebElement ancestor){
    int a = ancestor.findElements(By.xpath("./ancestor::*")).size();
    int s = self.findElements(By.xpath("./ancestor::*")).size();
    String path = "";
    WebElement current = self;
    for(int i = s - a; i > 0; i--){
        String tag = current.getTagName();
        int lvl = current.findElements(By.xpath("./preceding-sibling::" + tag)).size() + 1;
        path = String.format("/%s[%d]%s", tag, lvl, path);
        current = current.findElement(By.xpath("./parent::*"));
    }
    return path;
}