Есть ли способ получить элемент с помощью XPath, используя JavaScript в Selenium WebDriver?
Я ищу что-то вроде:
getElementByXpath(//html[1]/body[1]/div[1]).innerHTML
Мне нужно получить innerHTML элементов с использованием JS (чтобы использовать это в Selenium WebDriver/Java, поскольку WebDriver не может найти его сам), но как?
Я мог бы использовать атрибут ID, но не все элементы имеют атрибут ID.
[ФИКСИРОВАННЫЙ]
Я использую jsoup, чтобы сделать это на Java. Это работает для моих нужд.
12 ответов
Ты можешь использовать 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
В Chrome Dev Tools вы можете запустить следующее:
$x("some xpath")
Чтобы идентифицировать WebElement с помощью xpath и javascript, вы должны использовать evaluate()
метод, который оценивает выражение xpath и возвращает результат.
document.evaluate()
document.evaluate() возвращает XPathResult на основе выражения XPath и других заданных параметров.
Синтаксис:
var xpathResult = document.evaluate(
xpathExpression,
contextNode,
namespaceResolver,
resultType,
result
);
Где:
xpathExpression
: Строка, представляющая XPath для оценки.contextNode
: Задает контекстный узел для запроса. Обычная практика - пройтиdocument
в качестве узла контекста.namespaceResolver
: Функция, которая будет передавать любые префиксы пространства имен и должна возвращать строку, представляющую URI пространства имен, связанный с этим префиксом. Он будет использоваться для разрешения префиксов в самом XPath, чтобы их можно было сопоставить с документом.null
является обычным для документов HTML или когда не используются префиксы пространства имен.resultType
: Целое число, которое соответствует типу результата XPathResult, возвращаемого с использованием свойств именованных констант, таких какXPathResult.ANY_TYPE
конструктора XPathResult, которые соответствуют целым числам от 0 до 9.result
: Существующий XPathResult для использования в результатах.null
является наиболее распространенным и создаст новый XPathResult
Демонстрация
Например, поле поиска на главной странице Google, которое можно однозначно идентифицировать с помощью xpath как//*[@name='q']
также можно определить с помощью консоли google-chrome-devtools с помощью следующей команды:
$x("//*[@name='q']")
Снимок:
Этот же элемент можно также идентифицировать с помощью document.evaluate()
и выражение xpath следующим образом:
document.evaluate("//*[@name='q']", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
Снимок:
Для чего-то вроде $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
Хотя во многих браузерах
$x(xPath)
в качестве встроенной консоли, вот совокупность полезных, но жестко запрограммированных фрагментов из Введение в использование XPath в JavaScript, готовых для использования в сценариях:
Снимок
Это дает одноразовый снимок набора результатов xpath. Данные могут быть устаревшими после мутаций DOM.
Вы можете использовать document.evaluate javascript для запуска выражения 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
Чтобы перейти к делу, вы можете легко использовать 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
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");
}
}
Убедитесь, что вы используете правильный локатор для него.
Предполагая, что вашей целью является разработка и тестирование ваших запросов xpath для экранных карт. Затем используйте инструменты разработчика Chrome. Это позволяет вам выполнить запрос xpath, чтобы показать совпадения. Или в Firefox >9 вы можете сделать то же самое с консолью Web Developer Tools. В более ранней версии используйте x-path-finder или Firebug.
**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
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);