2012-03-17 84 views
5

thể trùng lặp:
Best way to use html5 data attributes with rails content_tag helper?Trích xuất dữ liệu HTML5 thuộc tính từ một thẻ

tôi muốn trích xuất tất cả dữ liệu HTML5 thuộc tính từ một thẻ, giống như this jQuery plugin.

Ví dụ, đưa ra:

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

Tôi muốn có được một băm như:

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

tôi ban đầu hy vọng sử dụng một ký tự đại diện như một phần của bộ chọn CSS của tôi, ví dụ

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

nhưng có vẻ như không được hỗ trợ.

+0

Các “sao chép” Câu hỏi liên quan là các thuộc tính về _creating_ dữ liệu (và là Rails cụ thể), câu hỏi này là về _extracting_ họ từ HTML hiện tại, do đó, nó không phải là một bản sao. – matt

Trả lời

6

Lựa chọn 1: lấy tất cả các yếu tố dữ liệu

Nếu tất cả bạn cần là để liệt kê tất cả các yếu tố dữ liệu của trang , Đây là một lớp lót:

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

Output:

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

Phương án 2: Nhóm kết quả theo tag

Nếu bạn muốn nhóm kết quả của bạn bằng thẻ (có lẽ bạn cần phải làm thêm xử lý trên mỗi thẻ), bạn có thể làm như sau:

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 

Sau đó tags là một ar ray chứa các cặp băm khóa-giá trị, được nhóm theo thẻ.

Lựa chọn 3: Hành vi như bộ dữ liệu jQuery plugin

Nếu bạn muốn tiếp cận plugin như thế nào, sau đây sẽ cung cấp cho bạn một phương pháp dataset trên mỗi nút 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 

Sau đó, bạn có thể tìm thấy các tập dữ liệu cho một yếu tố duy nhất:

doc.at_css("span").dataset 

Hoặc tải dữ liệu cho một nhóm các yếu tố:

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

Ví dụ:

Sau đây là hành vi của phương pháp dataset ở trên. Căn cứ vào dòng sau trong 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> 

Kết quả sẽ là:

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

Nếu có nhiều khoảng cách, điều này sẽ kết hợp chúng lại với nhau – pguardiario

+0

@pguardiario Có. Điều này tạo ra một Hash duy nhất với tất cả các thuộc tính dữ liệu từ toàn bộ trang. –

1

Thử lặp qua element.attributes trong khi bỏ qua bất kỳ thông báo nào không bắt đầu bằng số data-.

2

Tài liệu Node#css đề cập đến cách để đính kèm bộ chọn psuedo tùy chỉnh. Điều này có thể trông giống như sau để lựa chọn các nút với các thuộc tính bắt đầu bằng 'đĩa dữ liệu':

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

Bạn có thể làm điều này với một chút xpath:

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

này được tất cả các thuộc tính của các yếu tố span bắt đầu bằng 'data-'. (Bạn có thể muốn thực hiện việc này theo hai bước, trước tiên hãy lấy tất cả các yếu tố mà bạn quan tâm, sau đó trích xuất các thuộc tính dữ liệu từ mỗi phần tử đó lần lượt.

Tiếp tục ví dụ (sử dụng span trong câu hỏi của bạn):

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

puts hash 

sản xuất:

{"data-age"=>"50", "data-location"=>"London"} 
Các vấn đề liên quan