C# 查找具有满足多个By条件的Selenium Webdriver的元素

C# 查找具有满足多个By条件的Selenium Webdriver的元素,c#,selenium,selenium-webdriver,C#,Selenium,Selenium Webdriver,我正在使用Selenium的v2.52和带有C#的WebDriver。我试图实现的应该是相当简单的,但是我找不到解决方案:我想根据多个标准来查找元素 比方说,我有这样的想法: OpenQA.Selenium.Support.PageObjects.ByChained不起作用,因为它正在搜索层次结构 是否有办法根据-标准查找与多个匹配的元素 致以最良好的祝愿, 卡斯滕我想这样的事情可能适合你的情况: public IWebElement FindElementByMultipleCriteria

我正在使用Selenium的v2.52和带有C#的WebDriver。我试图实现的应该是相当简单的,但是我找不到解决方案:我想根据多个
标准来查找元素

比方说,我有这样的想法:

OpenQA.Selenium.Support.PageObjects.ByChained
不起作用,因为它正在搜索层次结构

是否有办法根据
-标准查找与多个
匹配的元素

致以最良好的祝愿,
卡斯滕

我想这样的事情可能适合你的情况:

public IWebElement FindElementByMultipleCriteria(List<By> Criteria, IReadOnlyCollection<IWebElement> toFilter = null)
{
    // If we've reached the end of the criteria list, return the first element:
    if (Criteria.Count == 0 && toFilter != null) return toFilter.ElementAt(0);

    // Take the head of the criteria list
    By currentCriteria = Criteria[0];
    Criteria.RemoveAt(0);

    // If no list of elements found exists, we get all elements from the current criteria:
    if (toFilter == null)
    {
        toFilter = Driver.FindElements(currentCriteria);
    }
    // If a list does exist, we must filter out the ones that aren't found by the current criteria:
    else
    {
        List<IWebElement> newFilter = new List<IWebElement>();
        foreach(IWebElement e in Driver.FindElements(currentCriteria))
        {
            if (toFilter.Contains(e)) newFilter.Add(e);
        }
        toFilter = newFilter.AsReadOnly();
    }

    // Pass in the refined criteria and list of elements found.
    return FindElementByMultipleCriteria(Criteria, toFilter);
}

IWebElement example = FindElementByMultipleCriteria(new List<By>(){ By.TagName("a"), ClassName("foo") });
public IWebElement FinDelementByMultiplePriteria(列表条件,IReadOnlyCollection toFilter=null)
{
//如果已到达条件列表的末尾,请返回第一个元素:
if(Criteria.Count==0&&toFilter!=null)返回toFilter.ElementAt(0);
//以标准列表的开头
按当前标准=标准[0];
标准。移除(0);
//如果不存在元素列表,我们将从当前条件中获取所有元素:
if(toFilter==null)
{
toFilter=Driver.FindElements(当前标准);
}
//如果确实存在列表,则必须筛选出当前条件未找到的列表:
其他的
{
List newFilter=新列表();
foreach(驱动程序中的IWebElement e.FindElements(currentCriteria))
{
如果(toFilter.Contains(e))newFilter.Add(e);
}
toFilter=newFilter.AsReadOnly();
}
//传入优化的条件和找到的元素列表。
返回FindElementByMultipleCliteria(标准,toFilter);
}
IWebElement示例=FinDelementByMultipleLiteria(新列表(){By.TagName(“a”)、类名(“foo”)});
从本质上讲,您将获取由传入的第一个
by
找到的元素列表。然后,您将按照
标准检查剩余的
,并从初始列表中删除再也找不到的元素

这是非常低效的,我真的不明白你为什么要这样做,但它是存在的


另外,您还需要使用System.Linq添加
为了与
IReadOnlyCollection

交互,我想您可以尝试类似的方法,并告诉我它是否有效:

    public IWebElement FindElementUsingNestedBy(By firstCriteria, By secondCriteria)
    {
        var allElements = Driver.FindElements(firstCriteria);
        foreach (var webElement in allElements)
        {
            try
            {
                var desiredObject = webElement.FindElement(secondCriteria);
                return desiredObject;
            }
            catch (NotFoundException ex)
            {

            }
        }
        return null;
    }

那么
XPath
CssSelector
有什么问题吗?它没有任何问题。好吧,也许XPath有点像静态的。我只是想知道我是否可以按照我描述的方式找到元素。我想没有这样的方法可以通过多个过滤器找到元素。无论如何,
xpath
将更加灵活,因为有许多
HTML
属性只能通过
xpath
cssSelector
找到。还要注意的是,包含空格的类名不能通过.ClassName(“foo”)
方法与
匹配,但可以通过.XPath('/*[@class=“fo”]')
匹配……事实上,这听起来是一个可怕的想法如果没有现成的支持,我可以。我想知道是否有可用的东西,但显然没有。我想它不存在,因为你可以给它一个可怕的标准列表,比如
[By.TagName(“a”)、.TagName(“input”)、.TagName(“h1”)]
,然后直接构建你的程序,哈哈,如果我没弄错的话,这不是我要找的。您的
secondCriteria
正在从
firstCriteria
搜索这些元素下面(从DOM的角度)的元素。此功能已包含在
ByChained
中。我希望所有条件在一个元素上都匹配。
public IWebElement FindElementByMultipleCriteria(List<By> Criteria, IReadOnlyCollection<IWebElement> toFilter = null)
{
    // If we've reached the end of the criteria list, return the first element:
    if (Criteria.Count == 0 && toFilter != null) return toFilter.ElementAt(0);

    // Take the head of the criteria list
    By currentCriteria = Criteria[0];
    Criteria.RemoveAt(0);

    // If no list of elements found exists, we get all elements from the current criteria:
    if (toFilter == null)
    {
        toFilter = Driver.FindElements(currentCriteria);
    }
    // If a list does exist, we must filter out the ones that aren't found by the current criteria:
    else
    {
        List<IWebElement> newFilter = new List<IWebElement>();
        foreach(IWebElement e in Driver.FindElements(currentCriteria))
        {
            if (toFilter.Contains(e)) newFilter.Add(e);
        }
        toFilter = newFilter.AsReadOnly();
    }

    // Pass in the refined criteria and list of elements found.
    return FindElementByMultipleCriteria(Criteria, toFilter);
}

IWebElement example = FindElementByMultipleCriteria(new List<By>(){ By.TagName("a"), ClassName("foo") });
    public IWebElement FindElementUsingNestedBy(By firstCriteria, By secondCriteria)
    {
        var allElements = Driver.FindElements(firstCriteria);
        foreach (var webElement in allElements)
        {
            try
            {
                var desiredObject = webElement.FindElement(secondCriteria);
                return desiredObject;
            }
            catch (NotFoundException ex)
            {

            }
        }
        return null;
    }