[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Creating New Objects from REXML::Elements

eddieroger

12/21/2006 6:39:00 AM

Hello group,

I'm new to using REXML to parse documents, but quickly getting the hang
of it. Something, however, is giving me a little trouble, so I could
use some help. I'm trying to create a new object, specifically a Movie
from elements in Delicious Library's XML data file (a Mac program,
found at http://www.delicious-m...). Basically, the XML file
stores the good stuff in tag attributes, and I'd rather make a new
objects from the attributes. I can pull the attributes, and puts proves
I'm pulling right, but when I try to push my new objects into an array,
the class identifies itself as an REXML::Element instead of a Movie.

This is the method that puts the new Movies into the array.
def get_movies
temp = @library.root
temp.elements.each('items/movie') { |movie|
@movies.push(Movie.new(movie.attributes['uuid'],
movie.attributes['fullTitle'], movie.attributes['asin'],
movie.attributes['mpaarating'], movie.attributes['minutes'],
movie.attributes['published'], movie.attributes['price']))
puts movie.attributes['fullTitle']
}
end

But, irb tells me this:
irb(main):025:0> movies.class
=> Array
irb(main):026:0> movies[1].class
=> REXML::Element


Am I doing something completely wrong? Shouldn't the values of the
attributes be passed directly to the constructor and I get a new object
of class Movie?

Thanks for the help,
Eddie

9 Answers

Peter Szinek

12/21/2006 8:06:00 AM

0

eddieroger wrote:
> Hello group,
>
> I'm new to using REXML to parse documents, but quickly getting the hang
> of it. Something, however, is giving me a little trouble, so I could
> use some help. I'm trying to create a new object, specifically a Movie
> from elements in Delicious Library's XML data file (a Mac program,
> found at http://www.delicious-m...). Basically, the XML file
> stores the good stuff in tag attributes, and I'd rather make a new
> objects from the attributes. I can pull the attributes, and puts proves
> I'm pulling right, but when I try to push my new objects into an array,
> the class identifies itself as an REXML::Element instead of a Movie.
>
> This is the method that puts the new Movies into the array.
> def get_movies
> temp = @library.root
> temp.elements.each('items/movie') { |movie|
> @movies.push(Movie.new(movie.attributes['uuid'],
> movie.attributes['fullTitle'], movie.attributes['asin'],
> movie.attributes['mpaarating'], movie.attributes['minutes'],
> movie.attributes['published'], movie.attributes['price']))
> puts movie.attributes['fullTitle']
> }
> end

Can you send the full code? Are you sure that e.g. Movie.new does not
return a REXML::Element for example? Anyway, I can not really figure
this out without seeing the full code.

Cheers,
Peter

__
http://www.rubyra...

Bob Hutchison

12/21/2006 12:47:00 PM

0


On 21-Dec-06, at 3:05 AM, Peter Szinek wrote:

> Can you send the full code? Are you sure that e.g. Movie.new does
> not return a REXML::Element for example? Anyway, I can not really
> figure this out without seeing the full code.
>


And the XML as well.

Cheers,
Bob

> Cheers,
> Peter

----
Bob Hutchison -- blogs at <http://www.rec...
hutch/>
Recursive Design Inc. -- <http://www.rec...>
Raconteur -- <http://www.raconteur...
xampl for Ruby -- <http://rubyforge.org/projects/...




eddieroger

12/21/2006 2:25:00 PM

0

Here is the full Ruby code:

require 'rexml/document'
include REXML

class DeliciousLibrary

#usual_path is the path of the DL XML file (until v2). Unless this
script is on a server, this works.
@@usual_path = "#{ENV['HOME']}/Library/Application Support/Delicious
Library/Library Media Data.xml"

@@medium_covers = "#{ENV['HOME']}/Library/Application
Support/Delicious Library/Medium Covers/" #requires UUID for
identification

def initialize(file = @@usual_path)
@library = Document.new(File.new(file))
@movies = Array.new
end

def get_library_as_xml
@library.root
end

def get_movies
temp = @library.root
temp.elements.each('items/movie') { |movie|
@movies.push(Movie.new(movie.attributes['uuid'].to_str,
movie.attributes['fullTitle'], movie.attributes['asin'],
movie.attributes['mpaarating'], movie.attributes['minutes'],
movie.attributes['published'], movie.attributes['price']))
puts movie.attributes['fullTitle']
}
end

def get_shelves
@library.root.elements['items/shelves']
end



end

class Movie
#Some Supplimental Classes
def initialize(uuid, fullTitle, asin, mpaarating, minutes, published,
price)
@uuid = uuid
@fullTitle = fullTitle
@asin = asin
@mpaarating = mpaarating
@minutes = minutes
@published = published
@price = price
end
attr_reader :uuid, :fullTitle, :asin, :mpaarating, :minutes,
:published, :price
end

The XML file is about 7000 lines long, os here's a snippet. i don't
think you really want 7000 lines of code listed anyway.

<movie asin="B000BW7QWW" aspect="DVD" country="us" created="188189008"
currentValue="$9.96"
features="AC-3&#x000a;Animated&#x000a;Color&#x000a;Dolby&#x000a;Dubbed&#x000a;Subtitled&#x000a;Widescreen&#x000a;NTSC&#x000a;2.35:1"
fullTitle="Serenity (Widescreen Edition)" genre="Sci-Fi
Action&#x000a;Futuristic&#x000a;Space Adventure&#x000a;Action &amp;
Adventure&#x000a;Science Fiction &amp; Fantasy"
lastLookupTime="188189024" minutes="119" mpaarating="PG-13"
netrating="4.5" price="$19.98" published="20-12-2005"
publisher="Universal Studios Home Entertainment"
purchaseDate="18-12-2006" stars="Chiwetel Ejiofor&#x000a;Nathan
Fillion&#x000a;Gina Torres&#x000a;Morena Baccarin&#x000a;Adam
Baldwin&#x000a;Raphael Feldman&#x000a;Yan Feldman&#x000a;Ron
Glass&#x000a;Summer Glau&#x000a;Michael Hitchcock&#x000a;Glenn
Howerton&#x000a;David Krumholtz&#x000a;Sean Maher&#x000a;Sarah
Paulson&#x000a;Nectar Rose&#x000a;Jewel Staite&#x000a;Tamara
Taylor&#x000a;Alan Tudyk&#x000a;Hunter Ansley Wryn"
theatricalDate="30-09-2005" title="Serenity" upc="0025192632723"
uuid="0CEA2670-C438-4C35-95A6-35F2E21DD05E">
....
</movie>


Thanks for the help.



Bob Hutchison wrote:
> On 21-Dec-06, at 3:05 AM, Peter Szinek wrote:
>
> > Can you send the full code? Are you sure that e.g. Movie.new does
> > not return a REXML::Element for example? Anyway, I can not really
> > figure this out without seeing the full code.
> >
>
>
> And the XML as well.
>
> Cheers,
> Bob
>
> > Cheers,
> > Peter
>
> ----
> Bob Hutchison -- blogs at <http://www.rec...
> hutch/>
> Recursive Design Inc. -- <http://www.rec...>
> Raconteur -- <http://www.raconteur...
> xampl for Ruby -- <http://rubyforge.org/projects/...

Tom Pollard

12/22/2006 5:52:00 AM

0


On Dec 21, 2006, at 1:40 AM, eddieroger wrote:
> [...] when I try to push my new objects into an array,
> the class identifies itself as an REXML::Element instead of a Movie.
> [...]
> irb tells me this:
> irb(main):025:0> movies.class
> => Array
> irb(main):026:0> movies[1].class
> => REXML::Element

I've encountered precisely this same problem! I use REXML to pull
values out of an XML document and into an object; but, instead of my
objects, I end up with an Array of REXML::Element's. :-(

TomP

eddieroger

12/22/2006 6:19:00 AM

0

Have you solved this? A fancy workaround, perhaps? Short of actually
making strings equivalent to the pieces, I am running out of ideas,
except the inefficiency of that kills me. I guess I'll give that a shot
and post an update if I get it to work.

Tom Pollard wrote:
> On Dec 21, 2006, at 1:40 AM, eddieroger wrote:
> > [...] when I try to push my new objects into an array,
> > the class identifies itself as an REXML::Element instead of a Movie.
> > [...]
> > irb tells me this:
> > irb(main):025:0> movies.class
> > => Array
> > irb(main):026:0> movies[1].class
> > => REXML::Element
>
> I've encountered precisely this same problem! I use REXML to pull
> values out of an XML document and into an object; but, instead of my
> objects, I end up with an Array of REXML::Element's. :-(
>
> TomP

Bob Hutchison

12/22/2006 12:27:00 PM

0


On 21-Dec-06, at 9:25 AM, eddieroger wrote:

> def get_movies
> temp = @library.root
> temp.elements.each('items/movie') { |movie|
> @movies.push(Movie.new(movie.attributes['uuid'].to_str,
> movie.attributes['fullTitle'], movie.attributes['asin'],
> movie.attributes['mpaarating'], movie.attributes['minutes'],
> movie.attributes['published'], movie.attributes['price']))
> puts movie.attributes['fullTitle']
> }
> end

Have you tried to_str on *all* of the arguments?

Cheers,
Bob

----
Bob Hutchison -- blogs at <http://www.rec...
hutch/>
Recursive Design Inc. -- <http://www.rec...>
Raconteur -- <http://www.raconteur...
xampl for Ruby -- <http://rubyforge.org/projects/...




Tom Pollard

12/22/2006 3:04:00 PM

0


On Dec 22, 2006, at 1:20 AM, eddieroger wrote:
> Have you solved this?

No, not yet. I'll try to find some more time to play with it (and
try Bob's suggestion) this evening.

TomP

eddieroger

12/23/2006 5:45:00 AM

0

Not exactly what I did right, but I managed to get it. Basically, its
the same as before, but I replaced my get_movies and get_library with
this:

def get_library
@library
end

def get_movies
allmovies = Array.new
temp = get_library
temp = temp.root
temp.elements.each('items/movie') { |movie|
tempm = Movie.new(movie.attributes['uuid'].to_s,
movie.attributes['title'].to_s, movie.attributes['asin'].to_s,
movie.attributes['mpaarating'].to_s, movie.attributes['minutes'].to_s,
movie.attributes['published'].to_s, movie.attributes['price'].to_s)
allmovies << tempm
}
return allmovies
end

So, @movies isn't initialized any more, and I just return the array of
Movies to irb or whatever calls it. I realized that I needed it there
more anyway, and if i really want it automatically created, I'll just
set @movies = get_movies in the constructor. Also, notice the .to_s
after each attribute. I'm not sure if its necessary, but that's just
how it is for now. Thanks for the help, all.

Eddie

Tom Pollard

12/30/2006 3:42:00 PM

0


On Dec 22, 2006, at 1:20 AM, eddieroger wrote:
> Tom Pollard wrote:
>> On Dec 21, 2006, at 1:40 AM, eddieroger wrote:
>>> [...] when I try to push my new objects into an array,
>>> the class identifies itself as an REXML::Element instead of a Movie.
>>> [...]
>>> irb tells me this:
>>> irb(main):025:0> movies.class
>>> => Array
>>> irb(main):026:0> movies[1].class
>>> => REXML::Element
>>
>> I've encountered precisely this same problem! I use REXML to pull
>> values out of an XML document and into an object; but, instead of my
>> objects, I end up with an Array of REXML::Element's. :-(
>
> Have you solved this?

Finally. I realized I'd made the bone-headed mistake of not
specifying an explicit return value in my function that processed the
REXML fragment. What I had was

class Evcase
def from_rexml ( record )
record.each_element do |el|
begin
self.send("ev_#{el.name.downcase}=", el.text)
rescue
Evcase.create_accessors(el.name.downcase)
retry
end
end
end
end

This was used from code that looked like

doc.root.get_elements('PROBLEM_RECORD').each do |rec|
@cases << Evcase.new.from_rexml(rec)
end

This latter code depends on the Evcase object being returned from the
_from_rexml method; instead, it was returning the REXML element
('record') that had been passed in. I'm not sure why it took me so
long to see that. Hope this helps someone else...

TomP