简体   繁体   English

Ruby:nil:NilClass的未定义方法“ <<”

[英]Ruby: undefined method `<<' for nil:NilClass

I have a CSV that I like to save all my hash values on it. 我有一个CSV文件,我想将所有哈希值保存在上面。 I am using nokogiri sax to parse a xml document and then save it to a CSV. 我正在使用nokogiri sax解析xml文档,然后将其保存为CSV。

It parse and saves the first xml file but when start parsing the second one, it stop and the error I get is this: 它解析并保存第一个xml文件,但是当开始解析第二个xml文件时,它停止了,我得到的错误是:

The error: NoMethodError: undefined method <<' for nil:NilClass` 错误: NoMethodError: undefined method nil:NilClass`的NoMethodError: undefined method <<'

the nil error is happing in the @infodata[:titles] << @content nil错误出现在@infodata [:titles] << @content中

The sax parser: 萨克斯解析器:

require 'rubygems'
require 'nokogiri'
require 'csv'

class MyDocument < Nokogiri::XML::SAX::Document

  HEADERS = [ :titles, :identifier, :typeOfLevel, :typeOfResponsibleBody, 
              :type, :exact, :degree, :academic, :code, :text ]

  def initialize
     @infodata = {}
     @infodata[:titles] = Array.new([])
  end

  def start_element(name, attrs)
    @attrs = attrs
    @content = ''
  end
  def end_element(name)
    if name == 'title'
      Hash[@attrs]["xml:lang"]
      @infodata[:titles] << @content
      @content = nil
    end
    if name == 'identifier'
       @infodata[:identifier] = @content
       @content = nil
    end
    if name == 'typeOfLevel'
       @infodata[:typeOfLevel] = @content
       @content = nil
    end
    if name == 'typeOfResponsibleBody'
       @infodata[:typeOfResponsibleBody] = @content
       @content = nil
    end
    if name == 'type'
       @infodata[:type] = @content
       @content = nil
    end
    if name == 'exact'     
       @infodata[:exact] = @content
       @content = nil
    end
    if name == 'degree'
       @infodata[:degree] = @content
       @content = nil
    end
    if name == 'academic'
       @infodata[:academic] = @content
       @content = nil
    end
    if name == 'code'
       Hash[@attrs]['source="vhs"']
       @infodata[:code] = @content 
       @content = nil
    end
    if name == 'ct:text'
       @infodata[:beskrivning] = @content
       @content = nil
    end 
  end
  def characters(string)
    @content << string if @content
  end
  def cdata_block(string)
    characters(string)
  end
  def end_document
    File.open("infodata.csv", "ab") do |f|
      csv = CSV.generate_line(HEADERS.map {|h| @infodata[h] })
      csv << "\n"
      f.write(csv)
    end
  end
end

creating new an object for every file that is store in a folder(47.000xml files): 为文件夹中存储的每个文件创建一个新对象(47.000xml文件):

parser = Nokogiri::XML::SAX::Parser.new(MyDocument.new)
counter = 0

Dir.glob('/Users/macbookpro/Desktop/sax/info_xml/*.xml') do |item|
  parser.parse(File.open(item, 'rb'))
  counter += 1
  puts "Writing file nr: #{counter}"
end

3 xml files for trying the code: https://gist.github.com/2378898 https://gist.github.com/2378901 https://gist.github.com/2378904 3个用于尝试代码的xml文件: https : //gist.github.com/2378898 https://gist.github.com/2378901 https://gist.github.com/2378904

You are doing this: 您正在执行此操作:

csv = CSV.generate_line(HEADERS.map {|h| @infodata[h] })
csv << "\n"

If for some reason the CSV.generate_line(HEADERS.map {|h| @infodata[h] }) returns nil , you will be trying to use the << method to a nil object, which is not defined. 如果由于某些原因CSV.generate_line(HEADERS.map {|h| @infodata[h] })返回nil ,则您将尝试对未定义的nil对象使用<<方法。

You might want to add some conditions to avoid adding "\\n" to csv if it is nil. 您可能需要添加一些条件,以避免在cv中添加“ \\ n”(如果为零)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM