XPath to find ancestor node containing CSS class

18,471

This should select the element you want

./ancestor::div[contains(concat(' ', @class, ' '), ' x-grid-view ')][1]

In plain English: Of all the ancestor div elements that have ' x-grid-view ' in their class, select the first (closest) one.

Notes:

  • I concat spaces as a defensive measure to prevent partial matches.
  • current() is an XSLT function, not an XPath one. It has no meaning outside of XSLT. The current node is expressed as . in XPath.
Share:
18,471
Ruan Mendes
Author by

Ruan Mendes

Client side/ middle tier web developer. Have programmed in C, C++, C#, Groovy, Java, ActionScript, Lingo, JavaScript, PHP, TypeScript. Basic My language of choice is TypeScript, on the browser or Deno. Technologies I've worked with substantially: HTML, CSS, DOM, AJAX, Angular, React, jQuery, Google Closure Templates, Sencha touch, Ext-JS ASP, PHP, JSP, Struts, Velocity, Node.js, Kohana Windows, Unix, OpenVMS, Solaris Ant, make, maven XML-RPC, RESTful services JSUnit, JUnit, PhpUnit, Karma, Jasmine, js-test-driver, NUnit, YUI tests Selenium, Cucumber, Cypress Grails ASP.NET

Updated on June 08, 2022

Comments

  • Ruan Mendes
    Ruan Mendes about 2 years

    I am writing some Selenium tests and I need to be able to find an ancestor of a WebElement that I have already found.

    This is what I'm trying but is returning no results

    // checkbox is also a WebElement
    WebElement container = checkbox.findElement(By.xpath(
        "current()/ancestor-or-self::div[contains(@class, 'x-grid-view')]") );
    

    The image below shows the div that I have selected highlighted in dark blue and the one I want to find with an arrow pointing at it.

    enter image description here

    UPDATE Tried prestomanifesto's suggestion and got the following error

    [cucumber]       org.openqa.selenium.InvalidSelectorException: The given selector ./ancestor::div[contains(@class, 'x-grid-view']) is either invalid or does not result in a WebElement. The following error occurred:
    [cucumber]       [InvalidSelectorError] Unable to locate an element with the xpath expression ./ancestor::div[contains(@class, 'x-grid-view']) because of the following error:
    [cucumber]       [Exception... "The expression is not a legal expression."  code: "51" nsresult: "0x805b0033 (NS_ERROR_DOM_INVALID_EXPRESSION_ERR)"  location: "file:///C:/Users/JUAN~1.MEN/AppData/Local/Temp/anonymous849245187842385828webdriver-profile/extensions/fxdriv
    

    Update 2 Really weird, even by ID is not working

    [cucumber]       org.openqa.selenium.NoSuchElementException: Unable to locate element:{"method":"xpath","selector":"./ancestor::div[@id='gridview-1252']"}
    

    Update 3

    The following XPATH works, but is brittle

    ../../../../../../../*
    

     

  • Ruan Mendes
    Ruan Mendes about 12 years
    An upvote for the effort: my guess is that my version of selenium doesn't support /ancestor::
  • Tomalak
    Tomalak about 12 years
    @Juan: This would be most unusual. Did you find any XPath that returns a node (apart from those of the ../../* variety)?
  • Ruan Mendes
    Ruan Mendes about 12 years
    I haven't tried your latest suggestion ./ancestor::*[local-name()='div' and contains(@class, 'x-grid-view')], will try it as soon as my environment is ready to run tests again, I broke a few things... thanks again
  • Tomalak
    Tomalak about 12 years
    If that happens to work, you are facing a namespace issue. If it doesn't work, you'll have to do some debugging as to what .findElement(By.xpath(... actually supports. It doesn't make any sense at all that ancestor:: won't work.
  • Ruan Mendes
    Ruan Mendes about 12 years
    I will do some deeper debugging with a very simple HTML page and no other code surrounding it. Will post results here
  • Tomalak
    Tomalak about 12 years
    I'm curious. There has to be some simple reason behind this odd behavior.
  • Ruan Mendes
    Ruan Mendes about 12 years
    Crazy ancestor::*[local-name()='div' and contains(@class, 'x-grid-view')] seems to do the trick. It's weird since I don't need that qualification in any of my other queries
  • Tomalak
    Tomalak about 12 years
    @Juan Then this looks a lot like an XML namespace issue. Your document seems to be in XHTML mode for some reason. That's the direction you should be digging.
  • Ruan Mendes
    Ruan Mendes about 12 years
    It's weird that the following xpath works if I use the $x() function in chrome and Firefox $x("id('gridview-1274')//span[contains(text(), 'cdk2')]/ancestor::div[contains(@class, 'x-grid-view')]")
  • Tomalak
    Tomalak about 12 years
    @Juan Nice, I did not even know about the $x() function until now. As I said, the XPath itself is fine. Does //body select anything in selenium?
  • Ruan Mendes
    Ruan Mendes about 12 years
    Yes, the problem only happens when using /ancestor:: or /ancestor-or-self
  • Ken Palmer
    Ken Palmer over 8 years
    Thanks @Tomalak, your solution worked for my scenario the first time. That's handy.