2

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

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

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

其他一些帖子建议是这样的://*/text().
但是,这在 Firefox 中不起作用。

这是一个重现问题的小单元测试:

 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();
    }
 }
4

5 回答 5

7

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

//*[text()]

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

在您的情况下,它将选择<span>标签,因为它包含文本。

于 2012-08-02T09:36:41.213 回答
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();");

仅供参考:类似的东西可能对你有用。

于 2012-08-02T09:02:10.500 回答
1

我看不出为什么这不起作用(通过java)

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

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

text = driver.findElement(By.xpath("//span")).getAttribute("innerHTML")
于 2012-08-02T09:05:40.480 回答
1

最后我发现没有办法用 xpath 来做(因为 XPathstext()也选择了一个节点的 innerText)。作为解决方法,我必须注入返回由 XPath 选择的所有元素的 Java 脚本,其中包含一些文本。

像这样:

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

}

我修改了示例可测试的 UnitTest。

于 2012-08-02T14:06:28.717 回答
1

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

<tag1><tag2/></tag1>

没有文本节点,但

<tag1>  <tag2/>    </tag1> 

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

如果您只想要具有非空文本的文本节点,这是一种方法:

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

或获取其父元素

//*[text()[string-length(normalize-space(.))>0]]
于 2015-01-09T13:58:43.640 回答