世界上最伟大的投资就是投资自己的教育

首页Ruby
随风 · 凡人

Ruby 的 xml 和 json 解析

随风发布于1477 次阅读

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 条回复
暂无回复~~
喜欢
我的微信官网服务号精品文章订阅号微信视频号
程序员随风
统计信息
    学员: 21523
    视频数量: 1376
    文章数量: 455

© 汕尾市求知科技有限公司 | 专业版网站 | 关于我们 | 在线学员:1152

粤公网安备 44152102000088号粤公网安备 44152102000088号 | 粤ICP备19038915号

Top