【问题标题】:Selenium: How to find any ancestor based on one of ancestor's attribute using IWebElement.FindElement()Selenium:如何使用 IWebElement.FindElement() 根据祖先的属性之一查找任何祖先
【发布时间】:2021-04-08 15:23:57
【问题描述】:

假设我有这个 HTML

<div class="item-wrapper">
 <div>
  <h6>My Header 1</h6>              
 <div>
 <div>
  <div>
   <label>
    <input type="checkbox" />
    <span class="class1">Text 2</span>       
    <span class="class2"></span>
   </label>
  <div>
 </div>
</div>
<div class="item-wrapper">
 <div>
  <h6>My Header 2</h6>              
 <div>
 <div>
  <div>
   <label>
    <input type="checkbox" />
    <span class="class1">Text 2</span>       
    <span class="class2"></span>
   </label>
  <div>
 </div>
</div>

如何将任何孩子联系到共同父母,即&lt;div class="item-wrapper"&gt;?在这种情况下,属性是类。但是,该属性可以是任何可以识别共同祖先的东西。

var xPathToAncestor = "ancestor::div[@class='item-wrapper']";
var ancestor = child.FindElement(By.XPath(xPathToAncestor)

我尝试了很多组合//ancestor::div[@class='item-wrapper'].//ancestor::div[@class='item-wrapper'],但没有任何效果。

【问题讨论】:

  • 相对于祖先&lt;div class="item-wrapper"&gt;,您正在查看哪个孩子
  • 一个问题是您需要具体说明要找到哪两个(或更多元素)的共同祖先。如果您选择 INPUT 或 SPAN,则共同祖先是 LABEL,依此类推。你找不到只有一个元素的“共同”祖先。
  • @JeffC,这是一个很好的观点。这就是为什么我说“任何父母”,因为我希望它成为一个占位符。我所需要的只是一个工作代码,这样我就可以将上面的 xpath 替换为字符串变量。上面的代码只是为了说明我在寻找什么。
  • @Richard77 问题内容是“我如何将任何孩子带到共同的父母那里,即
    ?” 并且答案就是这样。更新 ypur 问题
  • 我认为你的问题有很多困惑。在其中你问:“我如何让任何孩子TO到共同的父母那里?”我想你在那里打错字了,意思是说:“我如何任何孩子到共同的父母?对吗?如果是这样,你能更新你的问题吗?更多的例子可能也帮忙澄清一下。

标签: c# selenium selenium-webdriver xpath webdriver


【解决方案1】:

你可以使用

//div[@class='item-wrapper']//span

这会找到直接和间接子代的跨度标签

寻找直子

//div[@class='item-wrapper']/span

如何使用祖先:

//ancestor::div[@class="item-wrapper"]

这会找到一个带有标签 div 和类 item-wrapper 的元素,并且是任何子元素的父元素

//span/ancestor::div[@class="item-wrapper"]

在你的情况下,只需改变

var xPathToAncestor = "./ancestor::div[@class='item-wrapper']";

见“。”它表明孩子是xpath的上下文节点

这会找到一个带有标签 div 和类 item-wrapper 的元素,并且是 span 标签的父元素

//ancestor::div[@class="item-wrapper"]/span

查找作为 class="item-wrapper" 和 div 标签的直接子代的 span 标签

//ancestor::div[@class="item-wrapper"]//span

查找作为 class="item-wrapper" 和 div 标签的直接或非直接子代的 span 标签

【讨论】:

  • @Richard77 答案是否解决了您的问题?添加 .//ancestors 应该可以解决您的问题
【解决方案2】:

要获得与共同父母 &lt;div class="item-wrapper"&gt; 相关的任何孩子,您可以使用以下基于 Locator Strategies

  • 使用xpath获取&lt;input type="checkbox" /&gt;

    //div[@class='item-wrapper']//h6[text()='My Header']//following::label[1]/input[1]
    
  • 使用xpath获取&lt;span class="class1"&gt;Text 1&lt;/span&gt;

    //div[@class='item-wrapper']//h6[text()='My Header']//following::label[1]//span[@class='class1']
    

更新

根据您的问题更新,要获得共同的父母&lt;div class="item-wrapper"&gt;,您可以使用以下基于Locator Strategies

  • 使用 xpathancestor 和文本 Text 2:

    //span[text()='Text 2']//ancestor::div[@class='item-wrapper']
    
  • 使用xpathancestorclass="class1"属性:

    //span[@class='class1']//ancestor::div[@class='item-wrapper']
    

【讨论】:

  • @Richard77 查看更新的答案,让我知道状态。
【解决方案3】:

您可以尝试使用 CSS 选择器而不是 XPath。

以您问题中的 HTML 为例:

<div class="item-wrapper">
 <div>
  <h6>My Header</h6>              
 <div>
 <div>
  <div>
   <label>
    <input type="checkbox" />
    <span class="class1">Text 1</span>       
    <span class="class2"></span>
   </label>
  <div>
 </div>
</div>

要定位class="class1",你可以使用这个:

var classOne = driver.findElement(By.cssSelector(".item-wrapper &gt; div(2) &gt; div &gt; label &gt; '.class1'"));

  1. 这将定位item-wrapper 类,
  2. 然后是第二个div(因为第一个div 包含header),
  3. 然后是下一个div
  4. 然后label
  5. 那么类class1
  6. 您也可以使用span 代替类名。这将使它成为var classOne = driver.findElement(By.cssSelector(".item-wrapper &gt; div(2) &gt; div &gt; label &gt; span(1)));。因为您想要第一个 span 而不是第二个。

请注意,class 的 CSS 选择器是 .。您可以使用不同的 CCS 选择器。

这个answer explains 也使用 CSS 选择器。

【讨论】:

    猜你喜欢
    相关资源
    最近更新 更多
    热门标签