Rails 3: обнаружение типов при разборе XML - PullRequest
1 голос
/ 03 ноября 2010

У меня есть простой 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 нет атрибутов типа, поэтому использование Hash.from_xml просто анализирует каждое поле как строку.То, что я ищу, это своего рода автоопределение типа поля.Я также посмотрел на Nokogiri, но это не может быть выведено как хэш.

Какой самый простой и эффективный способ добиться этого?

Большое спасибо.

Ответы [ 4 ]

2 голосов
/ 05 января 2011

Rails автоматически преобразует строки в их нужные типы перед сохранением модели. Например, когда вы делаете: ModelName.create( params[:model_name] )

Редактировать: если ваши хеш-значения не являются отдельными столбцами, например вы их сериализуете.

2 голосов
/ 04 ноября 2010

Правильный способ справиться с этим - создать небольшой 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", чтобы получить хеш.

1 голос
/ 04 ноября 2010

Либо укажите его как атрибут в XML:

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

, либо просто используйте соответствующий метод преобразования в Ruby, если вы знаете, что получаете:

hash[:strField].to_i

Не будет особого волшебного способа сделать это.Вы можете попытаться проанализировать, что находится в строке, но вы можете легко получить строку «1/2/1234», которая выглядит как дата, но должна быть строкой.

1 голос
/ 04 ноября 2010

XML не обязательно имеет индикатор для типа значения в узле. Вы должны знать это, или ваш код синтаксического анализа, прежде чем вы получите данные. Базы данных, которые выводят XML или электронные таблицы, часто знают о типе данных, и они попытаются дать вам какое-то определение, но нет ничего, что гарантировало бы, что то, что они называют своим фиксированным номером, будет соответствовать тому, что Ruby называет им. В результате вам все равно придется выполнить какое-либо сопоставление / сопоставление атрибутов, чтобы понять, что они вам отправляют.

Если у вас есть хеш, было бы не сложно написать код для его обхода и преобразования значений в ожидаемые вами типы, или просто делайте это по мере использования значений.

Я всегда использую Nokogiri для непосредственного анализа XML, а затем я устанавливаю типы значений при обработке узлов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...