1

I have the html like below. And I want those webelments through CSSselector or xpath which don't have div< class="locked" Can anyone help me. The output should come as two webelements which are "I am free video1" & I am free video2.

Locked Video

<div class="item video " data-reactid="165">
    <a href="/video/peppa/xyz" data-reactid="166">
        <div class="LazyLoad is-visible" style="height:168px;" data-reactid="167">
            <img class="visual-video" src="https://abc.jpg?w=300" alt="I am locked video">
        </div>
        <p class="text" data-reactid="168">Episodio completo</p>
        <img class="video" src="/images/icon-video.svg" data-reactid="169">
        <div class="locked" data-reactid="170">
            <div class="opaque" data-reactid="171"></div>
            <p data-reactid="172">Activa tu cuenta</p>
        </div>
    </a>
    <p class="name" data-reactid="173">I am locked video</p>
</div>

Free Video 1

<div class="item video " data-reactid="185">
    <a href="/video/ghi" data-reactid="186">
        <div class="LazyLoad is-visible" style="height:168px;" data-reactid="187">
            <img class="visual-video" src="https://ghi.jpg?w=300" alt="I am free video1">
        </div>
        <p class="text" data-reactid="188">Episodio completo</p>
        <img class="video" src="/images/icon-video.svg" data-reactid="189">
    </a>
    <p class="name" data-reactid="190">I am free video1</p>
</div>

Free Video 2

<div class="item video " data-reactid="192">
    <a href="/video/sddfo" data-reactid="193">
        <div class="LazyLoad is-visible" style="height:168px;" data-reactid="194">
            <img class="video" src="/images/icon-video.svg" data-reactid="195">
        </div>
    </a>
    <p class="name" data-reactid="196">I am free video2</p>
</div>
Pedro Rodrigues
  • 1,662
  • 15
  • 19
asinha
  • 337
  • 1
  • 6
  • 24

4 Answers4

1

This is relatively straightforward to do with XPath:

//div[contains(@class, 'video') and not(div[@class='locked'])]

Note that, strictly speaking, to avoid false positives, you should be handling the class attribute values properly:

//div[contains(concat(' ', @class, ' '), ' video ') and 
      not(div[contains(concat(' ', @class, ' '), ' locked ')])]
Community
  • 1
  • 1
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • I have already tried these above solutions and it does not work. Also tried something like //a/div[contains(@class, 'LazyLoad is-visible') and not(contains(@class, 'locked'))] but did not work – asinha May 18 '17 at 09:01
0

If your CSS implementation supports the :not() "pseudo-element" selector, then you could try

.item.video:not(div.locked) p.name

cf. https://www.w3.org/wiki/CSS/Selectors/pseudo-classes/:not

That may be overly specific as I don't understand the context of the mark-up.

For XPath, I think it would be something like this:

//div[contains(@class, 'video') and not(.//div[contains(@class, 'locked')])]//p[contains(@class,'name')

Jon Wolski
  • 2,293
  • 2
  • 19
  • 21
  • I have gone through these above as these solutions are available since long time however it does not work. .item.video div:not(.locked) this won't work because it would find div class="LazyLoad is-visible and div class="opaque" – asinha May 18 '17 at 08:38
  • I misunderstood the question. What is it that you want your returned (selected) elements to be? You want the "webelements" with the text you mentioned. Does that mean you want the `

    ` elements? If so, @alexce's answer is probably the best place to start. `//div[contains(@class, 'video') and not(a/div[@class='locked'])]/p[contains(@class,'name')` might do the trick

    – Jon Wolski May 18 '17 at 13:46
  • I was looking for the list of webelements which don't have the locked video. Then I would click on the first one from that list. Anyway I used the xpath as below and it worked. //div[contains(@class, 'item video')]/a[not (div[@class='locked']) and (div[@class='LazyLoad is-visible']) and (img[@class='video'])] – asinha May 18 '17 at 20:11
0

Are those Texts are constant? If yes, then you can take elements from text.

How do I find an element that contains specific text in Selenium Webdriver (Python)?

Community
  • 1
  • 1
0

This is an interesting question and i came up with a idea.

My idea is to capture all the videos first and then remove the locked videos from all videos list. Code is below,

  //Gather all the videos
  List<WebElement> all = driver.findElements(By.xpath("//div[@class,'item video']/a"));

  //Gather the videos which has locked
  List<WebElement> locked = driver.findElements(By.xpath("//div[@class,'item video']//div[@class,'locked']"));

  //Remove the locked videos from all videos
  for(WebElement lock : locked)
  {
      all.remove(lock);
  }


  //Now "all" contains only the free videos.
  for(WebElement free : all)
  {
      //Do the stuff
  }

Note - Not tested. Kindly check and let me know if works

santhosh kumar
  • 1,981
  • 1
  • 9
  • 28
  • I tried this one before but I used the list of substract and did not work so gave up. Anyway I used the xpath as //div[contains(@class, 'item video')]/a[not (div[@class='locked']) and (div[@class='LazyLoad is-visible']) and (img[@class='video'])]"; The one I tried like List allVideos = driver.findElements(By.cssSelector(Properties.videos)); List allLockedVideos = driver.findElements(By.cssSelector(Properties.lockedVideo)); List allFreeVideos = subtract(allVideos, allLockedVideos); allFreeVideos.get(0).click(); – asinha May 18 '17 at 11:31
  • not sure about the css you have written. It has to be img.videos and div.locked. Can you check with the xpath that i have given. Try printing the number of elements in each list for debugging. – santhosh kumar May 18 '17 at 11:41
  • I was looking for the list of webelements which don't have the locked video. Then I would click on the first one from that list. Anyway I used the xpath as below and it worked. //div[contains(@class, 'item video')]/a[not (div[@class='locked']) and (div[@class='LazyLoad is-visible']) and (img[@class='video'])] – asinha May 18 '17 at 20:12