在使用Firefox WebDriver时,选择所有具有文本的节点的Xpath表达式是什么?

时间:2012-08-02 08:21:55

标签: firefox xpath selenium webdriver

我想选择所有包含文本的节点。

在此示例中,不应选择外部shouldBeIgnored标记:

<shouldBeIgnored>
    <span>
        the outer Span should be selected
    </span>
</shouldBeIgnored>

其他一些帖子提示如下://*/text()
但是,这在firefox中不起作用。

这是一个重现问题的小型UnitTest:

 public class XpathTest {
    final WebDriver webDriver   = new FirefoxDriver();

    @Test
    public void shouldNotSelectIgnoredTag() {

        this.webDriver.get("http://www.s2server.de/stackoverflow/11773593.html");

        System.out.println(this.webDriver.getPageSource());

        final List<WebElement> elements = this.webDriver.findElements(By.xpath("//*/text()"));

        for (final WebElement webElement : elements) {
            assertEquals("span", webElement.getTagName());
        }
    }

    @After
    public void tearDown() {
        this.webDriver.quit();
    }
 }

5 个答案:

答案 0 :(得分:6)

如果要选择包含文本的所有节点,则可以使用

//*[text()]

在xpath之上将查找包含文本的任何元素。请注意text()函数,该函数用于确定当前节点是否包含文本。

在您的情况下,它会选择<span>标记,因为它包含文字。

答案 1 :(得分:1)

你可以调用一个javascript函数,它将返回文本节点:

function GetTextNodes(){    
var lastNodes = new Array();
    $("*").each(function(){
      if($(this).children().length == 0)
        lastNodes.push($(this));
    });
    return lastNodes;
}

Selenium WebDriver代码:

IJavaScriptExecutor jscript = driver as IJavaScriptExecutor;
List<IWebElement> listTextNodes = jscript.ExecuteScript("return GetTextNodes();");

仅供参考:有些事可能适合你。

答案 2 :(得分:1)

我认为没有理由不这样做 (通过java)

text = driver.findElement(By.xpath("//span")).getText()

如果在奇怪的情况下不起作用:

text = driver.findElement(By.xpath("//span")).getAttribute("innerHTML")

答案 3 :(得分:1)

最后我发现用xpath无法做到这一点(因为XPath text()也选择了节点的innerText)。作为解决方法,我必须注入Java脚本,该脚本返回由XPath选择的具有一些文本的所有元素。

像这样:

public class XpathTest
{
    //@formatter:off
    final static String JS_SCRIPT_GET_TEXT  =  "function trim(str) {                                                       " +                                                                                                                                             
                                               "    return str.replace(/^\s+|\s+$/g,'');            " +                                                                                                                                             
                                               "}                                                                          " +                                                                                                                                             
                                               "                                                                           " +                                                                                                                                             
                                               "function extractText(element) {                                            " +                                                                                                                                             
                                               "    var text = '';                                                         " +                                                                                                                                             
                                               "    for ( var i = 0; i < element.childNodes.length; i++) {                 " +                                                                                                                                             
                                               "        if (element.childNodes[i].nodeType === Node.TEXT_NODE) {           " +                                                                                                                                             
                                               "            nodeText = trim(element.childNodes[i].textContent);            " +                                                                                                                                             
                                               "                                                                           " +                                                                                                                                             
                                               "            if (nodeText) {                                                " +                                                                                                                                             
                                               "                text += element.childNodes[i].textContent + ' ';           " +                                                                                                                                             
                                               "            }                                                              " +                                                                                                                                             
                                               "        }                                                                  " +                                                                                                                                             
                                               "    }                                                                      " +                                                                                                                                             
                                               "                                                                           " +                                                                                                                                             
                                               "    return trim(text);                                                     " +                                                                                                                                             
                                               "}                                                                          " +                                                                                                                                             
                                               "                                                                           " +                                                                                                                                             
                                               "function selectElementsHavingTextByXPath(expression) {                     " +                                                                                                                                             
                                               "                                                                           " +                                                                                                                                             
                                               "    result = document.evaluate(\".\" + expression, document.body, null,    " +                                                                                                                                             
                                               "            XPathResult.ANY_TYPE, null);                                   " +                                                                                                                                             
                                               "                                                                           " +                                                                                                                                             
                                               "    var nodesWithText = new Array();                                       " +                                                                                                                                             
                                               "                                                                           " +                                                                                                                                             
                                               "    var node = result.iterateNext();                                       " +                                                                                                                                             
                                               "    while (node) {                                                         " +                                                                                                                                             
                                               "        if (extractText(node)) {                                           " +                                                                                                                                             
                                               "            nodesWithText.push(node)                                       " +                                                                                                                                             
                                               "        }                                                                  " +                                                                                                                                             
                                               "                                                                           " +                                                                                                                                             
                                               "        node = result.iterateNext();                                       " +                                                                                                                                             
                                               "    }                                                                      " +                                                                                                                                             
                                               "                                                                           " +                                                                                                                                             
                                               "    return nodesWithText;                                                  " +                                                                                                                                             
                                               "}                                                                          " +                                                                                                                                             
                                               "return selectElementsHavingTextByXPath(arguments[0]);";                                                                                                                                                                                    
    //@formatter:on

    final WebDriver     webDriver           = new FirefoxDriver();

    @Test
    public void shouldNotSelectIgnoredTag()
    {
        this.webDriver.get("http://www.s2server.de/stackoverflow/11773593.html");

        final List<WebElement> elements = (List<WebElement>) ((JavascriptExecutor) this.webDriver).executeScript(JS_SCRIPT_GET_TEXT, "//*");

        assertFalse(elements.isEmpty());

        for (final WebElement webElement : elements)
        {
            assertEquals("span", webElement.getTagName());
        }
    }

    @After
    public void tearDown()
    {
        this.webDriver.quit();
    }

}

我修改了示例testable的UnitTest。

答案 4 :(得分:1)

定位文本节点的一个问题是即使空字符串也被视为有效的文本节点(例如

<tag1><tag2/></tag1>

没有文字节点,但

<tag1>  <tag2/>    </tag1> 

有2个文本节点,一个有2个空格,另一个有4个空格

如果您只想要具有非空文本的文本节点,可以采用以下方法之一:

//text()[string-length(normalize-space(.))>0]

或获取他们的父元素

//*[text()[string-length(normalize-space(.))>0]]