Czy istnieje sposób na uzyskanie elementu przez XPath przy użyciu JavaScript w Selenium WebDriver?

252

Szukam czegoś takiego:

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

Potrzebuję uzyskać innerHTML elementów za pomocą JS (aby użyć go w Selenium WebDriver / Java, ponieważ WebDriver nie może go znaleźć), ale jak?

Mógłbym użyć atrybutu ID, ale nie wszystkie elementy mają atrybut ID.

[NAPRAWIONY]

Używam jsoup, aby zrobić to w Javie. To działa na moje potrzeby.

pMan
źródło
2
Nawiasem mówiąc, selektory htmli bodysą zbędne, ponieważ DIV musi być potomkiem BODY (natychmiastowego lub głębszego), a BODY musi być dzieckiem HTML, więc pod warunkiem, że nie ma innych elementów DIV w dokumencie, //DIV[1]powinien działać (chociaż jestem ładna zardzewiały na wyrażeniach XPath). Odpowiednikiem DOM jest document.getElementsByTagName('div')[1](a może 0).
RobG

Odpowiedzi:

422

Możesz użyć document.evaluate:

Oblicza ciąg wyrażenia XPath i, jeśli to możliwe, zwraca wynik określonego typu.

Jest standaryzowany w3 i w pełni udokumentowany: 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

Jest także świetne wprowadzenie do sieci deweloperów Mozilli: https://developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript#document.evaluate


Alternatywna wersja, wykorzystująca XPathEvaluator:

yckart
źródło
11
Co oznacza magiczna liczba 9? Lepiej byłoby użyć tutaj nazwanej stałej.
Will Sheppard,
5
@WillSheppard XPathResult.FIRST_ORDERED_NODE_TYPE === 9 developer.mozilla.org/en-US/docs/…
yckart
2
Napisałem funkcję getElementByXPath, która obsługuje IE, ale na razie podstawową obsługę xpath. Jest tam również funkcja getElementXpath i działają one ładnie razem dla tego, czego potrzebowałem. gist.github.com/Joopmicroop/10471650
joopmicroop
@CiroSantilli Tak, proszę pana, to jest: w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathEvaluator-evaluate
yckart
var xpathResult = document.evaluate (xpathExpression, contextNode, namespaceResolver, resultType, wynik);
TechDog,
167

W Chrome Dev Tools możesz uruchomić:

$x("some xpath")
Dmitrij Semenyuk
źródło
1
Grałem z tym i wydaje się, że działa, ale czy jest jakaś dokumentacja dla tej funkcji? Niczego nie znalazłem.
Eric
To musi być wyżej. Firefox też to obsługuje.
iSWORD,
Jest to bardzo przydatne podczas debugowania strony internetowej. Dzięki.
theeranitp
21

Aby uzyskać coś takiego jak $ x z interfejsu wiersza polecenia chrome (aby wybrać wiele elementów), spróbuj:

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

Omówienie MDN pomogło: https://developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript

Sójka
źródło
9

Możesz użyć document.evaluate w javascript, aby uruchomić wyrażenie XPath w DOM. Myślę, że jest obsługiwany w taki czy inny sposób w przeglądarkach z powrotem do IE 6.

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

Zamiast tego IE obsługuje selectNodes .

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

RobG
źródło
7
Chciałbym zauważyć, że {document.evaluate} nie działa w IE.
Christopher Bales
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");
    }
}

Upewnij się, że używasz do tego odpowiedniego lokalizatora.

Prerit Jain
źródło
1
Cześć Prerit, pytanie polegało na wybraniu elementu na podstawie jego ścieżki x. Podane rozwiązanie polega na wybraniu go według identyfikatora. :)
Gaurav Thantry
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
Alok Patel
źródło
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);
Dharit Mehta
źródło
dodaj opisową odpowiedź. Twój opis pomoże pytającemu szybko zrozumieć twoje rozwiązanie.
NickCoder,
0

Aby przejść do rzeczy, możesz łatwo użyć xapth. Dokładny i prosty sposób na zrobienie tego za pomocą poniższego kodu. Prosimy postarać się o opinie. Dziękuję.

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']")));

Dalsze odczyty - https://medium.com/@smeesheady/webdriver-javascriptexecutor-interact-with-elements-and-open-and-handle-multiple-tabs-and-get-url-dcfda49bfa0f

Sameera De Silva
źródło
Uważam, że OP nie poprosił o rozwiązanie Selenium takie jak twoje, prawda?
ankostis