Xpath syntax for "and not contains"
Asked Answered
G

4

20

Here is the XPath I'm trying to use:

//div[contains(@class='xyz ng-binding ng-scope') and not(contains(@class = 'ng-hide'))]

I'm not sure what the correct syntax for this is. Basically the HTML looks like like:

class="xyz ng-binding ng-scope typeA ng-hide"
class="xyz ng-binding ng-scope typeB ng-hide"

I want to select the case where the HTML is either typeA or typeB but does not have ng-hide.

Gandhi answered 29/10, 2014 at 21:11 Comment(0)
L
30

You could do something like this:

//div[(contains(@class,'typeA') or contains(@class,'typeB')) and not(contains(@class,'ng-hide'))]

You should also take a look at How can I match on an attribute that contains a certain string? to see why the contains() above might not match exactly what you're intending.

For example, to truly match what you are intending, you could use:

//div[(contains(concat(' ',@class,' '),' typeA ') or contains(concat(' ',@class,' '),' typeB ')) and not(contains(concat(' ',@class,' '),' ng-hide '))]

It's much easier in XPath 2.0, but I'm not sure if qtp supports it. If you could make concat(' ',@class,' ') a variable, you could clean up the XPath too.

Here's a 2.0 example just in case:

//div[tokenize(@class,'\s')=('typeA','typeB') and not(tokenize(@class,'\s')='ng-hide')]
Leggat answered 29/10, 2014 at 21:47 Comment(1)
Unfortunately QTP/UFT does indeed only use XPath 1.0.Ginaginder
F
5

In your question, the syntax is incorrect as Michael Kay has pointed out.

If I understand your question correctly, you want to select a class that contains "xyz ng-binding ng-scope" but not "ng-hide" regardless if it contains "typeA", "typeB" or not.

I would use something like this:

//div[contains(normalize-space(@class), 'xyz ng-binding ng-scope') and not(contains(@class, 'ng-hide'))]

I often find that the spaces cause problem in this situation. I have seen attributes that have leading and/or trailing spaces and/or multiple consecutive space characters in the middle. Using normalize-space eliminates that problem.

Another thing is if QTP gives us multiple match error, we can use this trick to see if the xpath is working. Then keep working on to find the correct one.

(//div[contains(normalize-space(@class), 'xyz ng-binding ng-scope') and not(contains(@class, 'ng-hide'))])[1]
Forked answered 2/11, 2014 at 14:24 Comment(0)
C
3

contains() is a function that takes two arguments: contains(A, B) returns true if B is a substring of A.

So your syntax would become valid if you replaced your "=" with ",": contains(@class, 'X') in place of contains(@class = 'X'). But I don't know whether it would then do what you want against all possible input data - that's a different question.

Cantonese answered 30/10, 2014 at 12:0 Comment(0)
A
0

you can use this expression for XPATH and contains:

//div[contains(@class, 'xyz ng-binding ng-scope')]

just use , instead of = in contains.

and when you want to combine it with not contain you can use this expression for not contains:not(expression) function. finally:

//div[contains(@class, 'xyz ng-binding ng-scope') and not(contains(@class , 'ng-hide'))]
Aurore answered 15/9, 2019 at 7:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.