REXML and Date interaction

R

Robert Evans

Hi,

I have a problem parsing dates from XML. I have this little program
which produces an error, and I was able to fix it by moving the date
parsing into a class that is distinct from the xml processing. Below
is a broken version and the error it prints, and then a working
version with the correct output. I would be grateful if anyone could
explain what is going wrong here. It looks like it turns the class
Date into a string Constant.

Thanks,
Bob Evans

Broken Version
===========

#!/usr/bin/env ruby

require 'rexml/document'
require 'date'

class DateFun

def parse(xml)
doc = REXML::Document.new(xml)
elems = doc.root.get_elements('//body/dateelement[@date]')
elems.map { |s|
s.attributes["date"].to_s
}.sort
end

def sorted_dates_from(xml)
sorted_dates = parse(xml)
sorted_dates.map { |d| Date.parse(d)}.sort
end
end

xmlDates = <<HERE
<dateelement date="02/05/1954"/></body>
HERE

sorted_dates = DateFun.new.sorted_dates_from(xmlDates)
sorted_dates.each { |d| puts d.to_s}

Produces
===========
NoMethodError: undefined method `parse' for "2005/224":String
from /Users/bobevans/Documents/projects/rubyplay/brokendate.rb:18:in
`sorted_dates_from'
from /Users/bobevans/Documents/projects/rubyplay/brokendate.rb:18:in
`sorted_dates_from'
from /Users/bobevans/Documents/projects/rubyplay/brokendate.rb:26
from (irb):1835
from /usr/local/lib/ruby/1.8/rexml/element.rb:1182



Working Version
============
#!/usr/bin/env ruby

require 'rexml/document'
require 'date'

class DateFun
include REXML

def parse(xml)
doc = Document.new(xml)
elems = doc.root.get_elements('//body/dateelement[@date]')
elems.map { |s|
s.attributes["date"].to_s
}.sort
end
end

class Other
def sorted_dates_from(xml)
sorted_dates = DateFun.new.parse(xml)
sorted_dates.map { |d| Date.parse(d)}.sort
end
end

xmlDates = <<HERE
<dateelement date="02/05/1954"/></body>
HERE

sorted_dates = Other.new.sorted_dates_from(xmlDates)
sorted_dates.each { |d| puts d.to_s}

Produces:

1954-02-05
1970-02-06
1973-12-28
 
D

dblack

Hi --

Hi,

I have a problem parsing dates from XML. I have this little program which
produces an error, and I was able to fix it by moving the date parsing into a
class that is distinct from the xml processing. Below is a broken version and
the error it prints, and then a working version with the correct output. I
would be grateful if anyone could explain what is going wrong here. It looks
like it turns the class Date into a string Constant.

Your broken version worked for me. What version of Ruby are you
using?


David

--
David A. Black | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 
R

Robert Evans

Hi,

Thanks for running it, indeed that broken version works, and I
must've corrupted my irb session. So, I tried it again and discovered
more precisely the problem. If I include REXML in the class instead
of explicitly specifying REXML::Document, then I get the problem.
Which, I can just "not do that" for now, but it is still curious what
is happening. Here is a version that seems to produce the error still.

Thanks for the sanity check,

Bob Evans



Better Broken
=============
#!/usr/bin/env ruby

require 'rexml/document'
require 'date'

class DateFun
## BEGIN Different
include REXML
## END Different

def parse(xml)
## BEGIN Different
doc = Document.new(xml)
##End Different

elems = doc.root.get_elements('//body/dateelement[@date]')
elems.map { |s|
s.attributes["date"].to_s
}.sort
end

def sorted_dates_from(xml)
sorted_dates = parse(xml)
sorted_dates.map { |d| Date.parse(d)}.sort
end
end

xmlDates = <<HERE
<dateelement date="02/05/1954"/></body>
HERE

sorted_dates = DateFun.new.sorted_dates_from(xmlDates)
sorted_dates.each { |d| puts d.to_s}


Produces
===============
/brokendate.rb
/brokendate.rb:18:in `sorted_dates_from': undefined method `parse'
for "2005/224":String (NoMethodError)
from ./brokendate.rb:18:in `sorted_dates_from'
from ./brokendate.rb:26



Hi --

Hi,

I have a problem parsing dates from XML. I have this little
program which produces an error, and I was able to fix it by
moving the date parsing into a class that is distinct from the xml
processing. Below is a broken version and the error it prints, and
then a working version with the correct output. I would be
grateful if anyone could explain what is going wrong here. It
looks like it turns the class Date into a string Constant.

Your broken version worked for me. What version of Ruby are you
using?


David

--
David A. Black | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training &
consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central,
Inc. [4]
[1] http://www.manning.com/black | [3] http://
www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 
D

dblack

Hi --

Hi,

Thanks for running it, indeed that broken version works, and I must've
corrupted my irb session. So, I tried it again and discovered more precisely
the problem. If I include REXML in the class instead of explicitly specifying
REXML::Document, then I get the problem. Which, I can just "not do that" for
now, but it is still curious what is happening. Here is a version that seems
to produce the error still.

Thanks for the sanity check,

Bob Evans



Better Broken
=============
#!/usr/bin/env ruby

require 'rexml/document'
require 'date'

class DateFun
## BEGIN Different
include REXML
## END Different

def parse(xml)
## BEGIN Different
doc = Document.new(xml)
##End Different

elems = doc.root.get_elements('//body/dateelement[@date]')
elems.map { |s|
s.attributes["date"].to_s
}.sort
end

def sorted_dates_from(xml)
sorted_dates = parse(xml)
sorted_dates.map { |d| Date.parse(d)}.sort

What's happening is that you're bringing REXML::Date into scope. You
need to do:

::Date.parse

to get the top-level Date constant.


David

--
David A. Black | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 
R

Robert Evans

What's happening is that you're bringing REXML::Date into scope. You
need to do:

::Date.parse

to get the top-level Date constant.


David

Ah cool. I didn't realize there was a REXML::Date class, but I
suspected it might be something like that, and I didn't realize I
could do just ::Date to fully qualify top level modules.

Thanks,
Bob Evans
 
D

dblack

Hi --

Ah cool. I didn't realize there was a REXML::Date class, but I suspected it
might be something like that, and I didn't realize I could do just ::Date to
fully qualify top level modules.

REXML::Date is actually a constant, but same idea.


David

--
David A. Black | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 

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
473,774
Messages
2,569,596
Members
45,127
Latest member
CyberDefense
Top