为元素创建 Selenium getText() 方法?

Creating a Selenium getText() method for an element?

我正在尝试创建一个 Selenium getText() 方法来获取节点文本或获取元素的节点+子文本。默认情况下,Selenium 行为似乎使用 Xpath .//string() 方法来获取文本并包括直接子项的文本。我想利用 XPath 的强大功能使我能够以更有针对性的方式获取文本。我的问题是:我是不是误解了这一点,还是有更好的方法来实现这一点?

public String getText(By locationOfText, boolean childText)
{
  By locator = null;
  if ( childText)
  {
    locator = ByChained( locationOfText, By.xpath(".//string()"));
  } else {
    locator = ByChained( locationOfText, By.xpath(".//text()"));
  }
  JavascriptExecutor jse = (JavascriptExecutor)driver;
  String elementText = jse.executeScript("document.evaluate(locator, document.body, null, 
     XPathResult.STRING_TYPE, null);");

  return elementText;
} 

这是一个 HTML 片段:

<h5 class="class-name clearfix">Inner Text
   <a class="info-link class-description" href="#">i</a>
</h5>

问题是当我使用 Selenium 进行这样的文本调用时,我得到文本 Inner Texti

driver.findElement(".//h5").getText();

我的期望是检索值 Inner Text 。通过创建上面的方法,我希望这样调用它:

String text = elementHelper.getText(By.xpath(".//h5"),false);

string() 是一个 XPath 2.0 结构,但大多数浏览器(如果不是全部)仅支持 XPath 1.0。此外,我不太喜欢急于使用 XPath 来查询 DOM 树。 XPath 评估具有显着的性能开销。所以adapting my answer here,我建议:

public String getText(By locationOfText, boolean childText)
{
  WebElement el = driver.findElement(locationOfText);
  if (childText)
  {
    return el.getText();
  }

  JavascriptExecutor jse = (JavascriptExecutor) driver;
  return jse.executeScript(
    "var parent = arguments[0]; "+
    "var child = parent.firstChild; "+
    "var ret = ""; "+
    "while(child) { "+
    "    if (child.nodeType === Node.TEXT_NODE) "+
    "        ret += child.textContent; "+
    "    child = child.nextSibling; "+
    "} "+
    "return ret;", el);
}

locationOfText 参数可以是 Selenium 支持的任何 By 方法。

在您的代码中,您将 ByChained 用于 location,这可能是您想要传递给 executeScript 但忘记这样做的。我看不出这是如何工作的,即使您将 location 添加到 executeScript 调用(并修复脚本以获取 arguments[0])。 ByChained 将支持诸如混合 CSS 选择器与 XPath 等的东西。Selenium 大概可以通过执行多个搜索来解决组合,但 XPath 没有办法浏览器引擎将接受 CSS 和 XPath 的某种组合。