0

I have few data rows, they don't have a trackable id or class hence need a child/ follows kind of XPath. Below is the HTML content:

<tr class="v-formlayout-row v-formlayout-firstrow" xpath="1">
  <td class="v-formlayout-captioncell">
    <div class="v-caption v-caption-smalllabel v-caption-hide-indicator v-caption-hasdescription"><span id="gwt-uid-6138" for="gwt-uid-6139">Unit type</span></div>
  </td>
  <td class="v-formlayout-errorcell">
    <div class="v-formlayout-error-indicator"></div>
  </td>
  <td class="v-formlayout-contentcell">
    <div class="v-horizontallayout v-layout v-horizontal v-widget smalllabel v-horizontallayout-smalllabel hide-indicator v-horizontallayout-hide-indicator" id="gwt-uid-6139" aria-labelledby="gwt-uid-6138">
      <div class="v-slot v-slot-hide-indicator">
        <div class="v-formlayout v-layout v-widget hide-indicator v-formlayout-hide-indicator">
          <table cellpadding="0" cellspacing="0" role="presentation">
            <colgroup>
              <col>
            </colgroup>
            <tbody>
              <tr class="v-formlayout-row v-formlayout-firstrow v-formlayout-lastrow">
                <td class="v-formlayout-captioncell">
                  <div class="v-caption v-caption-tiny v-caption-smalllabel"></div>
                </td>
                <td class="v-formlayout-errorcell">
                  <div class="v-formlayout-error-indicator"></div>
                </td>
                <td class="v-formlayout-contentcell">
                  <div class="v-label v-widget tiny v-label-tiny smalllabel v-label-smalllabel v-label-undef-w" style="">CHDB&nbsp;&nbsp;</div>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
      <div class="v-slot v-slot-hide-indicator">
        <div class="v-formlayout v-layout v-widget hide-indicator v-formlayout-hide-indicator">
          <table cellpadding="0" cellspacing="0" role="presentation">
            <colgroup>
              <col>
            </colgroup>
            <tbody>
              <tr class="v-formlayout-row v-formlayout-firstrow v-formlayout-lastrow">
                <td class="v-formlayout-captioncell">
                  <div class="v-caption v-caption-tiny v-caption-smalllabel"></div>
                </td>
                <td class="v-formlayout-errorcell">
                  <div class="v-formlayout-error-indicator"></div>
                </td>
                <td class="v-formlayout-contentcell">
                  <div class="v-label v-widget tiny v-label-tiny smalllabel v-label-smalllabel v-label-undef-w">F1080&nbsp;</div>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </td>
</tr>

Here Unit type is the one which needs to be taken as parent element and this value will not change, but the next elements CHDB and F1080 changes and we need to validate these 2 elements.

To do this I need an XPath which takes Unit type as parent element and the value that we get as a child and need this for multiple values in same pattern, so this one will be helpful.

At present using

(//tr//child::td[contains(@class,'v-formlayout-contentcell')]//child::div[contains(@id,'gwt-uid')])[1]
(//tr//child::td[contains(@class,'v-formlayout-contentcell')]//child::div[contains(@id,'gwt-uid')])[2]

Which is not a good practise, hence taking the 1st value as a parent and next as a child or using sibling function need a reusable XPath

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352

3 Answers3

0

Use the below XPath.This will return two elements you are after.

//span[text()='Unit type']/following::table[@role='presentation']//td//div[contains(@class,'v-label-undef-w')]

You need to induce WebDriverWait and visibilityOfAllElementsLocatedBy() And Use getAttribute() to get the value with either innterText OR textContent

WebDriverWait wait = new WebDriverWait(driver, 30);
List<WebElement> elements = wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.xpath("//span[text()='Unit type']/following::table[@role='presentation']//td//div[contains(@class,'v-label-undef-w')]")));
for(int i=0;i<elements.size();i++)
   {
      System.out.println(elements.get(i).getAttribute("innerText"));
      System.out.println(elements.get(i).getAttribute("textContent"));
    }
KunduK
  • 32,888
  • 5
  • 17
  • 41
0

You can try this xpath. This uses 'Unit type' to locate the child element (which are dynamic). This xpath will return both elements. so you will have to loop through it to get the text.

//div[contains(text(),'Unit type')]/parent::td/following-sibling::td//tbody//td[contains(@class,'v-label')]
Sureshmani Kalirajan
  • 1,938
  • 2
  • 9
  • 18
0

To extract the texts e.g. CHDB and F1080 with respect to the text Unit type as the elements are dynamic elements, you have to induce WebDriverWait for the visibilityOfElementLocated() and you can use either can use either of the following Locator Strategies:

  • xpath for the text CHDB:

    System.out.println(new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//tr//span[text()='Unit type']//following::td[@class='v-formlayout-contentcell']/div[starts-with(@id, 'gwt-uid-') and starts-with(@aria-labelledby, 'gwt-uid-')]/div[@class='v-slot v-slot-hide-indicator']//div[@class="v-label v-widget tiny v-label-tiny smalllabel v-label-smalllabel v-label-undef-w"][@style]"))).getText());
    
  • xpath for the text F1080:

    System.out.println(new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//tr//span[text()='Unit type']//following::td[@class='v-formlayout-contentcell']/div[starts-with(@id, 'gwt-uid-') and starts-with(@aria-labelledby, 'gwt-uid-')]/div[@class='v-slot v-slot-hide-indicator']//div[@class="v-label v-widget tiny v-label-tiny smalllabel v-label-smalllabel v-label-undef-w" and not(@style)]"))).getText());
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352