4

在我的 Selenium 应用程序中,我尝试选择具有最高z-index. 该值不是在元素本身中定义的,而是在祖先节点上定义的(嵌套级别未知)。此外,如果使用display: none它的祖先不可见,则不应返回。

示例 HTML:

  <div class="container" style="z-index: 10">
    <div style="display: none">
      <!-- this should not be selected because it is invisible (and the z-index is lower than the others) -->
      <div myattr="example"></div>
    </div>
  </div>
  <div class="container" style="z-index: 100">
    <div>
      <!-- this should not be selected because the z-index is lower than the others -->
      <div myattr="example"></div>
    </div>
  </div>
  <div class="container" style="z-index: 1000">
    <div>
      <!-- this should be selected because it is visible and has the highest z-index -->
      <div myattr="example"></div>
    </div>
  </div>

目前我有一个正则表达式,它选择所有myattr="example"没有祖先的元素display: none

//div[@myattr='example'
and not(ancestor::div[contains(@style,'display:none')])
and not(ancestor::div[contains(@style,'display: none')])]

我需要一个附加条件来选择具有最高 z-index 的元素,可以说是在其他元素之上可见。对于每个找到的节点,必须查看所有祖先,直到找到具有特定类的节点(container在本例中)。然后只返回具有最高 z-index 祖先的元素。

XPath 甚至可以做到这一点吗?

4

2 回答 2

2

我真的很努力,但我认为你不能用一个 XPath 1.0 表达式来实现这一点。你可以靠近,但不完全在那里。

您需要使用其他一些逻辑。好像有一千种不同的方法。

例如,获取所有container元素,对它们进行排序z-index并测试它们的myattr="example"后代的可见性:

// Gets all containers - could also be Gets all elements containing z-index
List<WebElement> containers = driver.findElements(By.className("container"));

// Sorts the containers in an descending order by their z-indexes
Collections.sort(containers, Collections.reverseOrder(new Comparator<WebElement>() {
    @Override
    public int compare(WebElement o1, WebElement o2) {
        return getZindex(o1) - getZindex(o2);
    }
    private int getZindex(WebElement elem) {
        String zindex = elem.getAttribute("style").toLowerCase().replace("z-index: ", "");
        return Integer.parseInt(zindex);
    }
}));

// look for a visible candidate to return as a result
for (WebElement container : containers) {
    WebElement result = container.findElement(By.cssSelector("*[myattr='example']"));
    if (result.isDisplayed()) {
        return result;
    }
}
throw new IllegalStateException("No element found.");

编辑:在你接受这个答案后,我回到了这个问题并想出了一个 XPath 1.0 解决方案。它丑得要命,性能很差,我无法验证它的正确性(它适用于您的示例和我尝试过的其他一些示例),因此我建议您使用上面的 WebDriver 方法。无论如何,我会分享它:

Copypastable oneliner:

//div[@myattr='example' and not(ancestor::div[contains(@style,'display: none')])]/ancestor::div[@class='container' and substring-after(@style,'z-index:') > substring-after(../div[not(descendant::div[contains(@style,'display: none')])]/@style,'z-index:')]

格式化版本:

//div
    [
        @myattr='example'
        and not(ancestor::div[contains(@style,'display: none')])
    ]
    /ancestor::div
        [
            @class='container'
            and substring-after(@style,'z-index:')
                > substring-after(
                    ../div[not(descendant::div[contains(@style,'display: none')])]/@style,
                    'z-index:')
        ]

以及对人类语言的免费翻译(不是字面的!):

SELECT A VISIBLE <div @myattr='example'> NODE
//div
    [
        @myattr='example'
        and not(ancestor::div[contains(@style,'display: none')])
    ]
    THAT HAS A <div @class='container'> ANCESTOR
    /ancestor::div
        [
            @class='container'
            WHOSE z-index IS GREATER THAN z-index...
            and substring-after(@style,'z-index:')
                > substring-after(
                    ...OF ALL VISIBLE SIBLINGS
                    ../div[not(descendant::div[contains(@style,'display: none')])]/@style,
                    'z-index:')
        ]
于 2013-02-27T16:03:05.507 回答
1

我假设你知道 z-index 的最大值,在这种情况下 xpath 是

"//div[contains(@style,'1000')]/div[not(contains(@style,'none'))]/div"

否则使用下面的 xpath 获取 div 的所有样式属性

List<WebElement> divTags=driver.findElements(By.xpath("//div[not(contains(@style,'none'))]/parent::div[contains(@style,'z-index')]"))
for(WebElement ele:divTags)
{
    ele.getAttribute("style");
}
  • 将 z-indexes 存储在某个变量中
  • 解析存储的 z 索引并单独获取数字
  • 使用一些逻辑找到其中最大的数字
  • 做上述所有事情都会保留该元素的索引。
  • 找到最高 z-index 后,获取该元素的索引
  • 使用该索引构造 xpath。

我希望以上逻辑能帮助您实现目标。

于 2013-02-27T14:31:12.797 回答