2012-03-17 16 views
5

Duplicar posible:
Best way to use html5 data attributes with rails content_tag helper?Extracción de datos HTML5 atributos de una etiqueta

Quiero extraer todos los atributos de los datos de una etiqueta HTML 5, al igual que this jQuery plugin.

Por ejemplo, dado:

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

quiero conseguir un hash como:

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

yo esperaba originalmente utilizar un comodín como parte de mi selector CSS, por ejemplo,

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

pero parece que no es compatible.

+0

El “duplicar” cuestión vinculada se atribuye sobre _creating_ de datos (y es Rieles específica), esta pregunta se refiere a _extracting_ ellas desde HTML existente, por lo que no es un duplicado. – matt

Respuesta

6

Opción 1: Coge todos los elementos de datos

Si todo lo que necesita es una lista de todos los elementos de datos de la página , He aquí una sola línea:

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

Salida:

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

Opción 2: Resultados del Grupo por etiqueta

Si desea agrupar los resultados por etiqueta (tal vez lo que necesita hacer adicional procesamiento en cada etiqueta), se puede hacer lo siguiente:

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 

Entonces tags es un AR rayos que contienen pares clave-valor hash, agrupados por etiqueta.

Opción 3: Comportamiento como el plugin de jQuery conjuntos de datos

Si prefiere el enfoque de plug-in similar, la siguiente información le dará un método dataset en cada 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 

entonces usted puede encontrar el conjunto de datos para un solo elemento:

doc.at_css("span").dataset 

O obtener el conjunto de datos para un grupo de elementos:

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

Ejemplo:

El siguiente es el comportamiento del método dataset encima. Dadas las siguientes líneas en el código 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> 

la salida sería:

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

Si hay múltiples tramos aunque esto los combinará juntos – pguardiario

+0

@pguardiario Sí. Esto crea un Hash único con todos los atributos de datos de toda la página. –

1

Intente pasar por element.attributes ignorando cualquier attribuna que no comience con data-.

2

Los Node#css mencionan una forma de adjuntar un selector de psuedo personalizado. Esto podría ser similar al siguiente para la selección de nodos con atributos que empiezan con '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) 
3

Usted puede hacer esto con un poco de XPath:

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

Esto se lleva todos los atributos de los elementos span que comienza con 'datos-'. (Es posible que desee hacer esto en dos pasos, primero en obtener todos los elementos que le interesan, a continuación, extraer los atributos de datos de cada uno, a su vez

Continuando con el ejemplo (utilizando el span en su pregunta):.

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

puts hash 

produce:

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