newbie problem

J

JP

Hi, i just started to learn ruby today and run into annoying problem, i
don't quite get what's
wrong in the code snippet below, what i try to do is simple count all
"document" elements from xml file
why it complains this:

xmlreader.rb:33:in `tag_start': undefined method `+' for nil:NilClass
(NoMethodError)
from f:/ruby/lib/ruby/1.8/rexml/parsers/streamparser.rb:24:in `parse'


sum is undefined? but why? here's the code:


require "rexml/document"
include REXML

class Listener
sum=0

def text(text)
puts text
end

def xmldecl(version,encoding,standalone)
puts version
puts encoding
end

def tag_start(name,attrs)
if name == "document"
sum += 1
end
end

def tag_end(name)
end
end

list = Listener.new

xmlfile = File.new( "f:\\data2\\mloy\\out\\mtl009index.3.xml")
sparser = Parsers::StreamParser.new(xmlfile,list)

sparser.parse()
puts sum
 
J

James H.

Hey JP. Welcome to Ruby!

The first problem I noticed is in this method:

def tag_start(name,attrs)
if name == "document"
sum += 1
end
end

Ruby doesn't define the "+=" operator. You need to say this instead:

sum = sum + 1

Or, better yet,

sum.next

Here's how I would personally write that method:

def tag_start(name, attributes)
sum.next if name == "document"
end

Pretty sexy, isn't it? End-of-line logic, in my opinion, makes your
code more readable. If you read that line outloud it sounds very
English.

I hope this helps you,

James H.
 
E

Eric K Idema

James H. said:
Ruby doesn't define the "+=" operator. You need to say this instead:
sum = sum + 1

Ruby does have a += operator. (It doesn't have a ++ operator, which is
probably what you were thinking of)

To the OP, if you intend for sum to be an instance variable it should be
prefixed with an '@':

@sum = 0

@sum += 1

etc. Or, consider using one of the attr methods to create accessors.


Eric
 
B

baumanj

James said:
Ruby doesn't define the "+=" operator. You need to say this instead:

Sure it does:

$ irb --simple-prompt=> 1

It's ++ that ruby doesn't define.
sum = sum + 1
Or, better yet,
sum.next

Actually, it would have to be "sum = sum.next" if you actually wanted
to update the value of sum, but there's nothing wrong with sum += 1.

The problem is scope. If you want sum to be an instance variable, you
need to define it as @sum. Also, since you can't reference instance
variables from within the class definition (they must be accessed from
an instance method), you have to declare this in the initialize method
(you could get tricky and do it conditionally in the tag_start method,
but what's the point?). Finally, to give read-only access to this
attribute from outside the class, you can use the attr_accessor macro.
Then you'll be able to access the sum attribute as list.sum. This
version should work:

require "rexml/document"
include REXML

class Listener
attr_accessor :sum

def initialize
@sum = 0
end

def text(text)
puts text
end

def xmldecl(version,encoding,standalone)
puts version
puts encoding
end

def tag_start(name,attrs)
if name == "document"
@sum += 1
end
end

def tag_end(name)
end
end

list = Listener.new

xmlfile = File.new( "f:\\data2\\mloy\\out\\mtl009index.3.xml")
sparser = Parsers::StreamParser.new(xmlfile,list)

sparser.parse()
puts list.sum
 
J

James H.

It's okay, now I'll never forget ;) *feels a little silly at the
moment*

James H.
 
J

JP

This
version should work:

Yep it worked perfectly, ruby seems to be bit different than other languages
i have used but also very powerful, tasks like this simple xml parsing is
pain with e.g. c++, with ruby just 4 lines of code, how cool is that!
Now to the next step, trying to add this xml stuff to database

thanks for all,

/JP
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,262
Messages
2,571,054
Members
48,769
Latest member
Clifft

Latest Threads

Top