1

:hasのこぎりで疑似クラスを探しています。hasjQueryのセレクターと同じように機能するはずです。

例えば:

<li><h1><a href="dfd">ex1</a></h1><span class="string">sdfsdf</span></li>
<li><h1><a href="dsfsdf">ex2</a></h1><span class="string"></span></li>
<li><h1><a href="sdfd">ex3</a></h1></li>

CSSセレクターは、最初のリンク、つまり空でないspan.string兄弟を持つリンクのみを返す必要があります。

jQueryでは、このセレクターはうまく機能します。

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

しかし、のこぎりではありません:

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

:not:emptyうまく機能しますが、そうではありません:has


  1. NokogiriにCSSセレクターのドキュメントはありますか?
  2. :has多分誰かがカスタム疑似クラスを書くことができますか?セレクターの書き方の例を次に示します。:regexp
  3. オプションで、XPathを使用できます。XPathを作成するにはどうすればよいli:has(span.string:not(:empty))>h1>aですか?
4

4 に答える 4

5

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('<r><a/><a><b><c/></b></a></r>')
d.at_css('a:has(b)')    #=> #<Nokogiri::XML::Element:0x14dd608 name="a" children=[#<Nokogiri::XML::Element:0x14dd3e0 name="b" children=[#<Nokogiri::XML::Element:0x14dd20c name="c">]>]>
d.at_css('a:has(c)')    #=> nil
d.at_xpath('//a[.//c]') #=> #<Nokogiri::XML::Element:0x14dd608 name="a" children=[#<Nokogiri::XML::Element:0x14dd3e0 name="b" children=[#<Nokogiri::XML::Element:0x14dd20c name="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
于 2012-08-01T17:36:48.187 に答える
1

わかりました、私は多分誰かのために役立つであろう解決策を見つけました。

カスタム疑似クラス: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ですか?すでに宣言されているからです。のこぎりレポにはセレクターのテスト:hasがありますが、動作していません。この問題を作者に報告しました。

于 2012-08-01T13:59:52.913 に答える
1

Nokogiri には:hasセレクターがありません。 これが何をするかについてのドキュメントは次のとおりです

于 2012-08-01T13:39:18.757 に答える