Есть ли способ получить элемент с помощью XPath, используя JavaScript в Selenium WebDriver?

252

Я ищу что-то вроде:

getElementByXpath(//html[1]/body[1]/div[1]).innerHTML

Мне нужно получить innerHTML элементов с использованием JS (чтобы использовать это в Selenium WebDriver / Java, поскольку WebDriver не может найти его сам), но как?

Я мог бы использовать атрибут ID, но не все элементы имеют атрибут ID.

[ФИКСИРОВАННЫЙ]

Я использую jsoup, чтобы сделать это на Java. Это работает для моих нужд.

pMan
источник
2
Кстати, htmlи bodyселекторы излишни так как DIV должен быть потомком ТЕЛА (непосредственным или глубже) и тело должно быть ребенком HTML, поэтому при условии , нет никаких других элементов DIV в документе, //DIV[1]должны работать (хотя я довольно ржавый на XPath выражениях). Эквивалент DOM есть document.getElementsByTagName('div')[1](или может быть 0).
RobG

Ответы:

423

Вы можете использовать document.evaluate:

Оценивает строку выражения XPath и возвращает результат указанного типа, если это возможно.

Он стандартизирован по w3 и полностью документирован: https://developer.mozilla.org/en-US/docs/Web/API/Document.evaluate.

function getElementByXpath(path) {
  return document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}

console.log( getElementByXpath("//html[1]/body[1]/div[1]") );
<div>foo</div>

https://gist.github.com/yckart/6351935

В сети разработчиков Mozilla также есть отличное введение: https://developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript#document.evaluate.


Альтернативная версия, используя XPathEvaluator:

yckart
источник
11
Что означает магическое число 9? Было бы лучше использовать именованную константу здесь.
Уилл Шеппард
5
@WillSheppard XPathResult.FIRST_ORDERED_NODE_TYPE === 9 developer.mozilla.org/en-US/docs/...
yckart
2
Я написал функцию getElementByXPath, которая поддерживает IE, но на данный момент имеет некоторую базовую поддержку xpath. Там также есть функция getElementXpath, и они прекрасно работают вместе для того, что мне нужно. gist.github.com/Joopmicroop/10471650
joopmicroop
@CiroSantilli Да, сэр, это: w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathEvaluator-evaluate
yckart
var xpathResult = document.evaluate (xpathExpression, contextNode, namespaceResolver, resultType, result);
TechDog
168

В Chrome Dev Tools вы можете запустить следующее:

$x("some xpath")
Дмитрий Семенюк
источник
1
Я поиграл с этим, и это, кажется, работает, но есть ли документация для этой функции? Я ничего не нашел.
Эрик
Это должно быть выше. Firefox тоже это поддерживает.
ISWORD
Это очень полезно, когда вы отлаживаете свою веб-страницу. Спасибо.
theeranitp
@Eric Документация: developers.google.com/web/tools/chrome-devtools/console/…
rybo111
21

Для чего-то вроде $ x из api командной строки chrome (для выбора нескольких элементов) попробуйте:

var xpath = function(xpathToExecute){
  var result = [];
  var nodesSnapshot = document.evaluate(xpathToExecute, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
  for ( var i=0 ; i < nodesSnapshot.snapshotLength; i++ ){
    result.push( nodesSnapshot.snapshotItem(i) );
  }
  return result;
}

Этот обзор MDN помог: https://developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript

сойка
источник
9

Вы можете использовать документ document.evaluate для запуска выражения XPath в DOM. Я думаю, что это поддерживается так или иначе в браузерах до IE 6.

MDN: https://developer.mozilla.org/en-US/docs/Web/API/Document/evaluate

IE поддерживает selectNodes вместо этого.

MSDN: https://msdn.microsoft.com/en-us/library/ms754523(v=vs.85).aspx

RobG
источник
7
Я хотел бы отметить, что {document.evaluate} не работает в IE.
Кристофер Бейлс
2

Предполагая, что вашей целью является разработка и тестирование ваших запросов xpath для экранных карт. Затем используйте инструменты разработчика Chrome . Это позволяет вам выполнить запрос xpath, чтобы показать совпадения. Или в Firefox> 9 вы можете сделать то же самое с консолью Web Developer Tools . В более ранней версии используйте x-path-finder или Firebug .

Мартин Спамер
источник
2
public class JSElementLocator {

    @Test
    public void locateElement() throws InterruptedException{
        WebDriver driver = WebDriverProducerFactory.getWebDriver("firefox");

        driver.get("https://www.google.co.in/");


        WebElement searchbox = null;

        Thread.sleep(1000);
        searchbox = (WebElement) (((JavascriptExecutor) driver).executeScript("return document.getElementById('lst-ib');", searchbox));
        searchbox.sendKeys("hello");
    }
}

Убедитесь, что вы используете правильный локатор для него.

Прерит джайн
источник
1
Привет Прерит, вопрос заключался в том, чтобы выбрать элемент на основе его xpath. Решение, которое вы предоставили, состоит в том, чтобы выбрать его по идентификатору. :)
Гаурав Тантри
2
**Different way to Find Element:**

IEDriver.findElement(By.id("id"));
IEDriver.findElement(By.linkText("linkText"));
IEDriver.findElement(By.xpath("xpath"));

IEDriver.findElement(By.xpath(".//*[@id='id']"));
IEDriver.findElement(By.xpath("//button[contains(.,'button name')]"));
IEDriver.findElement(By.xpath("//a[contains(.,'text name')]"));
IEDriver.findElement(By.xpath("//label[contains(.,'label name')]"));

IEDriver.findElement(By.xpath("//*[contains(text(), 'your text')]");

Check Case Sensitive:
IEDriver.findElement(By.xpath("//*[contains(lower-case(text()),'your text')]");

For exact match: 
IEDriver.findElement(By.xpath("//button[text()='your text']");

**Find NG-Element:**

Xpath == //td[contains(@ng-show,'childsegment.AddLocation')]
CssSelector == .sprite.icon-cancel
Алок Патель
источник
0
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

System.setProperty("webdriver.chrome.driver", "path of your chrome exe");
        WebDriver driver = new ChromeDriver();
        driver.manage().window().maximize();
        driver.get("https://www.google.com");

            driver.findElement(By.xpath(".//*[@id='UserName']")).clear();
            driver.findElement(By.xpath(".//*[@id='UserName']")).sendKeys(Email);
Дхарит Мехта
источник
добавить описательный ответ. Ваше описание поможет спрашивающему быстро понять ваше решение.
NickCoder
0

Чтобы перейти к сути, вы можете легко использовать xapth. Точный и простой способ сделать это с помощью приведенного ниже кода. Пожалуйста, попробуйте и оставить отзыв. Спасибо.

JavascriptExecutor js = (JavascriptExecutor) driver;

    //To click an element 
    WebElement element=driver.findElement(By.xpath(Xpath));
    js.executeScript(("arguments[0].click();", element);

    //To gettext

    String theTextIWant = (String) js.executeScript("return arguments[0].value;",driver.findElement(By.xpath("//input[@id='display-name']")));

Дальнейшие чтения - https://medium.com/@smeesheady/webdriver-javascriptexecutor-interact-with-elements-and-open-and-handle-multiple-tabs-and-get-url-dcfda49bfa0f

Самера Де Сильва
источник
Я полагаю, что ОП не просила решение Selenium, как ваше, правильно?
Анкостис