355

我正在寻找类似的东西:

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

我需要使用 JS 获取元素的 innerHTML(在 Selenium WebDriver/Java 中使用它,因为 WebDriver 本身无法找到它),但是如何?

我可以使用 ID 属性,但并非所有元素都有 ID 属性。

[固定的]

我正在使用 jsoup 在 Java 中完成它。这适合我的需要。

4

11 回答 11

592

您可以使用document.evaluate

如果可能,计算 XPath 表达式字符串并返回指定类型的结果。

它是w3-standardized和完整记录的: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

function getElementByXPath(xpath) {
  return new XPathEvaluator()
    .createExpression(xpath)
    .evaluate(document, XPathResult.FIRST_ORDERED_NODE_TYPE)
    .singleNodeValue
}

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

于 2013-01-11T18:54:11.327 回答
236

在 Chrome 开发工具中,您可以运行以下命令:

$x("some xpath")
于 2013-12-12T09:21:47.340 回答
29

对于来自 chrome 命令行 api 的 $x 之类的东西(选择多个元素),请尝试:

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

于 2014-06-20T16:55:27.590 回答
16

要使用识别WebElement ,您必须使用评估xpath表达式并返回结果的方法。evaluate()


document.evaluate()

document.evaluate()根据XPath表达式和其他给定参数返回XPathResult 。

语法是:

var xpathResult = document.evaluate(
  xpathExpression,
  contextNode,
  namespaceResolver,
  resultType,
  result
);

在哪里:

  • xpathExpression:表示要评估的 XPath 的字符串。
  • contextNode:指定查询的上下文节点。通常的做法是document作为上下文节点传递。
  • namespaceResolver:将传递任何命名空间前缀的函数,并应返回一个字符串,该字符串表示与该前缀关联的命名空间 URI。它将用于解析 XPath 本身内的前缀,以便它们可以与文档匹配。null对于 HTML 文档或不使用命名空间前缀时很常见。
  • resultType: 一个整数,对应于使用命名常量属性返回的结果 XPathResult 的类型,例如XPathResult.ANY_TYPEXPathResult 构造函数的,对应于从 0 到 9 的整数。
  • result:用于结果的现有 XPathResult。null是最常见的,将创建一个新的 XPathResult

示范

例如,可以使用xpath唯一标识的Google 主页中的搜索框,也可以使用控制台通过以下命令进行标识://*[@name='q']

$x("//*[@name='q']")

快照:

googlesearchbox_xpath

也可以使用xpathdocument.evaluate()表达式来识别相同的元素,如下所示:

document.evaluate("//*[@name='q']", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

快照:

document_evalute_xpath

于 2020-07-26T23:37:29.827 回答
11

您可以使用 javascript 的document.evaluate在 DOM 上运行 XPath 表达式。我认为它在浏览器中以一种或另一种方式支持到 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

于 2012-05-15T09:05:16.683 回答
7

直截了当,您可以轻松地使用 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

于 2019-12-18T15:43:47.110 回答
3

尽管许多浏览器都$x(xPath)内置了控制台,但这里汇总了从Introduction 到在 JavaScript 中使用 XPath准备在脚本中使用的有用但硬编码的片段:

快照

这给出了 xpath 结果集的一次性快照。DOM 突变后数据可能会过时。

const $x = xp => {
  const snapshot = document.evaluate(
    xp, document, null, 
    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null
  );
  return [...Array(snapshot.snapshotLength)]
    .map((_, i) => snapshot.snapshotItem(i))
  ;
};

console.log($x('//h2[contains(., "foo")]'));
<h2>foo</h2>
<h2>foobar</h2>
<h2>bar</h2>

第一个有序节点

const $xOne = xp => 
  document.evaluate(
    xp, document, null,
    XPathResult.FIRST_ORDERED_NODE_TYPE, null
  ).singleNodeValue
;

console.log($xOne('//h2[contains(., "foo")]'));
<h2>foo</h2>
<h2>foobar</h2>
<h2>bar</h2>

迭代器

但是请注意,如果文档在迭代之间发生突变(文档树被修改),这将使迭代无效,并且 的invalidIteratorState属性XPathResult设置为true,并NS_ERROR_DOM_INVALID_STATE_ERR引发异常。

function *$xIter(xp) {
  const iter = document.evaluate(
    xp, document, null, 
    XPathResult.ORDERED_NODE_ITERATOR_TYPE, null
  );

  for (;;) {
    const node = iter.iterateNext();
    
    if (!node) {
      break;
    }
    
    yield node;
  }
}

// dump to array
console.log([...$xIter('//h2[contains(., "foo")]')]);

// return next item from generator
const xpGen = $xIter('//h2[text()="foo"]');
console.log(xpGen.next().value);
<h2>foo</h2>
<h2>foobar</h2>
<h2>bar</h2>

于 2021-07-01T20:49:36.747 回答
2

假设您的目标是开发和测试屏幕地图的 xpath 查询。然后要么使用Chrome 的开发者工具。这允许您运行 xpath 查询以显示匹配项。或者在 Firefox >9 中,您可以使用Web Developer Tools 控制台执行相同的操作。在早期版本中使用x-path-finderFirebug

于 2012-05-15T11:51:43.513 回答
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");
    }
}

确保您使用正确的定位器。

于 2017-02-24T06:17:45.700 回答
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
于 2019-04-12T06:15:15.737 回答
1
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);
于 2019-09-11T11:56:00.843 回答