Nokogiri:使用XPath </div>搜索<div>

时间:2009-03-16 11:03:23

标签: ruby-on-rails ruby regex xpath nokogiri

我使用Nokogiri(Rubygem)css搜索在我的html中查找某些<div>。看起来Nokogiri的css搜索不喜欢正则表达式。我想切换到Nokogiri的xpath搜索,因为它似乎支持搜索字符串中的正则表达式。

如何在xpath搜索中实现下面提到的(伪)css搜索?

require 'rubygems'
require 'nokogiri'

value = Nokogiri::HTML.parse(<<-HTML_END)
  "<html>
    <body>
      <p id='para-1'>A</p>
      <p id='para-22'>B</p>
      <h1>Bla</h1>
      <p id='para-3'>C</p>
      <p id='para-4'>D</p>
      <div class="foo" id="eq-1_bl-1">
        <p id='para-5'>3</p>
      </div>
    </body>
  </html>"
HTML_END

# my_block is given
my_bl = "1"
# my_eq corresponds to this regex
my_eq = "\/[0-9]+\/"

# FIXME The following line should be changed to an xpath search.
if my_div = value.css("div#eq-#{my_eq}_bl-#{my_bl}.foo").first
  # doing some stuff with the <p> inside the div
end

2 个答案:

答案 0 :(得分:6)

Mike Dalessio(Nokogiri核心开发人员的一半)在#nokogiri(irc.freenode.net)上给了我答案。看起来Nokogiri CSS和XPath搜索都不支持正则表达式匹配。这是他如何使用Nokogiri搜索正则表达式的解决方案:

require 'rubygems'
require 'nokogiri'

value = Nokogiri::HTML.parse(<<-HTML_END)
  "<html>
    <body>
      <p id='para-1'>A</p>
      <p id='para-22'>B</p>
      <h1>Bla</h1>
      <p id='para-3'>C</p>
      <p id='para-4'>D</p>
      <div class="foo" id="eq-1_bl-1">
        <p id='para-5'>3</p>
      </div>
      <div class="bar" id="eq-1_bl-1">
        <p id='para-5'>3</p>
      </div>
    </body>
  </html>"
HTML_END

# my_block is given
my_bl = "1"
# my_eq corresponds to this regex
my_eq = "[0-9]+"
# full regex to search for in node ids
full_regex = %r(eq-#{my_eq}_bl-#{my_bl})

filter_by_id = Class.new do
  attr_accessor :matches

  def initialize(regex)
    @regex = regex
    @matches = []
  end

  def filter(node_set)
    @matches += node_set.find_all { |x| x['id'] =~ @regex }
  end
end.new(full_regex)

value.css("div.foo:filter()", filter_by_id)
filter_by_id.matches.each do |node|
  puts node
end

答案 1 :(得分:3)

基于上述答案的简单方法:

regex = /subject|header/
headers = doc.css("table td:nth-child(1) div").find_all do
  |h| h['class'] =~ regex
end

感谢您发布此问题。