找不到包含一些文字的元素

时间:2017-09-18 13:40:30

标签: c# google-chrome selenium xpath selenium-webdriver

有一点页面:

 <label>
   <input type="checkbox">

   </input>
"  some text"
</label>

我需要找到一个包含“some text”的元素。 如果我使用

WebElement().ByXPath("//div/label[contains(text(),'some text')]");

但这并没有给出结果。无法找到元素。

但是!!如果我尝试使用

获取此元素的Attribute(InnerHTML,GetText,innerText)
    WebElement.ByXPath("//div/label").GetAttribute("InnerHTML"/"innerText");
   WebElement.ByXPath("//div/label").Text; 

有正确的结果(WebElement.ByXPath(“// div / label”)。Text ==“some text”)!

对于此XPath元素:

WebElement().ByXPath("//div/label[contains(@innerHtml,'some text')]");
WebElement().ByXPath("//div/label[contains(@innerText,'some text')]");

它也不起作用。

为什么这可能?为什么我无法通过页面上的唯一文本找到元素?

5 个答案:

答案 0 :(得分:0)

你的xpath似乎是正确的,但我无法查看你的页面。您的示例适用于此stackoverflow页面:

<a href='/person1'></a>
<a href='/person2'></a>

我知道这很有效,因为我使用FireFox的FirePath扩展程序进行了测试。尝试使用它来测试它:https://addons.mozilla.org/en-US/firefox/addon/firepath/

答案 1 :(得分:0)

可能由于页面在元素显示之前未完全加载,因此在构建selenium测试时,您将遇到错误,这些错误不是错误,只是对浏览器和速度的不一致。您可以通过构建计划无法找到的项目的稳定代码来为它们做好准备。

等待功能有帮助

public IWebElement WaitForElement(By element)
    {
            return new WebDriverWait(this.browser,
                TimeSpan.FromSeconds(10)).
                Until(ExpectedConditions.
                ElementIsVisible(element));
    }

如果您认为需要,您也可以通过允许程序刷新页面进行准备,如果失败则再次尝试测试,双重检查方法。

对于你总是使用的xpath,如果他们没有名字或id

By.Xpath("//*[contains(text(), 'Some Text')]");

答案 2 :(得分:0)

我不确定是什么导致了这个问题,但我同意有时会有一个问题。我建议你尝试以下方法:

//div//label[contains(node(),'some text')]

或者,建议使用 redp ,您可以使用*但请确保正确指定父元素,以防您的网页包含多个具有相同文字的标签:

//div//*[contains(node(),'some text')]

如果内存有效,您可以contains(.,'some text') contains(node(),'some text)'使用{{1}}。另外,请考虑在检查器工具中仔细检查元素,并注意属性选项卡。并且,请记住,您可以使用 Inspector 中的搜索找到您的元素,这将为您节省大量时间。

如果有帮助,请更新我。

答案 3 :(得分:0)

应该在“某些文字”周围加上一个span标签。这只是糟糕的HTML标记。

您也可以使用:

//label/text()[last()]
//label/text()[2]

答案 4 :(得分:0)

的确,虽然html并不是很好的做法,但是它已经存在,人们不得不对其进行处理。我认为normalize-space()在这里会有所帮助。在具有该html的页面上的chrome控制台中尝试以下操作:

$x(`//label[contains(normalize-space(), "some text")]`);

我认为上面的代码分为以下内容:

  1. 找到所有label个节点
  2. 对于每个节点
    1. 获取该节点内的text个节点及其子节点的所有
    2. 合并他们的文本
    3. 从每个文本节点的文本中删除多余的空格
    4. 如果我想要的确切字符串(“某些文本”)在其中,请将label添加到要返回的节点列表中。
  3. 返回具有该文本的所有节点的列表(如果不匹配则为空列表)

为了更复杂一点,如果我想找到具有“一些文本”的text节点的直接父节点,我可以这样做:

$x(`//label//text()[contains(normalize-space(), "some text")]/..`);

但是,这很棘手。对于每个包含给定字符串的text节点,它都会获得直接父级。因为“某些文本”全部位于一个text节点中,因此可以很好地工作。在其他情况下,它可能使某人绊倒。例如,看这个html:

<label>
  <span> text </span>
  some other text
</label>

作为一个人,我可以阅读“一些其他文本”,因此看来我应该能够找到“一些文本”的父代。如果我使用第一种方法查找其中带有“ text some”的label,则此代码将发现label很好:

$x(`//label[contains(normalize-space(), "text some")]`);

这是因为所有文本节点的组合中确实包含“一些文本”。我不能使用第二种方法。例如,在html上使用此代码只会给我一个空列表:

$x(`//label//text()[contains(normalize-space(), "text some")]/..`);

这是因为,当xpath在每个单独的text节点中查找时,它们中没有一个包含“ text some”。如果我考虑一下,“给一些文本”实际上并没有一个直接父母。它有两个直接父母。 xpath选择不给父母,而不给他们两个。似乎足够公平。

我没有找到normalize-space()的任何很好的解释,也不知道为什么它结合了所有后代节点的文本。至于为什么text()无法正常运作,我从2014年开始找到以下答案:

text()child::text()的缩写,它选择作为label元素的直接子元素的文本节点。 -https://stackoverflow.com/a/26823289/14144258

可能仍然正确。

此外,我知道这是一个古老的问题,但是我在尝试对自己的代码进行故障排除时遇到了同样的问题,并且花了很长时间才能找到解决方案。