首页ruby
hfpp2012

Ruby 的 xml 和 json 解析

hfpp2012发布于

1. 介绍

但凡是程序员,应该都有接触过xml和json吧。有很多api也是用xml和json来交互数据的。这篇文章来介绍如何用ruby来处理xml和json。

2. xml

ruby的标准库rexml就有对xml的解析处理。不过没多少人直接用它。

下面介绍几个其他的xml解析库。

2.1 roxml

我在开发微信公众账号接口的时候使用过这个库roxml,虽然好久不更新了,但是还是蛮好用的。它能把你的ruby对象或者数据映射成xml对象的属性,例如下面这个例子:

class ReplyMessage
  include ROXML
  xml_name :xml

  xml_accessor :ToUserName, :cdata   => true
  xml_accessor :FromUserName, :cdata => true
  xml_reader   :CreateTime, :as => Integer
  xml_reader   :MsgType, :cdata => true

  def initialize
    @CreateTime = Time.now.to_i
  end

  def to_xml
    super.to_xml(:encoding => 'UTF-8', :indent => 0, :save_with => 0)
  end
end
2.2 nokogiri

nokogiri是用c语言写的,能够解析xml和html,主要的特征是它用够用类似css选择器那样的语法来查询xml或html元素。因为它能够很好地解析html,所以经常被用于爬虫程序。官方就有它的使用方法,功能很强大。

require 'open-uri'
require 'nokogiri'
(1..10).each do |num|
  doc = Nokogiri::HTML(open("https://ruby-china.org/topics?page=#{num}"))
  doc.css("div.topic").each do |node|
    puts "#{node.css('> div.infos > div.title > a').text} #{node.css("> div.count > a").text}"
  end
end
2.3 libxml-ruby

libxml-ruby是用c语言写的xml的ruby实现。它的特点是速度快,性能好。要使用它远没有roxml这个库简单,下面介绍另一个库来更好地使用它。

2.4 multi_xml

multi_xml是一个被使用得比较多的库,它能够为上面的几个库提供统一的接口,上面的几个库也就相当于驱动(适配器),使用它也就能够轻易地换解析驱动。

require 'multi_xml'

MultiXml.parser = :ox
MultiXml.parser = MultiXml::Parsers::Ox # Same as above
MultiXml.parse('<tag>This is the contents</tag>') # Parsed using Ox

MultiXml.parser = :libxml
MultiXml.parser = MultiXml::Parsers::Libxml # Same as above
MultiXml.parse('<tag>This is the contents</tag>') # Parsed using LibXML

MultiXml.parser = :nokogiri
MultiXml.parser = MultiXml::Parsers::Nokogiri # Same as above
MultiXml.parse('<tag>This is the contents</tag>') # Parsed using Nokogiri

MultiXml.parser = :rexml
MultiXml.parser = MultiXml::Parsers::Rexml # Same as above
MultiXml.parse('<tag>This is the contents</tag>') # Parsed using REXML

MultiXml.parser = :oga
MultiXml.parser = MultiXml::Parsers::Oga # Same as above
MultiXml.parse('<tag>This is the contents</tag>') # Parsed using Oga

3. json

ruby的标准库就有json解析功能的实现。网址可见于:http://ruby-doc.org/stdlib-2.2.2/libdoc/json/rdoc/JSON.html。

require 'json'

my_hash = JSON.parse('{"hello": "goodbye"}')
puts my_hash["hello"] => "goodbye"

my_hash = {:hello => "goodbye"}
puts JSON.generate(my_hash) => "{\"hello\":\"goodbye\"}"

puts {:hello => "goodbye"}.to_json => "{\"hello\":\"goodbye\"}"

我们经常使用的to_json方法就是它所提供的功能。

3.1 json

json是用c语言和java语言写的ruby实现。它是对标准库的json的功能的扩展,包括对字符集更好的支持、解析功能的增强。

json = JSON.generate [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
# => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"

class Range
  def to_json(*a)
    {
      'json_class'   => self.class.name, # = 'Range'
      'data'         => [ first, last, exclude_end? ]
    }.to_json(*a)
  end
end
3.2 yajl-ruby

yajl-ruby是一个YAJL C的ruby实现,它性能好,速度快,是对流的处理,支持编码,压缩等,还兼容上文所说的json这个gem,为的是提高其解析速度。

json = File.new('test.json', 'r')
parser = Yajl::Parser.new
hash = parser.parse(json)

cat someJsonFile.json | ruby -ryajl -e "puts Yajl::Parser.parse(STDIN).inspect"

它还能解析api服务器返回的json数据。

require 'uri'
require 'yajl/http_stream'

url = URI.parse("http://search.twitter.com/search.json?q=engineyard")
results = Yajl::HttpStream.get(url)

更多的功能可以看官方的readme文档。

3.3 oj

ob是一个用c语言写的ruby实现,它的性能比yajl还高,还能对json的输出进行格式化。

require 'oj'

h = { 'one' => 1, 'array' => [ true, false ] }
json = Oj.dump(h)

# json =
# {
#   "one":1,
#   "array":[
#     true,
#     false
#   ]
# }

h2 = Oj.load(json)
puts "Same? #{h == h2}"
# true
3.4 multi_json

multi_json是一个类似multi-xml的gem,它也能对各种json解析库进行统一的封装,它不能指定驱动,是按照自己的规则来load解析库的。

MultiJSON tries to have intelligent defaulting. That is, if you have any of the supported engines already loaded, it will utilize them before attempting to load any. When loading, libraries are ordered by speed. First Oj, then Yajl, then the JSON gem, then JSON pure. If no other JSON library is available, MultiJSON falls back to OkJson, a simple, vendorable JSON parser.

require 'multi_json'

MultiJson.load('{"abc":"def"}') #=> {"abc" => "def"}
MultiJson.load('{"abc":"def"}', :symbolize_keys => true) #=> {:abc => "def"}
MultiJson.dump({:abc => 'def'}) # convert Ruby back to JSON
MultiJson.dump({:abc => 'def'}, :pretty => true) # encoded in a pretty form (if supported by the coder)

完结。

本站帖子均为原创内容,如需转载请注明出处,谢谢。

0 条回复
暂无回复~~
喜欢
友情提示
   官方 QQ 1 群 697272886(500/2000)
   官方 QQ 2 群 856141852

© 汕尾市求知科技有限公司 | 隐私条款 | 服务条款 | 粤ICP备15004902号 | 在线学员:24

Top