2012-03-17 19 views
5

Eventuali duplicati:
Best way to use html5 data attributes with rails content_tag helper?Estrazione dati HTML5 attributi da un tag

Voglio estrarre gli attributi di tutti i dati HTML5 da un tag, proprio come this jQuery plugin.

Ad esempio, dato:

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

voglio ottenere un hash come:

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

Mi è stato originariamente sperando utilizzare un carattere jolly come parte del mio selettore CSS, per esempio

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

ma sembra che non sia supportato.

+0

Il “duplicato” questione collegata è attributi su _creating_ dati (ed è Rails specifico), questa domanda è su di loro _extracting_ da HTML esistente, quindi non è un duplicato. – matt

risposta

6

Opzione 1: afferrare tutti gli elementi di dati

Se tutto ciò che serve è quello di elencare tutti gli elementi di dati della pagina , Ecco una battuta:

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

uscita:

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

Opzione 2: Risultati del Gruppo per tag

Se si desidera raggruppare i risultati per tag (forse avete bisogno di fare ulteriore elaborazione su ogni tag), è possibile effettuare le seguenti operazioni:

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 

Poi tags è un ar raggio contenente coppie di hash di valori-chiave, raggruppate per tag.

Opzione 3: Comportamento come il set di dati jQuery plugin di

Se preferite l'approccio plug-like, di seguito vi darà un metodo dataset su ogni nodo 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 

Quindi è possibile trovare il set di dati per un unico elemento:

doc.at_css("span").dataset 

O ottenere il set di dati per un gruppo di elementi:

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

Esempio:

Quanto segue è il comportamento del metodo dataset sopra. Date le seguenti righe nel codice 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> 

l'output sarà:

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

Se ci sono più span anche se questo li schiaccerà insieme – pguardiario

+0

@pguardiario Sì. Questo crea un singolo hash con tutti gli attributi dei dati dell'intera pagina. –

1

Provare a eseguire il ciclo attraverso element.attributes ignorando qualsiasi attributo che non inizia con data-.

2

I documenti Node#css menzionano un modo per allegare un selettore psuedo personalizzato. Questo potrebbe essere simile al seguente per la selezione di nodi con gli attributi che iniziano con 'dati-':

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

Si può fare questo con un po 'di XPath:

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

Questo ottiene tutti gli attributi di elementi span che inizia con "data-". (Puoi fare ciò in due passaggi, prima di ottenere tutti gli elementi che ti interessano, quindi estrarre gli attributi dei dati da ciascuno a turno.

Continuare l'esempio (utilizzando span nella tua domanda):

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

puts hash 

produce:

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