【问题标题】:Convert XML string to hash in Rails在 Rails 中将 XML 字符串转换为哈希
【发布时间】:2013-06-13 04:59:03
【问题描述】:

我使用了一些返回 xml 的服务:

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

我需要将此字符串转换为哈希。像这样的:

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

用什么方法?

【问题讨论】:

标签: ruby-on-rails ruby-on-rails-3


【解决方案1】:

内置的from_xml Rails Hash 方法将完全满足您的需求。为了让您的 response.parsed_response 正确映射到哈希,您需要将 gsub() 换行:

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

在 Rails 中解析散列的上下文中,从一般编程的角度来看,String 类型的对象比 Symbol 类型的对象是 not substantively different。但是,您可以将 Rails symbolize_keys 方法应用于输出:

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

如您所见,symbolize_keys 不会对任何嵌套散列进行操作,但您可能会遍历内部散列并应用 symbolize_keys

难题的最后一部分是将字符串"true" 转换为布尔值true。 AFAIK,没有办法在您的哈希上执行此操作,但如果您正在对其进行迭代/操作,您可能会实施类似suggested in this post 的解决方案:

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

基本上,当您到达内部键值对时,您会将to_boolean() 应用于当前设置为"true" 的值。在您的示例中,返回值为布尔值true

【讨论】:

  • 仅供参考,Rails 有一个 deep_symbolize_keys 方法,所以你不需要遍历内部哈希
【解决方案2】:

使用 nokogiri 将 XML 响应解析为 ruby​​ 哈希。速度挺快的。

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

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

【讨论】:

    【解决方案3】:

    你可以试试这个:

    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"}}
    

    【讨论】:

    • 感谢您包含在 ruby​​ 外部 Rails 中使用的要求!
    【解决方案4】:

    使用 gem Nokogir

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

    这些tutorials 可能会对您有所帮助。

    【讨论】:

    • 希望它不会像我得到的那样给出精确的哈希值#&lt;Nokogiri::XML::Document:0x16e3790 name="document" children=[#&lt;Nokogiri::XML::Element:0x16e32e0 name="result" children=[#&lt;Nokogiri::XML::Element:0x16e30ec name="success" children=[#&lt;Nokogiri::XML::Text:0x16e2de0 "true"&gt;]&gt;]&gt;]&gt;
    【解决方案5】:

    我找到了一个可以做到这一点的宝石:

    gem 'actionpack-xml_parser'
    

    基本上,每个节点代表一个键。使用以下 XML:

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

    生成的参数将是:

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

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

    【讨论】:

      猜你喜欢
      • 2017-06-02
      • 1970-01-01
      • 1970-01-01
      • 2010-11-05
      • 2011-05-08
      • 2016-10-21
      • 1970-01-01
      • 1970-01-01
      • 2021-12-30
      相关资源
      最近更新 更多