Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
pivotal-benchmark opened this issue Oct 13, 2010 · 6 comments
Assignees

Comments

@pivotal-benchmark
Copy link

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>
    <div id="inner"/>
  </div>
</div>

(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
Copy link
Member

On it

@flavorjones
Copy link
Member

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
Copy link
Contributor

mgenereu commented Nov 9, 2010

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

@flavorjones
Copy link
Member

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.

Thanks!

@Phrogz
Copy link

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
Copy link
Member

PR #1852 addresses this.

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

No branches or pull requests

4 participants