代码之家  ›  专栏  ›  技术社区  ›  gjb

Rails 3:分析XML时检测类型

  •  1
  • gjb  · 技术社区  · 14 年前

    我有一个简单的XML文档,格式如下:

    <?xml version="1.0" encoding="utf-8"?>
    <object>
      <strField>Foo</strField>
      <intField>1</intField>
      <dateField>2010-11-03</dateField>
      <boolField>true</boolField>
      <nilField></nilField>
    </object>
    

    我想将其解析为要传递给model.create的哈希:

    {:object => {
      :strField  => 'Foo',
      :intField  => 1,
      :dateField => Date.today,
      :boolField => true,
      :nilField  => nil }}
    

    遗憾的是,XML中没有“type”属性,因此使用hash.from_xml只将每个字段解析为字符串。我要找的是某种场类型的自动检测。我也看过Nokogiri,但它不能作为散列输出。

    实现这一目标最简单、最有效的方法是什么?

    非常感谢。

    4 回复  |  直到 10 年前
        1
  •  2
  •   Bill Dueber    14 年前

    正确的处理方法是构建一个小的pull解析器。这是错误的方法:-)

    #假定XML包含XML

    def castValue(node)
      puts "Got #{node.name} with content #{node.content}"
      case node.name
      when "strField"
        return node.content
      when "intField"
        return node.content.to_i
      when "dateField"
        return Date.parse(node.content)
      when "boolField"
        case node.content
        when "true"
          return true
        else
          return false
        end
      when "nilField"
        return nil
      end
    end
    
    
    def to_hash xmlstring
      h = {}
      Nokogiri::XML.parse(xmlstring).root.children.each do |node|
        next if node.name == 'text'
        h[node.name] = castValue(node)
      end
      return h
    end
    

    从这里,您只需调用“h=to_hash myxmlstring”来获取散列值。

        2
  •  2
  •   Jeff Peterson    13 年前

    在保存模型之前,Rails将自动将字符串转换为其适当的类型。就像你做的那样: ModelName.create( params[:model_name] )

    编辑:除非散列值不是单独的列,例如,您正在序列化它们。

        3
  •  1
  •   the Tin Man Bryan    14 年前

    XML不一定具有节点中值类型的指示器。在获得数据之前,您应该知道,或者您的解析代码是。输出XML或电子表格的数据库通常知道数据的类型,他们会给你一些定义,但是没有什么能保证他们所称的固定数字与Ruby所称的相匹配。因此,您仍然需要进行某种属性匹配/映射,以了解它们发送给您的内容。

    如果您有一个散列,那么编写代码来遍历它并将值转换为您期望的类型就不会太困难,或者只是在使用值的同时执行它。

    我总是使用nokogiri直接解析XML,然后在处理节点时设置值类型。

        4
  •  1
  •   Karl    14 年前

    在XML中将其指定为属性:

    <intField type="integer">101</intField>
    

    或者只要在Ruby中使用适当的转换方法,如果您知道您收到的是什么:

    hash[:strField].to_i
    

    没有什么神奇的方法可以做到这一点。您可以尝试分析字符串中的内容,但您可以轻松地得到一个“1/2/1234”的字符串,它看起来像一个日期,但应该是一个字符串。