如何创建一个nokogiri不区分大小写的Xpath选择器?

Ric*_*ick 18 ruby xpath nokogiri

我正在使用nokogiri来选择'keywords'属性,如下所示:

puts page.parser.xpath("//meta[@name='keywords']").to_html
Run Code Online (Sandbox Code Playgroud)

我正在使用的其中一个页面的关键字标签带有大写"K",这促使我使查询不区分大小写.

<meta name="keywords"> AND <meta name="Keywords"> 
Run Code Online (Sandbox Code Playgroud)

所以,我的问题是:什么是使nokogiri选择案例不敏感的最佳方法?

编辑托马拉克的建议如下,对于这个具体问题非常有用.我也想用这个例子来帮助更好地理解nokogiri,并且有一些我想知道并且没有成功搜索的问题.例如,正则表达式"伪类" Nokogiri Docs是否适合这样的问题?

我也很好奇nokogiri中的匹配?()方法.我无法找到有关该方法的任何说明.它是否与XPath 2.0中的"匹配"概念有关(因此可以用它来解决这个问题)?

非常感谢.

Jon*_*ran 21

Nokogiri允许自定义XPath功能.您链接的nokogiri文档显示内联类定义,以便您只使用一次.如果您有很多自定义函数,或者如果您经常使用不区分大小写的匹配,则可能需要在类中定义它.

class XpathFunctions

  def case_insensitive_equals(node_set, str_to_match)
    node_set.find_all {|node| node.to_s.downcase == str_to_match.to_s.downcase }
  end

end
Run Code Online (Sandbox Code Playgroud)

然后像任何其他XPath函数一样调用它,将类的实例作为第二个参数传入.

page.parser.xpath("//meta[case_insensitive_equals(@name,'keywords')]",
                  XpathFunctions.new).to_html
Run Code Online (Sandbox Code Playgroud)

在你的Ruby方法中,node_set将绑定到一个Nokogiri::XML::NodeSet.在您传递属性值的情况下@name,它将是一个带有单个的NodeSet Nokogiri::XML::Attr.因此,调用to_s它可以为您提供价值.(或者,您可以使用node.value.)

与使用translate必须指定每个字符的XPath不同,这适用于Ruby处理的所有字符和字符编码.

另外,如果你对除XPath 1.0不支持的不区分大小写的匹配之外的其他事情感兴趣,那么它就是Ruby.所以这是一个很好的起点.


Tom*_*lak 9

包含易读性:

puts page.parser.xpath("
  //meta[
    translate(
      @name, 
      'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 
      'abcdefghijklmnopqrstuvwxyz'
    ) = 'keywords'
  ]
").to_html
Run Code Online (Sandbox Code Playgroud)

XPath 1.0中没有"小写"功能,所以你必须使用translate()这种东西.根据需要添加重音字母.