Mapping xml to active record objects

I’ve built a simple service that returns an xml feed like so:

blah blah 1 blah blah 2 etc..

What is a quick way to map this result to an array of user objects?



Just to answer my own question: Hpricot!

Very, very easy to do this now. Here’s an example.

doc = HJpricot(open(“http://locahost:3000/user/list”))
(doc/:user).each do |user|
u = = (user/:login).innerHTML
u.first_name = (user:/:first_name).innerHTML

This has got to be the easiest thing I’ve ever done to consume XML.

Here's another option... If your xml elements match your User model's
attribute names, you can just convert the xml to a hash and loop through
its contents:

xml = <your xml>
users = []
Hash.from_xml(xml)['users']['user'].each { |user_vals|
  users <<


Marlon Moyer wrote:

I've got an almost identical problem, except my data looks like:

  <user id="1">
  <user id="2">

I'm really struggling with Hpricot - my brain just isn't working today
(probably because of the aircon problems at work today...). If
someone could show me how to map *this* to an array of User objects,
I'd greatly appreciate it.

Thanks in advance

Dave M.

Sorry, I think the quick and easy stops once you start having attributes
on your elements (or, have elements that don't match your user's fields).

Take a look at ReXML:

Comes with standard with Ruby, IIRC.


David Mitchell wrote:

Yep, that's kind of what I suspected.


Dave M.

Um, that's not even XML. But if it were XML (e.g. <first_name>blah</
first_name>) you could do something like this:

  # require 'rubygems' # if installed via Gems
  require 'xml/libxml'
  doc = XML::Document.file('users.xml')

  doc.find('//user').each do |user|
    u = = user.find_first('@id').content
    u.first_name = user.find_first('first_name').content
    u.last_name = user.find_first('last_name').content

yep, that’s what I was thinking about the format, but given that feed, you could also do something ugly like this:

require ‘rubygems’
require ‘hpricot’

doc = Hpricot(’

' )

(doc/“user”).each do |user|
puts “user id = #{user.attributes[‘id’]}”
puts “first_name = #{user.children[0].to_s.scan(/first_name=”([^"]*)"/).to_s}"


actually, it is xml

the <tagname/> is shorthand for <tagname></tagname>