0

I need to find elements with loan amounts for investor A (in this case it is 100, 100)

can someone suggest how to write xpath to find those elements

[Example] In the screenshot below, I need to find xpath to get elements with text 100 in row one and two for which radio buttons are selected.

Below xpath is giving all the three loan amounts

//td[contains(., "Investor A")]/preceding-sibling::td[descendant::input][1]/label/text()

But I need only loan amounts from row one and two for which radio button is selected

enter image description here

<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
  crossorigin="anonymous"></script>
<html>

<head>
  <style>
    table {
      border: 1px dashed #cccccc;
      border-collapse: collapse;
    }

    table td {
      border: 1px dashed #cccccc;
    }
  </style>
</head>

<body>
  <table>
    <tr>
      <td>
        <label>Loan1</label>
      </td>
      <td>
        <input type='radio' name='L1' id='L1_one'></input>
        <label>100</label>
      </td>
      <td>
        <label>Investor A</label>
      </td>
      <td>
        <input type='radio' name='L1' id='L1_two'></input>
        <label>200</label>
      </td>
      <td>
        <label>Investor B</label>
      </td>
      <td>
        <input type='radio' name='L1' id='L1_three'></input>
        <label>300</label>
      </td>
      <td>
        <label>Investor C</label>
      </td>
    </tr>
    <tr>
      <td>
        <label>Loan2</label>
      </td>
      <td>
        <input type='radio' name='L2' id='L2_one'></input>
        <label>100</label>
      </td>
      <td>
        <label>Investor A</label>
      </td>
      <td>
        <input type='radio' name='L2' id='L2_two'></input>
        <label>200</label>
      </td>
      <td>
        <label>Investor B</label>
      </td>
      <td>
        <input type='radio' name='L2' id='L2_three'></input>
        <label>300</label>
      </td>
      <td>
        <label>Investor C</label>
      </td>
    </tr>
    <tr>
        <td>
          <label>Loan3</label>
        </td>
        <td>
          <input type='radio' name='L3' id='L3_one'></input>
          <label>100</label>
        </td>
        <td>
          <label>Investor A</label>
        </td>
        <td>
          <input type='radio' name='L3' id='L3_two'></input>
          <label>200</label>
        </td>
        <td>
          <label>Investor B</label>
        </td>
        <td>
          <input type='radio' name='L3' id='L3_three'></input>
          <label>300</label>
        </td>
        <td>
          <label>Investor C</label>
        </td>
      </tr>
  </table>
</body>
Greg Burghardt
  • 17,900
  • 9
  • 49
  • 92
vineel
  • 3,483
  • 2
  • 29
  • 33

4 Answers4

1

try this xpath:

//td[contains(., "Investor A")]/preceding-sibling::td[descendant::input[@selected or @checked]][1]/label/text()

ruhaib
  • 604
  • 5
  • 12
  • Thanks for providing the xpath. for some reason If I have [@selected] elements are not selected. Below xpath is giving all the three loan amounts //td[contains(., "Investor A")]/preceding-sibling::td[descendant::input][1]/label/text() is there another way to get selected inputs? – vineel Aug 20 '19 at 13:58
  • i have updated the xpath to use @checked or @selected, but i have tried and even they are not working for xpath, however a solution is working in css, if you are interested in css based solution then please try this `#L1_one:checked`. if this works for you than i'll convert the above xpath to a css. – ruhaib Aug 20 '19 at 14:20
  • I will try using css, can you please provide equivalent css – vineel Aug 20 '19 at 14:29
1

Since you are looking for loan amount given the loan label (Loan1) and investor (Investor A), you can use the XPath below.

//tr[.//label[.='Loan1']]//label[.='Investor A']//preceding::label[1]
^ find a TR
    ^ that has a descendant LABEL with the loan label
                         ^ that TR has a descendant LABEL that contains the investor name
                                                ^ then go back up the DOM and find the first LABEL

That will return "100".

You can insert whatever loan and investor label you want into the XPath and get the loan amount of anything you want.

"//tr[.//label[.='#{loanLabel}']]//label[.='#{investorLabel}']//preceding::label[1]"

See Ruby: Merging variables in to a string

JeffC
  • 22,180
  • 5
  • 32
  • 55
  • Thanks for providing the code. I need to fetch the element only if the radio button next to the loan amount is selected. As ruhaib suggested I used input[@selected] in the xpath but it is not working. – vineel Aug 20 '19 at 14:16
  • 1
    As far as I know, you can't get the selected elements using XPath because that value isn't reflected in the HTML (a default might be but not one that's been selected). You will have to loop through all, find the ones that are checked using Selenium, and then go back and find the elements based on what you found. – JeffC Aug 20 '19 at 14:21
  • Why did your post get so many downvotes @JeffC? I tried to fix few of them. – SIM Aug 26 '19 at 15:21
  • Well it only got one downvote. It's usually a particular person that revenge downvotes. You downvote his post and leave a constructive criticism or feedback and he downvotes a few of your answers. It's been happening for years. I flag from time to time and he has been banned before but he keeps doing it. I appreciate the upvotes... but you should upvote only if you think it warrants it, not just because it was downvoted. – JeffC Aug 26 '19 at 18:07
0

Here example how you can get radio buttons depends on Loan label and value:

//tr[.//label[.='Loan1']]//td[./label[.='100']]/input
//tr[.//label[.='Loan1']]//td[./label[.='300']]/input

//tr[.//label[.='Loan2']]//td[./label[.='100']]/input

//tr[.//label[.='Loan3']]//td[./label[.='200']]/input
Sers
  • 12,047
  • 2
  • 12
  • 31
0

If the selection status of the radio buttons has changed since the HTML was loaded what you're trying to do isn't possible with XPath. This is because XPath doesn't have access to the properties of the inputs which reflect the current state (it can only access the attributes). You also have the issue that none of the <label> elements are actually associated with any of the inputs they refer to (if you are the person creating this HTML you should really fix that). CSS does have access to the current state of the page and all of the radios you're interested in appear to have ids ending in _one so we can use that to find the relevant elements. The CSS would be

input[id$="_one"]:checked + label

since you want the text of the label elements that CSS will find and you indicate you're using Capybara it would then be

texts = all(:css, 'input[id$="_one"]:checked + label').map(&:text)

Note: this doesn't actually use the text "Investor A" to find elements you're interested in. If the ids are not reliable and using the "Investor A" text is important then it's not possible to do this using a single XPath or CSS with the way the HTML is structured.

Thomas Walpole
  • 48,548
  • 5
  • 64
  • 78