CSV to XML questions builder gem

Hi all!

I’m converting a csv file to an xml with the code below. This works
fine. Maybe it can be done differently and better but it works for me.

I have three questions:
1 - Why cant I re-use “csv” within “builder.type” ? If re-use it I dont
get any data.
2 - I would like to add an attribute to builder.type. How can do that? I
want the result to be like and then the rest of the
xml…
3 - If I change to an excel file as source. How should I change the
code?

Any suggestions are appreciated. Maybe my code is not so “ruby”? Please
show me an example of how I can improve :slight_smile:

Br
cristian

require 'csv'
require 'builder'

File.open("testXML.xml","w"){|f|
  builder = Builder::XmlMarkup.new(:target => f, :indent => 2)
  builder.instruct!

  csv = CSV.open('mytest.csv','rb',:headers=>true)


  builder.statusinfo("date"=>"#{Time.now}", "count" =>
"#{csv.readlines.size}")
  builder.type{#, "upgnr"=>"12345"

# Question 1: I would like to use > csv.each do |invoice|
    CSV.open('mytest.csv','rb',:headers=>true).each do |invoice|

      column = invoice[0].split(";")

      builder.status{|b|
        b.custid("#{column[1]}")
        b.invno("#{column[2]}")
        b.date("#{column[4]}")
        b.code("#{column[8]}")
        b.date2("#{column[9]}")
      }
    end
  }
}

