XPath to find ancestor node containing CSS class
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.
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, 2022Comments
-
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.
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 about 12 yearsAn upvote for the effort: my guess is that my version of selenium doesn't support
/ancestor::
-
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 about 12 yearsI 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 about 12 yearsIf 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 thatancestor::
won't work. -
Ruan Mendes about 12 yearsI will do some deeper debugging with a very simple HTML page and no other code surrounding it. Will post results here
-
Tomalak about 12 yearsI'm curious. There has to be some simple reason behind this odd behavior.
-
Ruan Mendes about 12 yearsCrazy
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 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 about 12 yearsIt'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 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 about 12 yearsYes, the problem only happens when using
/ancestor::
or/ancestor-or-self
-
Ken Palmer over 8 yearsThanks @Tomalak, your solution worked for my scenario the first time. That's handy.