2012-04-14 3 views
0

У меня есть CSV, который мне нравится сохранять на нем все мои значения хэша. Я использую nokogiri sax для анализа XML-документа и сохранения его в CSV.Ruby: undefined method `<< 'для nil: NilClass

Это разобрать и сохраняет первый файл XML, но при запуске разбора второй, он остановится, и ошибка, я получаю это:

Ошибка:NoMethodError: undefined method < < 'для ноль: NilClass`

нилъ ошибка happing в @infodata [: названия] < < @content

саксофоне анализатор:

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 

создает новый объект для каждого файла, который следует хранить в папке (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-файлы для пытаться код:https://gist.github.com/2378898 HTTPS://gist.github.com/2378901 https://gist.github.com/2378904

+0

Совет: вместо 'csv = ...; csv << "\ n"; f.write (csv) 'just do' csv = ...; f.puts csv' – Phrogz

+0

Совет: 'foo = Array.new ([])' смешно; просто сделайте 'foo = []'. – Phrogz

+0

Совет: не используйте двоичный режим для xml или csv – pguardiario

ответ

0

Вы делаете это:

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

Если по какой-то причине CSV.generate_line(HEADERS.map {|h| @infodata[h] }) возвращает ноль, вы будете пытаться использовать метод < < до нулевого объекта, который не определен.

Возможно, вы захотите добавить некоторые условия, чтобы не добавлять «\ n» в csv, если это нуль.

+0

ошибка nil происходит в @infodata [: titles] << @content – SHUMAcupcake

+0

@SHUMAcupcake Эй, это было бы приятно узнать: p Вы улучшаете включение более подробной информации в свой вопрос, но все равно этого недостаточно. Ошибка _message_ хороша, но номер строки примерно так же важен. – Phrogz

Смежные вопросы