【问题标题】:TypeError: no implicit conversion of String into IntegerTypeError:没有将字符串隐式转换为整数
【发布时间】:2015-10-29 13:56:36
【问题描述】:

我正在尝试将 Internet 上的开放数据 XML 文件解析到我的 rails 数据库中。以下是应该解析它的代码:

require 'rake' 
require 'open-uri' 
namespace :db do 
  task :xml_parser => :environment do 
    doc = Nokogiri::XML(open("https://dl.dropboxusercontent.com/u/21695507/openplaques/gb_20151004.xml")) 
    doc.css('plaque').each do |node| 
      children = node.children 
      Plaque.create(
        :title => children.css('title').inner_text,
        :subject => children.css('subjects').inner_text,
        :colour => children.css('colour').inner_text,
        :inscription => children.css('inscription raw').inner_text,
        :latitude => children.css('geo')["latitude"].text,
        :longitude => children.css('geo')["longitude"].text,
        :address => children.css('address').inner_text,
        :organisation => children.css('organisation').inner_text,
        :date_erected => children.css('date_erected').inner_text
      )
    end
  end
end

这是架构:

create_table "plaques", force: :cascade do |t|
  t.string   "title"
  t.string   "subject"
  t.string   "colour"
  t.text     "inscription"
  t.string   "latitude"
  t.string   "longitude"
  t.text     "address"
  t.text     "organisation"
  t.string   "date_erected"
  t.datetime "created_at",   null: false
  t.datetime "updated_at",   null: false
end

我运行 rake db:xml_parser 并收到以下错误:

TypeError: no implicit conversion of String into Integer

以下是我尝试解析的 XML 文件的示例。

<plaque uri="http://openplaques.org/plaques/4856" machine_tag="openplaques:id=4856" created_at="2010-11-26T13:58:23+00:00" updated_at="2011-06-28T17:00:01+01:00">
  <title>Arthur Linton blue plaque</title>
  <subjects>Arthur Linton</subjects>
  <colour>blue</colour>
  <inscription>
    <raw>
      World Champion Cyclist 1895 lived here Arthur Linton 1872-1896
    </raw>
    <linked>
      World Champion Cyclist 1895 lived here <a href="/people/2934">Arthur Linton</a> 1872-1896
    </linked>
  </inscription>
  <geo reference_system="WGS84" latitude="51.7005" longitude="-3.4251" is_accurate="true" />
  <location>
    <address>Sheppard's Pharmacy, 218 Cardiff Road</address>
    <locality uri="http://0.0.0.0:3000/places/gb/areas/aberaman/plaques">Aberaman</locality>
    <country uri="http://0.0.0.0:3000/places/gb">United Kingdom</country>
  </location>
  <organisation uri="http://0.0.0.0:3000/organisations/rhondda_cynon_taf_council">Rhondda Cynon Taf Council</organisation>
  <date_erected>2009-10-26</date_erected>
  <person uri="http://0.0.0.0:3000/people/2934">Arthur Linton</person>
</plaque>

【问题讨论】:

  • children.css('geo')["latitude"].text - 这显然不是您访问属性值的方式。不过,我不知道什么是正确的 api。由你来决定:)

标签: ruby-on-rails xml database parsing type-conversion


【解决方案1】:

我认为错误不在架构或 Place.create(...)内容 中。我认为这是您从 Nokogiri 获取数据的方式。 some_node.css("some-selector") 将返回一组符合条件的多个节点。节点数可能是 1(或 0),因此您的 .inner_text 调用有效。

我相信您的问题在于获取纬度和经度的两条线:

:latitude => children.css('geo')["latitude"].text,
:longitude => children.css('geo')["longitude"].text,

children.css('geo') 将返回一组节点,在这种情况下,它类似于单个元素数组[geo]。但是,您对["latitude"] 的调用就像向数组询问它的latitude-th 元素......这没有意义。具体来说,

a = ["a", "b", "c", "d"]
a[1] # => "b"
a["longitude"] # => what?!?, or TypeError: no implicit conversion of String into Integer

要获得您的 lat 和 long 值,我首先要从 css("geo") 搜索中提取第一个元素。然后,调用属性来获取属性哈希。 然后,你可以通过字符串获取"latitude""longitude",最后,你需要调用.value来获取文本值。完整的,

:latitude => children.css('geo').first.attributes["latitude"].value,
:longitude => children.css('geo').first.attributes["longitude"].value,

【讨论】:

  • 它有所帮助,但我得到的下一件事是:NoMethorError: undefined method 'attributes' for nil:NilClass
  • @BystrikOndica:也许是时候学习一些调试技巧了。得到错误?检查值/变量。他们是你期望他们成为的样子吗?如果不是,为什么?继续(对自己)提问并查看程序的状态。阅读文档也很有帮助。
【解决方案2】:

有一个更简单的解决方案,效果很好!

require 'rake' 
require 'open-uri'

namespace :db do 
    task :xml_parser => :environment do 
        doc = Nokogiri::XML(open("https://dl.dropboxusercontent.com/u/21695507/openplaques/gb_20151004.xml")) 
        doc.css('plaque').each do |node| 
                title = node.xpath("plaque").text,
                subject = node.xpath("plaque").text,
                colour = node.xpath("plaque").text,
                inscription = node.xpath("plaque").text,
                latitude = node.xpath("plaque").text,
                longitude = node.xpath("plaque").text,
                address = node.xpath("plaque").text,
                organisation = node.xpath("plaque").text,
                date_erected = node.xpath("plaque").text

                Plaque.create(:title => title, :subject => subject, :colour => colour, :inscription => inscription, :latitude => latitude, :longitude => longitude, :address => address, :organisation => organisation, :date_erected => date_erected)
            end
        end
    end

【讨论】:

    最近更新 更多