Parsing data from XML using Ruby and Nokogiri I have a method that parses XML into an array of hashes.

Here is the original XML:



&lt;rowset name="skillqueue" key="queuePosition" columns="queuePosition,typeID,level,startSP,endSP,startTime,endTime"&gt;
  &lt;row queuePosition="0" typeID="20495" level="3" startSP="2829" endSP="16000" startTime="2013-03-04 16:25:50" endTime="2013-03-05 01:02:20"/&gt;
  &lt;row queuePosition="1" typeID="19767" level="4" startSP="40000" endSP="226275" startTime="2013-03-05 01:02:20" endTime="2013-03-07 06:40:31"/&gt;
&lt;/rowset&gt;


Here is the final array of hashes:



[{:queuePosition=&gt;"0", :typeID=&gt;"20495", :level=&gt;"3", :startSP=&gt;"2829", :endSP=&gt;"16000", :startTime=&gt;"2013-03-04 16:25:50", :endTime=&gt;"2013-03-05 01:02:20"}, {:queuePosition=&gt;"1", :typeID=&gt;"19767", :level=&gt;"4", :startSP=&gt;"40000", :endSP=&gt;"226275", :startTime=&gt;"2013-03-05 01:02:20", :endTime=&gt;"2013-03-07 06:40:31"}]


Here is the method, which uses Nokogiri for parsing:

def get_training_queue(xml_data)
  queue = []
  xml_data.xpath("//row").each do |skill_in_queue|
    skill = {}
    skill_in_queue.attributes.each do |details|
      skill[details[0].to_s.to_sym] = details[1].to_s
    end
    queue &lt;&lt; skill
  end
  queue
end


This works great, but it feels a bit inelegant.  


I'm curious if there is a better way to create the hashes within the internal loop?  
I am calling to_s because I couldn't figure out a way to pull out just the key/value without doing so, and it 'feels' like I'm missing some more elegant way of doing that.
Notes:


Use functional Enumerable#map instead of imperative pattern obj = [] +  Enumerable#each + Array#&lt;&lt;.
Use Kernel#Hash to build a hash from its pairs. Note that this method is very ugly and some prefer a more OOP approach, in that case check Enumerable#mash from Facets.
Use nokogiri_node.text.
Arguments in blocks can be unpacked.


I'd write:

require 'nokogiri'
require 'facets'

def get_training_queue(xml_data)
  xml_data.xpath("//row").map do |skill_in_queue|
    skill_in_queue.attributes.mash do |name, attribute|
      [name.to_sym, attribute.text]
    end
  end
end


All those eachs and in-place updates show that you think in imperative terms instead of functional, check this wiki page.