的problem with Nokogiri's current implementation of :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
':has' pseudo是一个jQuery扩展,所以我猜Nokogiri不支持它,因为它不是任何标准的一部分。 – 2012-08-01 13:22:24
好的,所以我最近的3个问题都适合 – rogal111 2012-08-01 13:26:42
根据你提供的HTML,// li [span [@ class =“string”] [count(node())> 0]]/h1/a'节点与'ex1'内容(第一个“a”)。 – 2012-08-01 13:42:24