首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在保留空数组和nil值的Rails中将XML转换为哈希

如何在保留空数组和nil值的Rails中将XML转换为哈希
EN

Stack Overflow用户
提问于 2013-03-27 04:31:44
回答 1查看 871关注 0票数 1

当我在Rails中将XML结构转换为使用Hash.from_xml(@xml)进行散列时,解析器不会区分空数组和nil值,而XML将立即以\终止的节点描述为空数组,例如<audio_languages/>与那些将属性nil="true"解释为nil值的节点。

XML结构(由我控制如何生成)如下所示:

代码语言:javascript
复制
<response>
  <medias>
    <media>
      <id>1</id>
      <name>Media-1</name>
      <audio_languages/>
      <avg_rating nil="true"></avg_rating>
    </media>
    <media>
      <id>2</id>
      <name>Media-2</name>
      <audio_languages/>
      <avg_rating nil="true"></avg_rating>
    </media>
  </medias>
</response>

Hash.from_xml(@xml)的预期输出为:

代码语言:javascript
复制
{"response"=>{"medias"=>{"media"=>[{"id"=>"1", "name"=>"Media-1", "audio_languages"=>[], "avg_rating"=>nil}, {"id"=>"2", "name"=>"Media-2", "audio_languages"=>[], "avg_rating"=>nil}]}}} 

相反,对于audio_languagesavg_rating,我得到的值是空值

代码语言:javascript
复制
{"response"=>{"medias"=>{"media"=>[{"id"=>"1", "name"=>"Media-1", "audio_languages"=>nil, "avg_rating"=>nil}, {"id"=>"2", "name"=>"Media-2", "audio_languages"=>nil, "avg_rating"=>nil}]}}}  
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-03-28 08:00:52

最后,我使用libxml解析节点,并检查节点是否具有所需的签名,以确定是否要转换为空数组或nil值。

代码语言:javascript
复制
# Usage: Hash.from_xml_with_libxml(xml)
require 'xml/libxml'
# adapted from 
# http://movesonrails.com/articles/2008/02/25/libxml-for-active-resource-2-0

class Hash 
  class << self
    def from_xml_with_libxml(xml, strict=true) 
      LibXML::XML.default_load_external_dtd = false
      LibXML::XML.default_pedantic_parser   = strict
      result = LibXML::XML::Parser.string(xml).parse 
      return { result.root.name.to_s => xml_node_to_hash_with_libxml(result.root)}
    end 

    def xml_node_to_hash_with_libxml(node) 
      # If we are at the root of the document, start the hash 
      if node.element? 
        if node.children? 
          result_hash = {} 

          node.each_child do |child| 
            result = xml_node_to_hash_with_libxml(child) 

            if child.name == "text"
              if !child.next? and !child.prev?
                return result
              end
            elsif result_hash[child.name]
              if result_hash[child.name].is_a?(Object::Array)
                result_hash[child.name] << result
              else
                result_hash[child.name] = [result_hash[child.name]] << result
              end
            else 
              result_hash[child.name] = result
            end
          end
          return result_hash 
        else 
          # Nodes of sort <audio_languages/>, are arrays, 
          # and nodes like <average_rating "nil"="true"/> are nil values.
          if node.to_s.match(/^\<(.+)\/\>$/) && nil == node.attributes["nil"]
            return []
          end
          return nil 
        end 
      else 
        return node.content.to_s 
      end 
    end          
  end
end
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15646811

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档