I’m not sure what version of Ruby you’re using, but I suspect that the
reason you can’t see “csv” is because you’re inside the “builder.type{”
block.
http://ruby.about.com/od/newinruby191/a/blockvariscope.htm

Making the variable something like @csv or $csv should make it visible
inside the block, since those are not local variables (instance and
global, respectively).

I suspect that builder.type doesn’t work because you’ve commented out
the rest of that line:

builder.type{#, “upgnr”=>“12345”
Here the “#” makes the rest of the line a comment, and is ignored by the
interpreter.

If you want to read an Excel file, there are several gems that allow you
to do so. Each has their merits. Try this list:

Hi Joel,

Thank you for helping me.

Im using ruby 2.0.0p247

Regarding the variables I have tried @csv and $csv without luck.

In my code above I forgot to delete the outcommented code after the #.
Even if I remove the # it doesnt work. At the moment (with the out
commented line above) the result is: without the attribute
“upgnr”.

Exactly what error do you get when you try to reference “csv”? Is it
undefined variable, or something else?

Sorry for late reply.

Well. I dont get an error message. When I use the variable “csv” inside
the block it seems as it just ignores it. so the result is as executing
this:

require 'csv'
require 'builder'

File.open("testXML.xml","w"){|f|
  builder = Builder::XmlMarkup.new(:target => f, :indent => 2)
  builder.instruct!

  csv = CSV.open('mytest.csv','rb',:headers=>true)


  builder.statusinfo("date"=>"#{Time.now}", "count" =>
"#{csv.readlines.size}")
  builder.type("upgnr"=>"12345"){

  #Code removed

  }
}

What happens when you inspect the csv inside that block?
Like this:
puts csv.inspect, csv.length

Well…this is the error with suggested inspect and length…

C:\CR - XML convevert>ruby converter_test.rb
converter_test.rb:31:in block (2 levels) in <main>' undefined method 'length' for #<CSV:0x2396bc8> (NoMethodError) from C:/Ruby200/lib/ruby/gems/2.0.0/gems se.rb:170:incall’
from C:/Ruby200/lib/ruby/gems/2.0.0/gems
se.rb:170:in _nested_structures' from C:/Ruby200/lib/ruby/gems/2.0.0/gems se.rb:63:intag!’
from C:/Ruby200/lib/ruby/gems/2.0.0/gems
se.rb:88:in method_missing' from converter_test.rb:29:inblock in ’
from converter_test.rb:19:in open' from converter_test.rb:19:in

Ok…

The code should look like this to get the attribute in there:

builder.type(“upgnr”=>“12345”){…

I dont know what I was thinking about.

Still I have a problem with the scope of that variable. I dont
understand how to “pass” the variable to the block within
builder.type…

There’s no parameter called csv within the block so it should refer to
the variable outside the block…Im getting confused…

I guess length isn’t supported, I thought it was.

Anyway, the good news is that you can see your csv variable!
It’s this: #CSV:0x2396bc8

You should be able to, yes. There shouldn’t be any difference between
using the variable and reopening the file, as far as I can see, except
possibly a conflict with opening the file when it’s already open.

At this point you should continue entering debugging lines, like this:

puts csv.inspect
csv.each do |invoice|

  puts invoice.inspect

  column = invoice[0].split(";")
  puts column.inspect
  etc, etc....

Yes. Now that I only have puts csv.inspect just above the I can see
whats in there. But why cant I use it?


....

puts csv.inspect
CSV.open('mytest.csv','rb',:headers=>true).each do |invoice|

      column = invoice[0].split(";")

      builder.status{|b|
        b.custid("#{column[1]}")
        b.invno("#{column[2]}")
        b.date("#{column[4]}")
        b.code("#{column[8]}")
        b.date2("#{column[9]}")
      }
    end

...

This gives me:

<#CSV io_type:File io_path:“mytest.csv” encoding:ASCII-8BIT lineno:360
col_s
ep:"," row_sep:"\r\n" quote_char:"""
headers:[“Namn;CustID;InvoiceID;InvoiceDate;F
xF6rfdat;InvoiceAm;Payedbel;AM;KKL;Date;KK;RK;”]>

csv is:
csv = CSV.open(‘mytest.csv’,‘rb’,:headers=>true)

Cant I do a “.each do |x|” on this variable?

/cristian

If I try iterate csv it doesnt give anything so everything I do within
the block is just ignored.

I think its some kind of conflict because if I declare a new variable
outside the block it works fine:

csv2 = CSV.open(infile+’.csv’,‘rb’,:headers=>true)

The problem arises when I do “csv.readlines.size”. After this I cant use
the variable even though if I inspect it there is something in there…

This works…

require 'csv'
require 'builder'

File.open("testXML.xml","w"){|f|
  builder = Builder::XmlMarkup.new(:target => f, :indent => 2)
  builder.instruct!

  csv = CSV.open('mytest.csv','rb',:headers=>true)
  csv2 = CSV.open('mytest.csv','rb',:headers=>true)


  builder.statusinfo("date"=>"#{Time.now}", "count" =>
"#{csv.readlines.size}")
  builder.type{#, "upgnr"=>"12345"


    csv2.each do |invoice|

      column = invoice[0].split(";")

      builder.status{|b|
        b.custid("#{column[1]}")
        b.invno("#{column[2]}")
        b.date("#{column[4]}")
        b.code("#{column[8]}")
        b.date2("#{column[9]}")
      }
    end
  }
}

ok. Thank you for your help Joel.

Perhaps “readlines” leaves nothing left to iterate through with “each”.
I suspect that the csv keeps its current position, meaning you’re
already at the end of the file after using “readlines”.

Hello everyone,

Is it good idea to use nested classes if they are small and will be used
by parent class only?

Bob

How do I get removed from this list, please?

Hello,

On 7 Οκτ 2013, at 16:47 , Χαράλαμπος Κώστας [email protected] wrote:

Hello everyone,

Is it good idea to use nested classes if they are small and will be used by
parent class only?

Sure. There’s nothing wrong with that, depends heavily on the use case.

Bob

Panagiotis (atmosx) Atmatzidis

email: [email protected]
URL: http://www.convalesco.org
GnuPG ID: 0x1A7BFEC5
gpg --keyserver pgp.mit.edu --recv-keys 1A7BFEC5

@John: Enable/disable email notification…

Are these topics mixed now?

https://www.ruby-lang.org/en/community/mailing-lists/

On 8 2013, at 10:30 , John McKeag [email protected] wrote:

Panagiotis (atmosx) Atmatzidis

email: [email protected]
URL: http://www.convalesco.org
GnuPG ID: 0x1A7BFEC5
gpg --keyserver pgp.mit.edu --recv-keys 1A7BFEC5