2015-11-26 3 views
1

Я хотел бы импортировать XML-файл из URL-адреса с помощью Nokogiri и сохранить его в моей базе данных PostgreSQL.Импорт XML в PostgreSQL с использованием Nokogiri

В моем schema.rb У меня есть следующая таблица:

create_table "centres", force: :cascade do |t| 
    t.string "name" 
    t.string "c_type" 
    t.text  "description" 
    t.float "lat" 
    t.float "long" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
end 

Ниже приведен пример из файла я импортирующий:

<facility> 
<id>CG432</id> 
<facility_name>Cairncry Community Centre</facility_name> 
<expiration>2099-12-31T23:59:59Z</expiration> 
<type>Community Centre</type> 
<brief_description/> 
<lat>57.1601027</lat> 
<long>-2.1441739</long> 
</facility> 

Я создал следующую задачу import.rake в Lib/задачи:

require 'rake' 
require 'open-uri' 
require 'Nokogiri' 

namespace :db do 
    task :xml_parser => :environment do 
     doc = Nokogiri::XML(open("http://sample.xml")) 
     doc.css('centre').each do |node| 
       facility_name = node.xpath("centre").text, 
       type = node.xpath("centre").text, 
       brief_description = node.xpath("centre").text, 
       lat = node.xpath("centre").text, 
       long = node.xpath("centre").text,    

       Centre.create(:facility_name => name, :type => c_type, :brief_description => description, :lat => lat, :long => long) 
      end 
     end 
    end 

rake db:migrate Я попробовал, а также rake -T | grep import.

ответ

1

Ваш XML не содержит элемент <centre>. Также нет необходимости создавать кучу переменных, если вы только собираетесь использовать их один раз.

doc.css('facility').each do |f| 
    centre = Centre.create do |c| 
    c.facility_name = node.css("facility_name").first.text 
    c.type = node.css("type").first.text 
    c.brief_description = node.css("brief_description").first.text 
    c.lat = node.css("lat").first.text 
    c.long = node.css("long").first.text 
    end 
end 

Более изящный способ сделать это, если селекторы совпадают с атрибутами является:

KEYS = ["facility_name", "type", "brief_description", "lat", "long"] 
doc.css('facility').each do |f| 
    values = KEYS.map { |k| node.css(k).first.text } 
    Centre.create(Hash[*KEYS.zip(values).flatten]) 
end 

объяснений о том, как это работает, можно найти по адресу: http://andywenk.github.io/programming/2014/06/27/ruby-create-a-hash-from-arrays/

+0

Спасибо за объяснение и ссылку! – bystrik

+0

Просто добавлю, была еще одна ошибка, которую я имел в своем исходном коде - требуется «Nokogiri». Когда я попытался подтолкнуть к Хероку и запустить миграцию, он всегда прекратил бы грабли. После некоторых исследований я обнаружил, что nokogiri не должен быть капитализирован. После того, как я изменил это, он отлично поработал. – bystrik