:has() selector should match against all descendants, not just direct children #350

pivotal-benchmark opened this Issue Oct 13, 2010 · 5 comments


None yet
4 participants

From http://api.jquery.com/has-selector/:

The expression $('div:has(p)') matches a <div> if a <p> exists anywhere among its descendants, not just as a direct child.

So I would expect:

Nokogiri::CSS.xpath_for("#outer:has(#inner)")  # => ["//*[@id = 'outer' and .//*[@id = 'inner']]"]

But, instead:

Nokogiri::CSS.xpath_for("#outer:has(#inner)")  # => ["//*[@id = 'outer' and *[@id = 'inner']]"]

which doesn't match:

<div id="outer">
    <div id="inner"/>

(I think that's the right way to match all descendants, but I'm not totally solid on XPath. It works in my testing.)


flavorjones commented Oct 13, 2010

On it


flavorjones commented Oct 27, 2010

Just to be clear, to anyone following this issue: ":has()" does indeed match all descendents for most queries. Used in combination with an element id ("#inner"), though (and perhaps one or two other types of selectors), the xpath doesn't work.

It's not clear to me yet whether this is an xpath interpreter bug in libxml, or whether we simply need to restructure the xpath query in these cases. Need to investigate more.

mgenereu commented Nov 9, 2010

Got bit by this. Want me to write test cases?


flavorjones commented Nov 9, 2010

Sure, test cases of the sort found in https://github.com/tenderlove/nokogiri/blob/master/test/css/test_parser.rb#L61-64 would be great -- pass the CSS and assert on the generated XPath query string.

The point being, we need more thorough coverage of what the :has operator should generate for different (more complex) CSS queries.


Phrogz commented Aug 2, 2012

This test line is wrong:

assert_xpath  "//a[b]", @parser.parse("a:has(b)")

It should be:

assert_xpath  "//a[.//b]", @parser.parse("a:has(b)")

Similarly, the next line:

assert_xpath  "//a[b/c]", @parser.parse("a:has(b > c)")

should instead be:

assert_xpath  "//a[.//b/c]", @parser.parse("a:has(b > c)")

flavorjones added the css label Dec 31, 2014

flavorjones self-assigned this Mar 2, 2015

flavorjones removed the flavorjones label Mar 2, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment