Reputation: 1118
I have html like
<html>
<body>
<div class='open'>
<h1>Title</h1>
<div>Opened</div>
</div>
</body>
</html>
And in my Selenium WebDriver 3 tests I am trying to select the div.open element using the following xpath:
//h1/../.[contains(@class, 'open')]
In the following command in c#:
driver.FindElement(By.XPath("//h1/../.[contains(@class, 'open')]"));
Which results in
OpenQA.Selenium.InvalidSelectorException : invalid selector: Unable to locate an element with the xpath expression //h1/../.[contains(@class, 'open')] because of the following error:: Failed to execute 'evaluate' on 'Document': The string '//h1/../.[contains(@class, 'open')]' is not a valid XPath expression.
Searching by the same Xpath in Firefox console successfully locates the element.
Any ideas why WebDriver considers this xpath invalid?
Note: my example is of course simplified
Upvotes: 1
Views: 799
Reputation: 89325
I would say that's probably down to the specification doesn't explicitly state whether predicate after abbreviated step i.e .
and ..
should be allowed, neither the specification ever mention an example involving predicate after abbreviated step.
So some XPath implementations just don't support it. One of these, I noticed, is XPath implementation in .NET framework. Other implementations explicitly disallow it, and even provide useful suggestion for the user to replace .
or ..
in their XPath with the equivalent unabbreviated expression, in order, self::node()
or parent::node()
, for example, the implementation used by xpathtester. But as you noticed, other implementations might support it.
As of workaround, there are many alternatives XPath which equivalent or close enough to you original attempted XPath. The easiest is to expand the .
to its unabbreviated expression, as I mentioned above. Personally, I prefer not to go down the tree and then back up to return a parent element, if possible. Instead, just stop at the parent element which we want to return, and check for the child in predicate :
//*[contains(@class, 'open')][h1]
Upvotes: 3
Reputation: 331
If you want to reference "div" with respect to "h1" tag then you can change the xpath to following:
//h1/ancestor::div[contains(@class, 'open')]
Upvotes: 1
Reputation: 193338
Instead of //h1/../.[contains(@class, 'open')]
xpath
can you try //div[@class='open']
xpath
Upvotes: 0