1

I am using XPath to search the below web elements. My XPath command returns 2 nodes. I am trying to retrieve 1 node. Unfortunately, the web page I am testing has the exact same elements and text. Can you help? I am using ChroPath to test my XPath. Thanks in advance!

XPath command is:

//*[@id="'tabMiddleDIV_Port Details'"]

The HTML Elements from my Web Page are:

<div class="DNMSTabClass" style="visibility: visible; display: inline;">
    <div id="'tabLeftDIV_Port Details'" class="DNMS_Tab DNMS_Tab_Corners DNMS_Tab_Left_On"></div>
    <div id="'tabMiddleDIV_Port Details'" class="DNMS_Tab DNMS_Tab_Title DNMS_Tab_Title_On DNMS_Tab_Middle DNMS_Tab_Middle_On" style="">&nbsp;Port Details</div>
    <div id="'tabRightDIV_Port Details'" class="DNMS_Tab DNMS_Tab_Corners DNMS_Tab_Right_On"></div>
</div>


<div class="DNMSTabClass" style="visibility: hidden; display: none;">
    <div id="'tabLeftDIV_Port Details'" class="DNMS_Tab DNMS_Tab_Corners DNMS_Tab_Left_Off"></div>
    <div id="'tabMiddleDIV_Port Details'" class="DNMS_Tab DNMS_Tab_Title DNMS_Tab_Title_Off DNMS_Tab_Middle DNMS_Tab_Middle_Off" style="">&nbsp;Port Details</div>
    <div id="'tabRightDIV_Port Details'" class="DNMS_Tab DNMS_Tab_Corners DNMS_Tab_Right_Off"></div>
</div>
1

Simply add [1] to the end of your xpath.

//*[@id="tabMiddleDIV_Port Details"][1]

Alternatively if the returned elements are not the same time, i.e. if one is a button and one is a div or something, then specify the tagname instead of using "*"

//button[@id="tabMiddleDIV_Port Details"]

But if they're both the same element type and have the same id (which is not supposed to happen) then specify the one you want inside brackets.

edit: After reviewing your added HTML code, I would offer the following longer, but workable xpath without a subscript:

//div[@class="DNMSTabClass" and @style="visibility: visible; display: inline;"]/div[@id="tabMiddleDIV_Port Details"]

Here you first locate the parent div tag, then your xpath for the second div will find just that child div with the id tag specified instead of both shown in your HTML code segment.

  • This still returns 2 matching nodes: //*[@id="'tabMiddleDIV_Port Details'"][1] I tried adding quotes and no success. – joe john Jun 29 '18 at 21:38
  • It should work. You could try it with single quotes instead of double quotes. Also try my second example. – Bill Hileman Jun 30 '18 at 0:12
  • Hi @Bill! Your solution won't work for OP's case. It will only work if the elements are the siblings. – Alexey R. Jun 30 '18 at 21:04
  • You are right Lexey. I used the below code and it worked: – joe john Jul 2 '18 at 12:59
  • (//div[@id="'tabMiddleDIV_Port Details'"])[1] – joe john Jul 2 '18 at 12:59
1

Simple adding [1] to the end of your path will not work since the elements reside in the different branches of DOM tree

Use

(//*[@id="'tabMiddleDIV_Port Details'"])[1]

Below are some examples:

<div>
    <div>
        <div id="abc"/>
    </div>
    <div>
        <div id="abc"/>
    </div>
</div>

For example the xpath //*[@id='abc'][1] will get into the first div block, find all matching nodes with id='abc' and take the first one, then get into the second div block, find all matching nodes with id='abc' and take the first one. Hence the total number of the found nodes will be 2.

Another remarkable example is the xpath //*[@id='abc'][2]. One could expect that the second <div id="abc"/> will be returned, however according to the algorithm described in the first example: it will get into the first div block, find all matching nodes with id='abc' and take the second one (which does not exist since there is only one matching node), then get into the second div block, find all matching nodes with id='abc' and take the second one (which does not exist since there is only one matching node). Hence the total number of the found nodes will be 0.

  • 1
    I see your point. Yours if the correct answer, thanks. Upvoted. – Bill Hileman Jun 30 '18 at 21:15
1

1) When you are identifying single element, dont use * instead specify the exact tag. So in this case it would be

//div[id="'tabMiddleDIV_Port Details'"]

2) There are 2 matching nodes, in which 1 element is in visible state and other is in invisible state. First you should know which element you want. Lets consider both the cases:

For the Element in visible state: Try the below 2 xpaths

//div[@class='DNMSTabClass' and @style='visibility: visible; display: inline;']//div[id="'tabMiddleDIV_Port Details'"]

//div[id="'tabMiddleDIV_Port Details'" and contains(@class,'DNMS_Tab_Title_On')]

For the Element in invisible state: Try the below 2 xpaths

//div[@class='DNMSTabClass' and @style='visibility: hidden; display: none;']//div[id="'tabMiddleDIV_Port Details'"]

//div[id="'tabMiddleDIV_Port Details'" and contains(@class,'DNMS_Tab_Title_Off')]
  • Thank-you all for your great answers. I do have another question. How do I perform the same task in CSS?. I tried but was not successful. Is searching for text even supported in CSS? Thanks again in advance. – joe john Jul 3 '18 at 12:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.