:在Nokogiri有CSS伪类

我正在寻找伪类:has在Nokogiri有 。 它应该像jQuery的选择器一样工作。

例如:

 
  • ex1

    sdfsdf
  • ex2

  • ex3

  • CSS选择器应该只返回第一个链接,一个带有非空的span.string兄弟。

    在jQuery中,这个选择器运行良好:

     $('li:has(span.string:not(:empty))>h1>a') 

    但不是在Nokogiri:

     Nokogiri::HTML(html_source).css('li:has(span.string:not(:empty))>h1>a') 

    :not and :empty运行良好,但不是:has


    1. 在Nokogiri有CSS选择器的文档吗?
    2. 也许有人可以写一个自定义:has伪类吗? 以下是如何编写:regexp选择器的示例 。
    3. 我可以选择使用XPath。 如何为li:has(span.string:not(:empty))>h1>a编写XPath li:has(span.string:not(:empty))>h1>a

    Nokogiri当前实现的问题:has()是它创建了XPath,要求内容是直接子,而不是任何后代:

     puts Nokogiri::CSS.xpath_for( "a:has(b)" ) #=> "//a[b]" #=> Should output "//a[.//b]" to be correct 

    要使此XPath与jQuery相匹配,您需要允许span作为后代元素。 例如:

     require 'nokogiri' d = Nokogiri.XML('') d.at_css('a:has(b)') #=> #]>]> d.at_css('a:has(c)') #=> nil d.at_xpath('//a[.//c]') #=> #]>]> 

    对于您的具体情况,这里是完整的“破损”XPath:

     puts Nokogiri::CSS.xpath_for( "li:has(span.string:not(:empty)) > h1 > a" ) #=> //li[span[contains(concat(' ', @class, ' '), ' string ') and not(not(node()))]]/h1/a 

    在这里它是固定的:

     # Adding just the .// //li[.//span[contains(concat(' ', @class, ' '), ' string ') and not(not(node()))]]/h1/a # Simplified to assume only one CSS class is present on the span //li[.//span[@class='string' and not(not(node()))]]/h1/a # Assuming that `not(:empty)` really meant "Has some text in it" //li[.//span[@class='string' and text()]]/h1/a # ..or maybe you really wanted "Has some text anywhere underneath" //li[.//span[@class='string' and .//text()]]/h1/a # ..or maybe you really wanted "Has at least one element child" //li[.//span[@class='string' and *]]/h1/a 

    Nokogiri没有:has选择器,这里有关于它做什么的文档: http :has //ruby.bastardsbook.com/chapters/html-parsing/#h-2-2

    好的,我找到了一个可能对某人有用的解决方案。

    自定义伪类:custom_has

     class MyCustomSelectors def custom_has node_set, selector node_set.find_all { |node| node.css(selector).present? } end end #usage: doc.css('li:custom_has(span.string:not(:empty))>h1>a',MyCustomSelectors.new) 

    我为什么声明:custom_has不仅仅是:has吗? 因为它已经宣布了。 在Nokogiri repo中测试 :has选择器,但它们不起作用。 我向作者报告了这个问题 。

    Nokogiri允许在同一对象上链接.css().xpath() 。 因此,只要你想使用:has ,只需结束当前的.css()调用并添加.xpath(..) (父选择器)。 您甚至可以从另一个.css()调用恢复您的选择,从xpath()停止开始!

    例:

    这是来自维基百科的一些HTML:

       Origin   Edinburgh Scotland     Genres   Electronica IDM ambient downtempo trip hop     Labels   Warp Skam Music70   

    假设您要选择包含href="/Music_genre"链接的

    之后的

    一个

    内的所有元素。

     @artistPage.css("table th > a[href='https://stackoverflow.com/wiki/Music_genre']").xpath("..").css("+ td a") 

    这将返回每个类型列表的所有

    现在好好衡量一下,让我们抓住所有那些的内部文本并将它们放在一个数组中。

     @genreLinks = @artistPage.css("table th > a[href='https://stackoverflow.com/wiki/Music_genre']").xpath("..").css("+ td a") @genres = [] @genreLinks.each do |genreLink| @genres.push(genreLink.text) end