2010-02-17 56 views
16

我使用引入nokogiri选择“关键字”属性,像这样:如何创建nokogiri不区分大小写的Xpath选择器?

puts page.parser.xpath("//meta[@name='keywords']").to_html 

一个我的工作页面有一个大写字母“K”这促使我做的关键字标签查询不区分大小写。

<meta name="keywords"> AND <meta name="Keywords"> 

所以,我的问题是:是什么力量让一个引入nokogiri选择不区分大小写的最佳方式?

编辑 Tomalak的建议对于这个特定的问题很有效。我也想用这个例子来更好地理解nokogiri,并且有一些我想知道并且没有成功搜索的问题。例如,正则表达式'伪类'Nokogiri Docs是否适合这样的问题?

我也很好奇nokogiri中的匹配?()方法。我一直无法找到关于该方法的任何澄清。它与XPath 2.0中的“匹配”概念有什么关系(因此可用于解决此问题)?

非常感谢。

+1

+1 - 很好的问题。欢迎来到SO :) – 2010-02-17 14:36:31

回答

9

裹的可读性:

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

有XPath 1.0中没有“小写”的功能,所以你必须使用translate()为这种事情。根据需要添加重音字母。

+0

非常感谢Tomalak。这个解决方案对我来说很好。 – Rick 2010-02-22 03:48:24

+0

仅供参考,VTD-XML的xpath 1.0实际上实现了upperCase和lowerCase作为某种中间步骤到2.0 – 2010-02-24 08:12:25

19

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 

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

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

在你的Ruby方法,node_set将绑定到一个Nokogiri::XML::NodeSet。如果您传递的属性值为@name,则它将是一个带有单个Nokogiri::XML::Attr的节点集。所以打电话给to_s就可以了。 (或者,您可以使用node.value。)

与使用必须指定每个字符的XPath translate不同,它适用于所有Ruby处理的字符和字符编码。另外,如果您有兴趣做除XPath 1.0不支持的不区分大小写匹配之外的其他任何事情,则此时只是Ruby。所以这是一个很好的起点。

+0

非常优雅的解决方案! – Severin 2014-12-10 10:37:31

相关问题