ruby-on-rails – 如何在Rails中将XML转换为哈希?
如何在
Ruby中将XML主体转换为哈希?
我有一个XML体,我想解析成哈希 <soap:Body> <TimesInMyDAY> <TIME_DATA> <StartTime>2010-11-10T09:00:00</StartTime> <EndTime>2010-11-10T09:20:00</EndTime> </TIME_DATA> <TIME_DATA> <StartTime>2010-11-10T09:20:00</StartTime> <EndTime>2010-11-10T09:40:00</EndTime> </TIME_DATA> <TIME_DATA> <StartTime>2010-11-10T09:40:00</StartTime> <EndTime>2010-11-10T10:00:00</EndTime> </TIME_DATA> <TIME_DATA> <StartTime>2010-11-10T10:00:00</StartTime> <EndTime>2010-11-10T10:20:00</EndTime> </TIME_DATA> <TIME_DATA> <StartTime>2010-11-10T10:40:00</StartTime> <EndTime>2010-11-10T11:00:00</EndTime> </TIME_DATA> </TimesInMyDAY> </soap:Body> 我想把它转换成这样的哈希: { :times_in_my_day => { :time_data = > [ {: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" } ] } } 理想情况下,标记会转换为snake_case符号并成为哈希中的键. 此外,日期时间缺少其时区偏移.它们位于当地时区(不是UTC).所以我想解析它以显示本地偏移量,然后将xml日期时间字符串转换为Rails DateTime对象.结果数组将是这样的: { :times_in_my_day => { :time_data = > [ {: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 } ] } } 我能够用这种方式用parse和in_time_zone方法转换单个日期时间: 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转换器. require 'ap' require 'date' require 'time' require 'nokogiri' xml = %{ <soap:Body> <TimesInMyDAY> <TIME_DATA> <StartTime>2010-11-10T09:00:00</StartTime> <EndTime>2010-11-10T09:20:00</EndTime> </TIME_DATA> <TIME_DATA> <StartTime>2010-11-10T09:20:00</StartTime> <EndTime>2010-11-10T09:40:00</EndTime> </TIME_DATA> <TIME_DATA> <StartTime>2010-11-10T09:40:00</StartTime> <EndTime>2010-11-10T10:00:00</EndTime> </TIME_DATA> <TIME_DATA> <StartTime>2010-11-10T10:00:00</StartTime> <EndTime>2010-11-10T10:20:00</EndTime> </TIME_DATA> <TIME_DATA> <StartTime>2010-11-10T10:40:00</StartTime> <EndTime>2010-11-10T11:00:00</EndTime> </TIME_DATA> </TimesInMyDAY> </soap:Body> } time_data = [] doc = Nokogiri::XML(xml) doc.search('//TIME_DATA').each do |t| start_time = t.at('StartTime').inner_text end_time = t.at('EndTime').inner_text time_data << { :start_time => DateTime.parse(start_time),:end_time => Time.parse(end_time) } end puts time_data.first[:start_time].class puts time_data.first[:end_time].class ap time_data[0,2] 输出看起来像: DateTime Time [ [0] { :start_time => #<DateTime: 2010-11-10T09:00:00+00:00 (19644087/8,0/1,2299161)>,:end_time => 2010-11-10 09:20:00 -0700 },[1] { :start_time => #<DateTime: 2010-11-10T09:20:00+00:00 (22099598/9,:end_time => 2010-11-10 09:40:00 -0700 } ] 故意将时间值解析为DateTime和Time对象,以显示可以使用其中任何一个. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |