Извлечение атрибутов данных HTML5 из ​​тега - PullRequest
5 голосов
/ 18 марта 2012

Я хочу извлечь все атрибуты данных 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

но, похоже, это не поддерживается.

Ответы [ 4 ]

6 голосов
/ 18 марта 2012

Вариант 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 datasets

Если вы предпочитаете плагиноподобный подход, следующий метод даст вам dataset метод для каждого узла Nokogiri.

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"}
]
3 голосов
/ 18 марта 2012

Вы можете сделать это с небольшим количеством xpath:

doc = Nokogiri.HTML(html)
data_attrs = doc.xpath "//span/@*[starts-with(name(), 'data-')]"

Это получает все атрибуты span элементов, которые начинаются с 'data-'.(Возможно, вы захотите сделать это в два этапа: сначала получить все интересующие вас элементы, а затем извлекать атрибуты данных из каждого по очереди.

Продолжение примера (используя span ввопрос):

hash = data_attrs.each_with_object({}) do |n, hsh|
  hsh[n.name] = n.value
end

puts hash

производит:

{"data-age"=>"50", "data-location"=>"London"}
2 голосов
/ 18 марта 2012

В документах Node # css упоминается способ подключения пользовательского псевдо-селектора.Это может выглядеть следующим образом для выбора узлов с атрибутами, начинающимися с '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)
2 голосов
/ 18 марта 2012

Попробуйте выполнить цикл по element.attributes, игнорируя при этом любое имя, которое не начинается с data-.

...