4

I have a table where each row will have a download link with a (partly) auto-generated id element. The reason for this is that the actual href-element will allways be "#", so the id's separate the downloads.

I need to find the name of that id element in the td. That is: I know the table row has an id element, and I know part of the name, and I need to get the exact name.

I'm accessing each row one at a time, so I only need to look within ONE td at a time. No need to look through the whole table.

I know well how to find an element when I know the name. But to find the element when I only know the type is another thing.

...
<tr>
 <td class="journalTable-journalPost"
  <a class="htext-small" href="#" id="downloadJournalPost-345">Download</a>
 </td>
</tr>
<tr>
 <td class="journalTable-journalPost"
  <a class="htext-small" href="#" id="downloadJournalPost-346">Download</a>
 </td>
</tr>
...

I cannot find any method(s) in the webdriver that lets me find an element by type.

Partial name would work, since the id's get the name "downloadJournalPost-xxx", where only xxx changes. But link text is the only value I can find which lets me search for a partial match.

EDIT: More complete markup.

<td class="journalTable-journalpost">
 <span class="hb-tekst--sekundar">In <!----><est-ikon class="ng-star-inserted">
  <div aria-hidden="true" class="hb-ikon hb-ikon--pil3-inn  ">
   <svg focusable="false">
    <use xlink:href="#ikon-pil3-inn"></use>
   </svg>
  </div></est-ikon><!----></span>
 <span class="hb-tekst--mellomTittel hb-avstandIngen"> Application and attachments</span>
 <a class="hb-tekst--liten" href="#" id="lastNedJournalPost-2892">Download journal post</a>
</td>
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • What exactly do you mean by _...I only know the type is another thing..._? Both the elements looks to be similar? How many rows/columns are there in the table? Update the HTML with a bit more of the parent elements – undetected Selenium Apr 16 '19 at 11:40
  • I'm not sure how more of the same code will help? The elements are not similar. In this example, one row has id="downloadJournalPost-345" and the next has id="downloadJournalPost.346". For each row, I need to get the name of the id. I don't need the contect of the element. –  Apr 16 '19 at 11:45
  • 1
    Yes, as you need to get the `id` (which is dynamic) of the element we need to identify the element first. So we need to know how deeper the desired element is present. So you need to update the HTML with a bit more of the HTML including the parent element to identify the element first. – undetected Selenium Apr 16 '19 at 11:47
  • Are you looking for all the `id` attributes? – undetected Selenium Apr 16 '19 at 11:50

2 Answers2

3

Until you find the element first, you can't retrieve the attribute values of it.

Use findElements method to fetch all links using the following locator

table tr td[class='journalTable-journalPost'] a

Then iterate through each element using for-each to fetch id for each element.

Sample code:

List<WebElement> listOfLinks = driver.findElements(By.cssSelector("table tr td[class='journalTable-journalPost'] a"));

for(WebElement link: listOfLinks) {
     System.out.println("id:" + link.getAttribute("id"));
}
Naveen Kumar R B
  • 6,248
  • 5
  • 32
  • 65
  • I can almost get that to work. It finds the elements with the class name (the number matches the number of rows) , but getAttbute("id") is blank. –  Apr 16 '19 at 12:02
  • If it not printing it, I am sure element's HTML won't be having IDs in it. Are you sure IDs are generated every time? try printing `link.getText()` and check the text. Also, print `link.getAttribute("innerHTML");` to see the complete HTML for that element. – Naveen Kumar R B Apr 16 '19 at 12:20
  • Yes, I'm sure that there is an ID every time. link.getText() prints the text inside the td. link.getAttribute("innerHTML") prints, among lots of other things, id="downloadJournalPost-345"> –  Apr 16 '19 at 12:30
  • It could be a timing issue then. Solve it using WebDriverWait or Sleep. for confirmation, put a debug point before finding the elements and wait for the complete page to load. Then continue with the execution. If it prints the IDs, then it is timing issue you need to solve. – Naveen Kumar R B Apr 16 '19 at 12:36
  • Don't think it's a timing issue. I'm using WebDriverWait to check for the presence of the class before all this messing around with finding the ID inside of it. I've updated the question with some more complete markup. Maybe my shortened example was misleading? –  Apr 16 '19 at 12:40
  • 2
    Well, your solution works, it seems. It's just that I cannot find it using cssSelector. Using xPath instead, as @DebanjanB suggests, it works. –  Apr 16 '19 at 12:52
1

To print the List of id attribute of the element you need to induce WebDriverWait for the visibilityOfAllElementsLocatedBy() and you can use Java8 stream() and map() and you can use either of the following Locator Strategies:

  • cssSelector:

    List<String> myID = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector("td.journalTable-journalPost>a.htext-small"))).stream().map(element->element.getAttribute("id")).collect(Collectors.toList());
    System.out.println(myIDs);
    
  • xpath:

    List<String> myIDs = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//td[@class='journalTable-journalPost']/a[@class='htext-small' and text()='Download']"))).stream().map(element->element.getAttribute("id")).collect(Collectors.toList());
    System.out.println(myIDs);
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • 1
    That's elegant. I like streams. However, the problem is - as with the below answer - that getAttribute("id") returns "" instead of the name of the id. –  Apr 16 '19 at 12:22
  • Checkout my answer update and let me know the status – undetected Selenium Apr 16 '19 at 12:28
  • 2
    Ah! It worked with the xpath version. Is that because there are other elements inside the class, so that the cssSelector version needs to be more precise? I really don't like xpath if I can avoid it. –  Apr 16 '19 at 12:47
  • Well _xpath_ or _cssSelector_, a lot depends on the _AUT (Application Under Test)_. Hence the options. – undetected Selenium Apr 16 '19 at 12:49