2

I want to write xpath for the following div:

<div class='someclass' id='someid'>:TEST&nbsp;SELENIUM&nbsp;1234<div>

Please note :

  1. tag can be anything such as div, span ,or anchor tag.
  2. &nbsp; can be present anywhere in the text.

What I have tried so far :

//div[contains(text(),":TEST SELENIUM 1234")]

//div[contains(text(),":TEST{&nbsp;}SELENIUM{&nbsp;}1234")] 

//div[contains(text(),":TEST&nbsp;SELENIUM&nbsp;1234")] 

//div[normalize-space(text()) = ':TEST SELENIUM 1234']

//div[normalize-space(text()) = ':TEST{&nbsp;}SELENIUM{&nbsp;}1234']

//div[normalize-space(text()) = ':TEST&nbsp;SELENIUM&nbsp;1234']

//div[normalize-space(.) = ':TEST SELENIUM 1234']  

//div[normalize-space(.) = ':TEST{&nbsp;}SELENIUM{&nbsp;}1234']  

//div[normalize-space(.) = ':TEST&nbsp;SELENIUM&nbsp;1234']  

//div[normalize-space(.) = ':TEST{\u00a0}SELENIUM{\u00a0}1234']  

//div[normalize-space(.) = ':TEST${nbsp}SELENIUM${nbsp}1234']  

What has worked for me (thanks to @Andersson)

//div[starts-with(text(), ":TEST") and substring(text(), 7)="SELENIUM" and  substring(text(), 16)="1234"]  

This is more of a work around and would work only for known Strings.

These are the SO post which I have already followed :

Link1
Link2

Any help will be highly appreciated.

Andrei Suvorkov
  • 5,559
  • 5
  • 22
  • 48
cruisepandey
  • 28,520
  • 6
  • 20
  • 38
  • How are you testing this? Is it `xPath 2.0`, right? In Chrome and Firefox it is not working – Andrei Suvorkov Aug 07 '18 at 05:39
  • @AndreiSuvorkov : I want to click on check boxes based on names. Names can be extracted only form the divs. Yes I'm using `xpath2.0` .No , it's not working in FF and chrome. If you know any workaround , that'd be really helpful. – cruisepandey Aug 07 '18 at 05:56
  • 1
    Why don't you use `//div[starts-with(text(), ":TEST") and contains(text(), "SELENIUM")]`? This will return all divs which has both text irrespective of spaces between them. and you can add more `and` condition as needed. – Raj Aug 07 '18 at 06:01
  • 1
    If you want to make it generic instead of dev, use this code: `//*[starts-with(text(), ":TEST") and contains(text(), "SELENIUM")]` – Raj Aug 07 '18 at 06:01
  • Instead of `starts-with`, you can use simply `contains` too. E.g. `//*[contains(text(), ":TEST") and contains(text(), "SELENIUM")]` – Raj Aug 07 '18 at 06:02
  • And this works on chrome. – Raj Aug 07 '18 at 06:03
  • @RajKamal `starts-with` is better – Andrei Suvorkov Aug 07 '18 at 06:03
  • @RajKamal : The text is not generic , it can be `xyz&nbsp1234` also – cruisepandey Aug 07 '18 at 06:03
  • 1
    @AndreiSuvorkov Yes! I just gave a suggestion, in case , if we need to use multiple `contains`, we can do so. – Raj Aug 07 '18 at 06:04
  • @cruisepandey If text is not generic , what you want to validate?? I assumed that you are looking for an element with some text? – Raj Aug 07 '18 at 06:05
  • whatever text is, you can pass that text to create xpath at runtime.. That's what I mean. – Raj Aug 07 '18 at 06:06
  • @RajKamal : Yes. I am reading text from excel file and creating an item in UI. That particular text can be anything , as I do not have control over it. – cruisepandey Aug 07 '18 at 06:06
  • 1
    But you know the text what you are passing in excel will be used to create element. Use same text to create xpath at runtime. – Raj Aug 07 '18 at 06:07
  • your solution `//*[contains(text(), ":TEST") and contains(text(), "SELENIUM")]` will be good but if I have 3-4 sub strings then it wouldn't work I guess – cruisepandey Aug 07 '18 at 06:07
  • For your case, xpath string will have to be designed at runtime, depending on how many `contains` condition, you need. – Raj Aug 07 '18 at 06:09
  • @RajKamal : Yes , can you give the generic solution, that'd really helpful. – cruisepandey Aug 07 '18 at 06:10
  • @RajKamal : I mean how can we have multiple contains as per the requirement while designing the xpath. – cruisepandey Aug 07 '18 at 06:14

2 Answers2

1

According to the conversation above, you can use this sample xPath builder(JAVA):

public class Test {
    public static void main(String[] args) {
        String s = ":TEST&nbsp;SELENIUM&nbsp;1234";
        String[] parts = s.split("&nbsp;");
        StringBuilder xpath = new StringBuilder("//*");

        for (int i = 0; i < parts.length; i++){
            xpath.append((i == 0) ? "[contains(text(), '" + parts[i] + "')" : " and contains(text(), '" + parts[i] + "')");
        }
        xpath.append("]");

        System.out.println(xpath);
    }
}

Output:

//*[contains(text(), ':TEST') and contains(text(), 'SELENIUM') and contains(text(), '1234')]
Andrei Suvorkov
  • 5,559
  • 5
  • 22
  • 48
1

In Python I would do

required_div = [div for div in driver.find_elements_by_xpath('//div') if div.text == ':TEST SELENIUM 1234'][0] 

to find required node by its complete text content ignoring non-breaking space chars

P.S. Again it's just a workaround, but it seem to be quite simple solution

Andersson
  • 51,635
  • 17
  • 77
  • 129