2012-03-17 18 views
5

Powiel możliwe:
Best way to use html5 data attributes with rails content_tag helper?HTML5 z tagiem

Chcę, aby wyodrębnić wszystkie atrybuty danych z tagu HTML5, tak jak this jQuery plugin.

Na przykład, biorąc pod uwagę:

<span data-age="50" data-location="London" class="highlight">Joe Bloggs</span> 

Chcę uzyskać hash jak:

{ 'data-age' => '50', 'data-location' => 'London' } 

ja pierwotnie nadzieję użyć symbolu wieloznacznego jako część mojego selektora CSS, np

Nokogiri(html).css('span[@data-*]').size 

ale wydaje się, że nie jest obsługiwany.

+0

prowadzi link „duplikat” Pytanie jest atrybuty o _creating_ danych (i Rails specyficzne), to pytanie jest o _extracting_ je z istniejącego HTML, więc nie jest duplikatem. – matt

Odpowiedz

6

Wariant 1: Grab wszystkie elementy danych

Jeśli wszystko, co potrzebne jest, aby wymienić wszystkie elementy danych widoku za , Oto jedna wkładka:

Hash[doc.xpath("//span/@*[starts-with(name(), 'data-')]").map{|e| [e.name,e.value]}] 

wyjściowa:

{"data-age"=>"50", "data-location"=>"London"} 

Opcja 2: Wyniki Grupy po tagu

Jeśli chcesz pogrupować wyniki według znacznika (być może trzeba zrobić dodatkowy przetwarzanie na każdym znaczniku), można wykonać następujące czynności:

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 

Następnie tags jest ar promień zawierający pary skrótów wartość kluczowa, pogrupowane według tagów.

Wariant 3: Zachowanie jak jQuery zestawów danych wtyczki

Jeśli wolisz podejście plugin-jak dodaje daje dataset metody na każdym węźle 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 

Następnie można znaleźć zbiór danych dla pojedynczego elementu:

doc.at_css("span").dataset 

Albo dostać zestaw danych dla grupy elementów:

doc.css("span").map(&:dataset) 

Przykład:

Poniżej przedstawiono zachowanie metody dataset powyżej. Biorąc pod uwagę następujące linie w 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> 

Wyjście będzie:

[ 
{"data-location"=>"London", "data-age"=>"50"}, 
{"data-location"=>"Oxford", "data-age"=>"40"} 
] 
+0

Jeśli istnieje wiele rozpiętości, ale spowoduje to ich zetknięcie – pguardiario

+0

@pguardiario Tak. Spowoduje to utworzenie pojedynczego hasza zawierającego wszystkie atrybuty danych z całej strony. –

1

Spróbuj przełączyć się przez element.attributes, ignorując wszelkie atrybuty, które nie rozpoczynają się od data-.

2

Dokumenty o numerze Node#css wspominają o sposobie dołączenia niestandardowego selektora psuedo. To może wyglądać następująco wyboru węzłów z atrybutami rozpoczynający się od „teleinformatyczny”:

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) 
3

Można to zrobić przy odrobinie XPath:

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

ten pobiera wszystkie atrybuty span elementów zaczynające się od "data-". (Być może chcesz to zrobić w dwóch etapach, najpierw uzyskać wszystkie elementy, które Cię interesują, a następnie wyodrębnić atrybutów danych z każdego z kolei

Kontynuując przykład (przy użyciu span w swoim pytaniu).

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

puts hash 

produkuje:

{"data-age"=>"50", "data-location"=>"London"}