Найти элемент по тексту и получить xpath - selenium webdriver junit

У меня есть таблица с 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);
 }
}

Ответ 1

Мое намерение состоит в том, чтобы найти текст в таблице и получить соответствующее значение следующего столбца в той же строки. Я думал, что я заменил номер столбца, найденный путем выбора xpath с помощью номер столбца, который я хочу. есть лучший способ сделать это

Конечно, есть способ. Вот одно из возможных решений.

Получить все строки:

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

Теперь вы можете просто перейти к этому конкретному индексу для других строк; или вы можете использовать xpath как .../tr/td[voila] для извлечения всех ячеек для этого конкретного столбца.

Я написал подход, пожалуйста, не делайте реальный рабочий код!

Ответ 2

Вы также можете использовать это для обхода и создания 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;
}

Ответ 3

Вопрос, который вы задали, не имеет для меня никакого смысла. Я предполагаю, что может быть веская причина для вас "хотеть сделать это"!

Ваша строка кода

 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'

как указано выше!

Ответ 4

XPath элемента не является окончательным значением. Элемент может быть найден многими XPaths.

Вы не можете использовать Webdriver для извлечения XPath, и даже если бы это было возможно, это вряд ли будет самым эффективным или разумным, что может быть определено только автомаром.

Ответ 5

Вы можете создавать xpath с помощью JavaScript:

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 в String под названием getXPaths, а затем в Java, вы можете выполнить его следующим образом:

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

Он возвращает массив, а не строку, потому что, если на вашей странице будет меньше или больше элементов с соответствующим тэгом /innerText, вы захотите узнать. Вы можете определить размер массива.

Ответ 6

JavaScript fnction для генерации XPath

XPath/locator - это способ обращения к элементу путем навигации по структуре дерева.

Абсолютный XPath (/):/html/body/div [5]/div [4]

WebElement XPath:

function WebElement_XPath(element) {
    if (element.tagName == 'HTML')    return '/html';
    if (element===document.body)      return '/html/body';

    // calculate position among siblings
    var position = 0;
    // Gets all siblings of that element.
    var siblings = element.parentNode.childNodes;
    for (var i = 0; i < siblings.length; i++) {
        var sibling = siblings[i];
        // Check Siblink with our element if match then recursively call for its parent element.
        if (sibling === element)  return WebElement_XPath(element.parentNode)+'/'+element.tagName+'['+(position+1)+']';

       // if it is a siblink & element-node then only increments position. 
        var type = sibling.nodeType;
        if (type === 1 && sibling.tagName === element.tagName)            position++;
    }
}

MouseEvent XPath:

var eventXPath = '';
function MouseEvent_XPath(e) {      
    event = e.target || e.srcElement ||e.originalTarget;

    for ( var xpathEle = ''; event && event.nodeType == 1; event = event.parentNode ) {
        if ( event.tagName == 'HTML' || event.tagName == 'html' ) {
            eventXPath = '//html'+xpathEle;         break;
        }     
        if ( event.tagName == 'BODY' || event.tagName == 'body' ) {
            eventXPath = '//html/body'+xpathEle;    break;
        }     

        // calculate position among siblings
        var position = 0;
        // Gets all siblings of that event.
        var siblings = event.parentNode.children;
        for (var i = 0; i < siblings.length; i++) {
            var sibling = siblings[i];
        // Check Sibling with our event if match then recursively call for its parent event.
            if (sibling === event)  xpathEle = "/"+event.tagName+'['+(position+1)+']'+xpathEle;

           // if it is a sibling with same tagName then only increments position. 
            if (sibling.tagName === event.tagName)            position++;
        }
    }
}

Относительный xpath (//)://div [@id = social-media]/ul/li [3]/a

//Element.TagName [@id = "idvalue" и @class= "classValue" и text() = "innerHTML data" ] ИЛИ вы можете использовать. (Точка),. является псевдонимом для text(), [. = "innerHTML data" ], если вы знаете, что контент, который вы ищете, находится где-то внутри указанного тега, вы можете использовать этот

Пример запуска в консоли:

var xpath  = "//div[@id='answer-32201731' and @data-answerid='32201731']";
var element = document.evaluate(xpath, window.document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue;
element.style.setProperty( 'outline', "3px solid blue","important");

Ответ 7

Мой метод Java для получения абсолютного xpath:

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

Ответ 8

Предполагая, что у вас есть атрибут вашего элемента с именем "xpath", вы можете сделать следующее:

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

Хотя по звукам вы пытаетесь достичь чего-то еще, вы еще не делились с нами. Вы хотите, чтобы селен создал xpath для вас? Он не может.

Ответ 9

Почти такая же ситуация для меня:

У меня есть элемент в таблице, но я не знаю, в каком столбце он находится (например, какое-то имя пользователя по всем именам пользователей). Мне нужно найти определенную строку с именем пользователя и нажать кнопку "активировать" только для этого пользователя. (текст имени пользователя находится во втором столбце, который является td [2], и кнопка находится в пятом столбце, который является 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) {}
                } 
          }

Ответ 10

Перед повторным использованием используйте этот класс. Затем, когда вы найдете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;
}
}

Другой класс-оболочка для создания идентификаторов из документа размещен по адресу: http://scottizu.wordpress.com/2014/05/12/generating-unique-ids-for-webelements-via-xpath/

Ответ 11

Я думаю, что это не какая-либо специальная функция, доступная для получения xpath искомого элемента. Для этого сначала вам нужно найти элемент вручную, затем получить xpath через функции getXpath.