converting from xml name-values into simple hash

17,136

Solution 1

There are a few libraries you can use in Ruby to do this.

Ruby toolbox has some good coverage of a few of them:

https://www.ruby-toolbox.com/categories/xml_mapping

I use XMLSimple, just require the gem then load in your xml file using xml_in:

require 'xmlsimple'
hash = XmlSimple.xml_in('session.xml')

If you're in a Rails environment, you can just use Active Support:

require 'active_support' 
session = Hash.from_xml('session.xml')

Solution 2

Using Nokogiri to parse the XML with namespaces:

require 'nokogiri'

dom = Nokogiri::XML(File.read('OX.session.xml'))

node = dom.xpath('ox:CAppLogin',
                 'ox' => "http://oxbranch.optionsxpress.com").first

hash = node.element_children.each_with_object(Hash.new) do |e, h|
  h[e.name.to_sym] = e.content
end

puts hash.inspect
# {:SessionID=>"FE5E27A056944FBFBEF047F2B99E0BF6",
#  :AccountNum=>"8228-5500", :AccountID=>"967454"}

If you know that the CAppLogin is the root element, you can simplify a bit:

require 'nokogiri'

dom = Nokogiri::XML(File.read('OX.session.xml'))

hash = dom.root.element_children.each_with_object(Hash.new) do |e, h|
  h[e.name.to_sym] = e.content
end

puts hash.inspect
# {:SessionID=>"FE5E27A056944FBFBEF047F2B99E0BF6",
#  :AccountNum=>"8228-5500", :AccountID=>"967454"}
Share:
17,136
Marcos
Author by

Marcos

Pioneers are the ones with arrows in their backs. Investment Portfolio Software, Trade Automation Designer of infinite compression algorithms, and other research projects

Updated on June 29, 2022

Comments

  • Marcos
    Marcos almost 2 years

    I don't know what name this goes by and that's been complicating my search.

    My data file OX.session.xml is in the (old?) form

    <?xml version="1.0" encoding="utf-8"?>
    <CAppLogin xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://oxbranch.optionsxpress.com">
      <SessionID>FE5E27A056944FBFBEF047F2B99E0BF6</SessionID>
      <AccountNum>8228-5500</AccountNum>
      <AccountID>967454</AccountID>
    </CAppLogin>
    

    What is that XML data format called exactly?

    Anyway, all I want is to end up with one hash in my Ruby code like so:

    CAppLogin = { :SessionID => "FE5E27A056944FBFBEF047F2B99E0BF6", :AccountNum => "8228-5500", etc. }   # Doesn't have to be called CAppLogin as in the file, may be fixed
    

    What might be shortest, most built-in Ruby way to automate that hash read, in a way I can update the SessionID value and store it easily back into the file for later program runs?

    I've played around with YAML, REXML but would rather not yet print my (bad) example trials.

  • Marcos
    Marcos almost 12 years
    gem install xml-simple Thanks, I'll check if there's as simple a .xml_out method to save it right back to the file...
  • Marcos
    Marcos almost 12 years
    Thanks, I like your second example better since I don't know/don't want to care what the name of the root element will be, which contains the actual key/value pairs I need to edit and save back into the file somehow.
  • ply
    ply almost 12 years
    Yep, xml_out will take a data structure (Hash, in your case), and return it in XML encoding.