1

For a curiosity I tried to create an xpath of orangehrm website leave portal and I have tried to make an xpath with 2 contains and xpath axes

//*[contains(@class,'oxd-main-menu-item active') and 
   (contains(@class,'oxd-main-menu-item-wrapper')/child::a) ]
  • contains(@class,'oxd-main-menu-item active') : link to click
  • contains(@class,'oxd-main-menu-item-wrapper')/child::a) : parent of link access through the xpath axes

I am aware that this method is possible

//div[contains(@class, 'measure-tab') and contains(., 'someText')]

but my question is, is it possible can we also add xpath axes with one of the contains function?

enter image description here

All the things I have tried I have added in Description

Mads Hansen
  • 63,927
  • 12
  • 112
  • 147
Akash
  • 11
  • 1
  • Can you elaborate, what element are you trying to get? – Yaroslavm Jul 28 '23 at 20:45
  • Please, take some time to read [how to ask](/help/how-to-ask) and [How to create a Minimal, Reproducible Example](/help/minimal-reproducible-example) – LMC Jul 28 '23 at 20:50
  • _leave portal_: which element? – undetected Selenium Jul 28 '23 at 21:29
  • You haven't actually said what you are trying to achieve; it's difficult to infer your requirements from code that is clearly wrong. The reason your code doesn't work is that contains() returns a boolean and booleans don't have children. – Michael Kay Jul 29 '23 at 09:18

2 Answers2

0

In short and crisp, yes you create xpath with multiple contains() function as follows:

//div[contains(@class, 'measure-tab') and contains(., 'someText')]

This usecase

Given the HTML:

<li class="oxd-main-menu-item-wrapper" data-v-6475d26d="" data-v-636d6b87="">
    <a class="oxd-main-menu-item active" href="/web/index.php/leave/viewLeaveModule" data-v-6475d26d="">
        <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 500 500" role="presentation" class="oxd-icon oxd-main-menu-item--icon" data-v-bddebfba="" data-v-6475d26d="">
            <g fill="currentColor">
                <path ...></path>
            </g>
        </svg>
        <span class="oxd-text oxd-text--span oxd-main-menu-item--name" data-v-7b563373="" data-v-6475d26d="">Leave</span>
    </a>
</li>

The desired <a> element:

<a class="oxd-main-menu-item active" href="/web/index.php/leave/viewLeaveModule" data-v-6475d26d="">

is within it's parent <li> element:

<li class="oxd-main-menu-item-wrapper" data-v-6475d26d="" data-v-636d6b87="">

To identify the element you can use either of the following locator strategies:

  • Using cssSelector:

    li.oxd-main-menu-item-wrapper > a.oxd-main-menu-item.active
    
  • Using cssSelector and contains clause:

    li[class*='oxd-main-menu-item-wrapper'] > a[class*='oxd-main-menu-item']
    
  • Using xpath:

    //li[@class='oxd-main-menu-item-wrapper']/a[@class='oxd-main-menu-item active']
    
  • Using xpath and contains():

    //li[contains(@class, 'oxd-main-menu-item-wrapper')]/a[contains(@class, 'oxd-main-menu-item active')]
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
0

If your question is whether you can apply an XPath to the contains() function, the answer is no. That function returns a boolean and you can't XPath off that.

However, you can achieve what (I think) you want.

Instead of (contains(@class,'oxd-main-menu-item-wrapper')/child::a) you can instead use:

//*[contains(@class,'oxd-main-menu-item active') and 
    contains(@class,'oxd-main-menu-item-wrapper') and 
    child::a ]

to test whether the matched element has a class that contains those two values and has a child a element.

Mads Hansen
  • 63,927
  • 12
  • 112
  • 147
  • I know exactly what you mean by "you can't XPath off a boolean", but it's very informal terminology: the rule in the spec is that for an axis expression, the context item must be a node. – Michael Kay Jul 29 '23 at 23:10