简体   繁体   中英

Convert XML string to hash in Rails

I using some service that returns xml:

response = HTTParty.post(service_url)
response.parsed_response 
=> "\n\t<Result>\n<success>\ntrue\n</success>\n</Result>"

I need to convert this string to hash. Something like this:

response.parsed_response.to_hash
=> {:result => { :success => true } }

Which way to do this?

The built-in from_xml Rails Hash method will do precisely what you want. In order to get your response.parsed_response correctly mapped to a hash, you'll need to gsub() out the newlines:

hash = Hash.from_xml(response.parsed_response.gsub("\n", "")) 
hash #=> {"Result"=>{"success"=>"true"}}

In the context of parsing a hash in Rails, objects of String type are not substantively different than those of Symbol from a general programming perspective. However, you can apply the Rails symbolize_keys method to the output:

symbolized_hash = hash.symbolize_keys
#=> {:Result=>{"success"=>"true"}} 

As you can see, symbolize_keys doesn't operate on any nested hashes, but you could potentially iterate through inner hashes and apply symbolize_keys .

The final piece of the puzzle is to convert the string "true" to the boolean true . AFAIK, there's no way to do this on your hash in place, but if you're iterating/operating on it, you could potentially implement a solution like the one suggested in this post :

def to_boolean(str)
     return true if str == "true"
     return false if str == "false"
     return nil
end

Basically, when you reach the inner key-value pair, you'd apply to_boolean() to the value, which is currently set to "true" . In your example, the return value is the boolean true .

Use nokogiri to parse XML response to ruby hash. It's pretty fast.

require 'active_support/core_ext/hash'  #from_xml 
require 'nokogiri'

doc = Nokogiri::XML(response_body)
Hash.from_xml(doc.to_s)

You can try this below:

require 'active_support/core_ext/hash/conversions'  
str = "\n\t<Result>\n<success>\ntrue\n</success>\n</Result>".gsub("\n", "").downcase

Hash.from_xml(str)
# => {"result"=>{"success"=>"true"}}

Use gem Nokogir

doc = Nokogiri::XML(xml_string)

data = doc.xpath("//Result").map do |result|
  [
    result.at("success").content
  ]
end

These tutorials may help you.

I found a gem which does exactly that:

gem 'actionpack-xml_parser'

Basically, each node represents a key. With the following XML:

<person><name>David</name></person>

The resulting parameters will be:

{"person" => {"name" => "David"}}

https://github.com/eileencodes/actionpack-xml_parser

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM