我想从标签中提取所有HTML5数据属性,就像这个jQuery插件一样。
例如,给定:
<span data-age="50" data-location="London" class="highlight">Joe Bloggs</span>
我想得到一个散列像:
{ 'data-age' => '50', 'data-location' => 'London' }
我最初希望使用通配符作为CSS选择器的一部分,例如
Nokogiri(html).css('span[@data-*]').size
但这似乎没有得到支持。
选项1:抓取所有数据元素
如果你只需要列出页面的所有数据元素,这里有一行代码:
Hash[doc.xpath("//span/@*[starts-with(name(), 'data-')]").map{|e| [e.name,e.value]}]
输出:
{"data-age"=>"50", "data-location"=>"London"}
选项2:按标签对结果进行分组
如果你想按标签对结果进行分组(也许你需要对每个标签进行额外的处理),你可以做以下操作:
tags = []
datasets = "@*[starts-with(name(), 'data-')]"
#If you want any element, replace "span" with "*"
doc.xpath("//span[#{datasets}]").each do |tag|
tags << Hash[tag.xpath(datasets).map{|a| [a.name,a.value]}]
end
那么tags
是一个数组,包含按标签分组的键值哈希对。
选项3:类似jQuery数据集插件的行为
如果您更喜欢类似插件的方法,下面将在每个Nokogiri节点上为您提供一个dataset
方法。
module Nokogiri
module XML
class Node
def dataset
Hash[self.xpath("@*[starts-with(name(), 'data-')]").map{|a| [a.name,a.value]}]
end
end
end
end
然后您可以找到单个元素的数据集:
doc.at_css("span").dataset
或者获取一组元素的数据集:
doc.css("span").map(&:dataset)
示例:
以下是上面的dataset
方法的行为。给定HTML中的以下行:
<span data-age="50" data-location="London" class="highlight">Joe Bloggs</span>
<span data-age="40" data-location="Oxford" class="highlight">Jim Foggs</span>
输出为:
[
{"data-location"=>"London", "data-age"=>"50"},
{"data-location"=>"Oxford", "data-age"=>"40"}
]
您可以使用一点xpath:
doc = Nokogiri.HTML(html)
data_attrs = doc.xpath "//span/@*[starts-with(name(), 'data-')]"
这将获取以"data-"开头的span
元素的所有属性。(您可能需要分两步来完成,首先获取您感兴趣的所有元素,然后依次从每个元素中提取数据属性
继续示例(在问题中使用span
):
hash = data_attrs.each_with_object({}) do |n, hsh|
hsh[n.name] = n.value
end
puts hash
生产:
{"data-age"=>"50", "data-location"=>"London"}
尝试在element.attributes
中循环,同时忽略任何不以data-
开头的属性。
Node#css文档提到了一种附加自定义psuedo选择器的方法。选择属性以"data-"开头的节点时,可能会出现以下情况:
Nokogiri(html).css('span:regex_attrs("^data-.*")', Class.new {
def regex_attrs node_set, regex
node_set.find_all { |node| node.attributes.keys.any? {|k| k =~ /#{regex}/ } }
end
}.new)