Existe-t-il un moyen d'obtenir l'élément par XPath en utilisant JavaScript dans Selenium WebDriver?

252

Je cherche quelque chose comme:

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

J'ai besoin d'obtenir le innerHTML des éléments en utilisant JS (pour l'utiliser dans Selenium WebDriver / Java, car WebDriver ne le trouve pas lui-même), mais comment?

Je pourrais utiliser l'attribut ID, mais tous les éléments n'ont pas d'attribut ID.

[FIXÉ]

J'utilise jsoup pour le faire en Java. Cela fonctionne pour mes besoins.

pMan
la source
2
Soit dit en passant, les sélecteurs htmlet bodysont superflus car un DIV doit être un descendant de BODY (immédiat ou plus profond) et BODY doit être un enfant de HTML, donc à condition qu'il n'y ait pas d'autres éléments DIV dans le document, //DIV[1]devrait fonctionner (bien que je sois assez rouillé sur les expressions XPath). L'équivalent DOM est document.getElementsByTagName('div')[1](ou peut-être 0).
RobG

Réponses:

422

Vous pouvez utiliser document.evaluate:

Évalue une chaîne d'expression XPath et renvoie si possible un résultat du type spécifié.

Il est normalisé w3 et entièrement documenté: 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

Il y a aussi une excellente introduction sur le réseau de développeurs mozilla: https://developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript#document.evaluate


Version alternative, utilisant XPathEvaluator:

yckart
la source
11
Que signifie le chiffre magique 9? Il serait préférable d'utiliser une constante nommée ici.
Will Sheppard
5
@WillSheppard XPathResult.FIRST_ORDERED_NODE_TYPE === 9 developer.mozilla.org/en-US/docs/…
yckart
2
J'ai écrit une fonction getElementByXPath qui prend en charge IE mais une prise en charge de base de xpath pour l'instant. Il y a aussi une fonction getElementXpath là-dedans et ils fonctionnent bien ensemble pour ce dont j'avais besoin. gist.github.com/Joopmicroop/10471650
joopmicroop
@CiroSantilli Oui monsieur, c'est: w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathEvaluator-evaluate
yckart
var xpathResult = document.evaluate (xpathExpression, contextNode, namespaceResolver, resultType, result);
TechDog
167

Dans Chrome Dev Tools, vous pouvez exécuter les éléments suivants:

$x("some xpath")
Dmitry Semenyuk
la source
1
J'ai joué avec cela et cela semble fonctionner, mais existe-t-il une documentation pour cette fonctionnalité? Je n'ai rien trouvé.
Eric
Cela doit être plus haut. Firefox le prend également en charge.
iSWORD
Ceci est très utile lorsque vous déboguez votre page Web. Merci.
theeranitp
21

Pour quelque chose comme $ x de l'API de ligne de commande Chrome (pour sélectionner plusieurs éléments), essayez:

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

Cette présentation MDN a aidé: https://developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript

Geai
la source
9

Vous pouvez utiliser le document.evaluate de javascript pour exécuter une expression XPath sur le DOM. Je pense qu'il est pris en charge d'une manière ou d'une autre dans les navigateurs de retour à IE 6.

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

IE prend plutôt en charge selectNodes .

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

RobG
la source
7
Je voudrais noter que {document.evaluate} ne fonctionne pas dans IE.
Christopher Bales du
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");
    }
}

Assurez-vous que vous utilisez le bon localisateur pour cela.

Prerit Jain
la source
1
Salut Prerit, la question était de sélectionner par un élément en fonction de son xpath. La solution que vous avez fournie consiste à le sélectionner par l'identifiant. :)
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
la source
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
la source
ajoutez une réponse descriptive. votre description aidera l'interrogateur à comprendre rapidement votre solution.
NickCoder
0

Pour aller droit au but, vous pouvez facilement utiliser xapth .La manière exacte et simple de le faire en utilisant le code ci-dessous. Veuillez essayer de fournir des commentaires .Merci.

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

Lectures supplémentaires - https://medium.com/@smeesheady/webdriver-javascriptexecutor-interact-with-elements-and-open-and-handle-multiple-tabs-and-get-url-dcfda49bfa0f

Sameera De Silva
la source
Je pense que le PO n'a pas demandé une solution de sélénium comme la vôtre, n'est-ce pas?
ankostis