ruby-on-rails – 如何在Rails中将XML转换为哈希?

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – 如何在Rails中将XML转换为哈希?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
如何在 @L_404_0@中将XML主体转换为哈希?

我有一个XML体,我想解析成哈希

  1. <soap:Body>
  2. <TimesInMyDAY>
  3. <TIME_DATA>
  4. <StartTime>2010-11-10T09:00:00</StartTime>
  5. <EndTime>2010-11-10T09:20:00</EndTime>
  6. </TIME_DATA>
  7. <TIME_DATA>
  8. <StartTime>2010-11-10T09:20:00</StartTime>
  9. <EndTime>2010-11-10T09:40:00</EndTime>
  10. </TIME_DATA>
  11. <TIME_DATA>
  12. <StartTime>2010-11-10T09:40:00</StartTime>
  13. <EndTime>2010-11-10T10:00:00</EndTime>
  14. </TIME_DATA>
  15. <TIME_DATA>
  16. <StartTime>2010-11-10T10:00:00</StartTime>
  17. <EndTime>2010-11-10T10:20:00</EndTime>
  18. </TIME_DATA>
  19. <TIME_DATA>
  20. <StartTime>2010-11-10T10:40:00</StartTime>
  21. <EndTime>2010-11-10T11:00:00</EndTime>
  22. </TIME_DATA>
  23. </TimesInMyDAY>
  24. </soap:Body>

我想把它转换成这样的哈希:

  1. { :times_in_my_day => {
  2. :time_data = > [
  3. {:start_time=>"2010-11-10T09:00:00",:end_time => "2010-11-10T09:20:00" },{:start_time=>"2010-11-10T09:20:00",:end_time => "2010-11-10T09:40:00" },{:start_time=>"2010-11-10T09:40:00",:end_time => "2010-11-10T10:00:00" },{:start_time=>"2010-11-10T10:00:00",:end_time => "2010-11-10T10:20:00" },{:start_time=>"2010-11-10T10:40:00",:end_time => "2010-11-10T11:00:00" }
  4. ]
  5. }
  6. }

理想情况下,标记会转换为snake_case符号并成为哈希中的键.

此外,日期时间缺少其时区偏移.它们位于当地时区(不是UTC).所以我想解析它以显示本地偏移量,然后将xml日期时间字符串转换为Rails DateTime对象.结果数组将是这样的:

  1. { :times_in_my_day => {
  2. :time_data = > [
  3. {:start_time=>Wed Nov 10 09:00:00 -0800 2010,:end_time => Wed Nov 10 9:20:00 -0800 2010 },{:start_time=>Wed Nov 10 09:20:00 -0800 2010,:end_time => Wed Nov 10 9:40:00 -0800 2010 },{:start_time=>Wed Nov 10 09:40:00 -0800 2010,:end_time => Wed Nov 10 10:00:00 -0800 2010 },{:start_time=>Wed Nov 10 10:00:00 -0800 2010,:end_time => Wed Nov 10 10:20:00 -0800 2010 },{:start_time=>Wed Nov 10 10:40:00 -0800 2010,:end_time => Wed Nov 10 11:00:00 -0800 2010 }
  4. ]
  5. }
  6. }

我能够用这种方式用parse和in_time_zone方法转换单个日期时间:

  1. Time.parse(xml_datetime).in_time_zone(current_user.time_zone)

但是我不太确定在将XML转换为哈希时解析时间的最佳方法.

我很感激任何建议.谢谢!

编辑

将datetime字符串转换为Rails DateTime对象的代码错误的.这会将xml日期时间字符串解析为系统的时区偏移量,然后将该时间转换为用户的时区.正确的代码是:

Time.zone.parse(xml_datetime)

如果用户具有不同于系统的时区,则会将用户的时区偏移量添加到原始日期时间字符串.这里有一个关于如何启用用户时区首选项的Railscast:http://railscasts.com/episodes/106-time-zones-in-rails-2-1.

解决方法

我以前在Perl中使用XML :: Simple,因为使用Perl解析XML是一个PITA.

当我切换到Ruby时,我最终使用了Nokogiri,发现它非常容易用于解析HTML和XML.我认为在CSS或XPath选择器方面很容易,并且不要错过XML-to-hash转换器.

  1. require 'ap'
  2. require 'date'
  3. require 'time'
  4. require 'nokogiri'
  5.  
  6. xml = %{
  7. <soap:Body>
  8. <TimesInMyDAY>
  9. <TIME_DATA>
  10. <StartTime>2010-11-10T09:00:00</StartTime>
  11. <EndTime>2010-11-10T09:20:00</EndTime>
  12. </TIME_DATA>
  13. <TIME_DATA>
  14. <StartTime>2010-11-10T09:20:00</StartTime>
  15. <EndTime>2010-11-10T09:40:00</EndTime>
  16. </TIME_DATA>
  17. <TIME_DATA>
  18. <StartTime>2010-11-10T09:40:00</StartTime>
  19. <EndTime>2010-11-10T10:00:00</EndTime>
  20. </TIME_DATA>
  21. <TIME_DATA>
  22. <StartTime>2010-11-10T10:00:00</StartTime>
  23. <EndTime>2010-11-10T10:20:00</EndTime>
  24. </TIME_DATA>
  25. <TIME_DATA>
  26. <StartTime>2010-11-10T10:40:00</StartTime>
  27. <EndTime>2010-11-10T11:00:00</EndTime>
  28. </TIME_DATA>
  29. </TimesInMyDAY>
  30. </soap:Body>
  31. }
  32.  
  33. time_data = []
  34.  
  35. doc = Nokogiri::XML(xml)
  36. doc.search('//TIME_DATA').each do |t|
  37. start_time = t.at('StartTime').inner_text
  38. end_time = t.at('EndTime').inner_text
  39. time_data << {
  40. :start_time => DateTime.parse(start_time),:end_time => Time.parse(end_time)
  41. }
  42. end
  43.  
  44. puts time_data.first[:start_time].class
  45. puts time_data.first[:end_time].class
  46. ap time_data[0,2]

输出看起来像:

  1. DateTime
  2. Time
  3. [
  4. [0] {
  5. :start_time => #<DateTime: 2010-11-10T09:00:00+00:00 (19644087/8,0/1,2299161)>,:end_time => 2010-11-10 09:20:00 -0700
  6. },[1] {
  7. :start_time => #<DateTime: 2010-11-10T09:20:00+00:00 (22099598/9,:end_time => 2010-11-10 09:40:00 -0700
  8. }
  9. ]

故意将时间值解析为DateTime和Time对象,以显示可以使用其中任何一个.

猜你在找的Ruby相关文章