Let's say you want to find the element with the text hello
in the following DOM tree:
<html>
<body>
<article>
<strong>hello</strong>
<strong>world</strong>
</article>
</body>
</html>
You might think of using jQuery's
:contains
Show archive.org snapshot
selector:
$(":contains('hello')")
Unfortunately that returns a lot more elements than you expect:
[ <html>...<html>,
<body>...</body>,
<article>...</article>,
<strong>hello</strong> ]
The reason for this is that all of these elements contain the word hello
!
What you need to do instead is to find all elements containing "hello" which don't have a descendant containing "hello":
$(":contains('hello'):not(:has(:contains('hello')))")
Note that :contains
and :has
are non-standard selectors that are available in jQuery's selector engine only. You can't use them in other libraries that match CSS selectors, such as Nokogiri or Capybara.
You can do the same with an XPath expression, though. So e.g. in Capybara:
page.find(:xpath, ".//*[contains(text(), 'hello') and not (./*[contains(text(), 'hello')])]")