¿Hay alguna manera de obtener elementos mediante XPath usando JavaScript en Selenium WebDriver?

252

Estoy buscando algo como:

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

Necesito obtener el innerHTML de elementos usando JS (para usar eso en Selenium WebDriver / Java, ya que WebDriver no puede encontrarlo por sí mismo), pero ¿cómo?

Podría usar el atributo ID, pero no todos los elementos tienen un atributo ID.

[FIJO]

Estoy usando jsoup para hacerlo en Java. Eso funciona para mis necesidades.

pMan
fuente
2
Por cierto, los selectores htmly bodyson superfluos ya que un DIV debe ser un descendiente de BODY (inmediato o más profundo) y BODY debe ser un hijo de HTML, por lo que siempre que no haya otros elementos DIV en el documento, //DIV[1]debería funcionar (aunque soy bastante oxidado en expresiones XPath). El equivalente DOM es document.getElementsByTagName('div')[1](o tal vez 0).
RobG

Respuestas:

422

Puedes usar document.evaluate:

Evalúa una cadena de expresión XPath y devuelve un resultado del tipo especificado si es posible.

Está estandarizado con w3 y está completamente documentado: 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

También hay una gran introducción sobre la red de desarrolladores de mozilla: https://developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript#document.evaluate


Versión alternativa, usando XPathEvaluator:

yckart
fuente
11
¿Qué significa el número mágico 9? Sería mejor usar una constante con nombre aquí.
Will Sheppard
55
@WillSheppard XPathResult.FIRST_ORDERED_NODE_TYPE === 9 developer.mozilla.org/en-US/docs/…
yckart
2
Escribí una función getElementByXPath que tiene soporte para IE pero algo de soporte básico de xpath por ahora. También hay una función getElementXpath allí y funcionan muy bien juntos para lo que necesitaba. gist.github.com/Joopmicroop/10471650
joopmicroop
var xpathResult = document.evaluate (xpathExpression, contextNode, namespaceResolver, resultType, result);
TechDog
167

En Chrome Dev Tools puedes ejecutar lo siguiente:

$x("some xpath")
Dmitry Semenyuk
fuente
1
He jugado con esto y parece funcionar, pero ¿hay alguna documentación para esta función? No encontré nada.
Eric
Esto necesita estar más arriba. Firefox también lo admite.
iSWORD el
Esto es muy útil cuando está depurando su página web. Gracias.
theeranitp
21

Para algo como $ x desde la línea de comandos de Chrome API (para seleccionar varios elementos) intente:

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

Esta descripción general de MDN ayudó a: https://developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript

Arrendajo
fuente
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");
    }
}

Asegúrese de estar utilizando el localizador adecuado para ello.

Prerit Jain
fuente
1
Hola Prerit, la pregunta era seleccionar por un elemento basado en su xpath. La solución que ha proporcionado es seleccionarlo por la identificación. :)
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
fuente
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
fuente
agregue una respuesta descriptiva. Su descripción ayudará al interlocutor a comprender su solución rápidamente.
NickCoder
0

Para ir directo al grano, puede usar fácilmente xapth. La forma exacta y simple de hacerlo usando el código a continuación. Intente amablemente y envíe sus comentarios. Gracias.

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

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

Sameera De Silva
fuente
Creo que el OP no solicitó una solución de selenio como la suya, ¿correcto?
Ankostis