【问题标题】:Method is not available, requires "unneccessary" rewrite?方法不可用,需要“不必要”的重写?
【发布时间】:2020-11-05 21:22:55
【问题描述】:

我有这两个 Selenium/Java 调用:

List<WebElement> aList = driver.findElements(By.xpath("//something"));
List<WebElement> bList = driver.findElements(By.xpath("//something"));

在第一个示例中,XPath 指向元素内容(例如,&lt;b&gt;element content&lt;/b&gt;)并用一堆字符串填充 aList。

对于bList,我想在找到的节点上使用getAttribute("alt")(返回HTML标签中的alt属性的字符串值)并将结果字符串保存在bList中,但该方法不是如果我这样做,则可用/适用:

List<WebElement> bList = driver.findElements(By.xpath("//somethingElse")).getAttribute("alt"); //doesn't work

这是为什么呢?我真的需要吗

bList.get(1).getAttribute("alt");

?也就是说,逐个访问每个返回的元素并在它们上调用getAttribute。如果我能在一行中完成所有这些事情会更好,就像我为 aList 所做的那样。

澄清一下:

  1. 这主要是一道 Java 语法问题。
  2. 外观示例。我有几个与something-XPath 匹配的html 元素,看起来像这样&lt;b alt="EN"&gt;some text&lt;/b&gt;. 我希望some text 进入aList(这有效),而EN 应该进入bList。我该如何写,bList-case,作为 oneliner?

【问题讨论】:

    标签: java selenium selenium-webdriver syntax operator-precedence


    【解决方案1】:

    是的 selenium 方法:.getAttribute() 仅适用于一个 WebElement 而不是整个列表,因此您应该按照您所说的应用 for 循环...

    像这样:

    List<String> blist = new ArrayList<>();
        for (WebElement el:alist) {
            blist.add(el.getAttribute("alt"));
        }
    

    【讨论】:

      【解决方案2】:

      您的aListbList 变量都是Lists,其中包含一组项目,而不仅仅是一个项目。为了在其上使用.getAttribute(),您可以使用循环并单独处理每一个,或者如果您想要一个单行,您可以使用stream()

      一个简单的例子是

      List<String> aListStrings = aList.stream().map(e -> e.getText()).collect(Collectors.toList());
      

      此代码获取aList 集合,对其进行迭代,并将文本(使用.getText())推送到aListStrings

      话虽如此,我会建议我认为更有效的方法。从您发布的代码看来,aListbList 是相同的元素集合。如果是这种情况,您不需要同一列表的两个实例。此外,由于您似乎想从同一个元素中收集 alt 属性和文本,所以我会将它们存储在一起,以便您可以轻松地同时访问两者。

      考虑到所有这些,我会编写更像这样的代码

      // store all the elements in a single variable List
      List<WebElement> elements = driver.findElements(By.xpath("//something"));
      // initialize a List that will contain the pair of strings, alt text and the contained text
      List<Pair<String, String>> list = new ArrayList<Pair<String, String>>();
      // use a .stream() to map the alt text and contained text values into the Pair instance and return as a list
      list = elements.stream().map(e -> new Pair<String, String>(e.getText(), e.getAttribute("alt"))).collect(Collectors.toList());
      
      for (Pair<String, String> pair : list)
      {
          // do something with those values
          System.out.println(pair.getKey() + "," + pair.getValue());
      }
      

      我根据您的示例创建了一个简单的 HTML 文件,看起来像

      <b alt="EN">some EN text</b>
      <b alt="DE">some DE text</b>
      <b alt="ES">some ES text</b>
      

      当我运行上面的代码时,它会在模拟的 HTML 上输出

      some EN text,EN
      some DE text,DE
      some ES text,ES
      

      我添加了打印值的代码,作为如何访问这两个值的示例。你可以删除它,然后在循环中做任何你想做的事情。

      【讨论】:

        【解决方案3】:

        如果我理解你的问题,下面一行就足够了。

        List<String> blist = driver.findElements(By.xpath("//something")).stream().map(a->a.getAttribute("alt")).collect(Collectors.toList()); 
        

        【讨论】:

        • 是的。 Stream 真的让我们的生活变得轻松。在大多数情况下,您可以跳过 for 循环。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-01-22
        • 1970-01-01
        • 1970-01-01
        • 2020-09-02
        • 1970-01-01
        • 2017-06-19
        • 1970-01-01
        相关资源
        最近更新 更多