r3nrut
r3nrut

Reputation: 1055

Ruby - Builder - Trying to convert CSV rows as data sets for constructing several XML's

Here's what I'm trying to accomplish. I need to have a single CSV with headers and several rows. I'm iterating through the headers and storing then and then associating the row data to the header. I need to be able to iterate through each of the rows in the CSV to use for constructing an XML's data. The constructed XML is then dumped as a .xml file and the program starts on the next row in the CSV. Each row has a column that provides the name of the XML file.

Here's what I've got so far.

Read in the data from the CSV file. Collect the header and row data.

def get_rows
        raw_data = CSV.read('test.csv', {:skip_blanks => false, :headers => true})
        data = []
        raw_data.each { |row| data << row}
        return build_header(data, raw_data)
    end

take the header and row data and marry them up.

def build_header(data, raw_data)
    (0..(data.length - 1)).each do |ri|
        h = {}
        raw_data.headers.each_with_index do |v, i|
            h[v] = data[ri].fields[i]
        end
        return build_ostruct(h)
    end
end

take the hash h and make an ostruct of it.

def build_ostruct(h)
    x = OpenStruct.new(h)
    uniq = x.tc_name
    y = uniq_name.to_s + ".xml"
    #marshal dump for debugging
    x.marshal_dump.each{ |k,v| puts "#{k} => #{v}" }
    return xml_builder(x, y)

end

Below this I'm taking the new ostruct "x" and calling the column headers from the CSV to #populate the XML nodes

For example: x.column1, x.column2, x.column3

Now the part I'm getting hung up on is getting the ostruct to receive the new row of data per iteration run. The objective is to have the ostruct populate with each row from the CSV. Currently the hash is displaying the proper data set and my XML is populating as expected but only with the first row of data. How do I get this to iterate through all the rows and populate the ostruct with the data per iteration so I can create a bulk set of XML's?

Thanks in advance for any and all help!

Upvotes: 0

Views: 1124

Answers (2)

pguardiario
pguardiario

Reputation: 54984

Something like this should work:

require 'csv'
require 'nokogiri'

CSV.foreach('test.csv', :headers => true) do |row|
    builder = Nokogiri::XML::Builder.new do |xml|
        xml.root do |root|
            row.each do |k, v|
                root.send k, v
            end
        end
    end
    File.open("#{row['tc_name']}.xml", 'w'){|f| f << builder.to_xml}
end

Upvotes: 3

dlchet
dlchet

Reputation: 1063

you are calling return in build_header, which ends the call. you need to collect your results in some way without immediately returning the first one, so that build_header can run for the entire set of rows.

Upvotes: 1

Related Questions