Ruby解析XML(REXML)

XML是可扩展的标记语言,如HTML。它允许程序员开发可以被其他应用程序读取的应用程序,而不管使用的是什么操作系统和开发语言。

它可用于保存中小型数据量,不用在后端有任何基于SQL的技术。

REXML是一个纯Ruby的XML处理器。 它表示一个完整的XML文档,包括PI,doctype等。一个XML文档有一个可以由root()访问的单个子对象。 如果想要为创建的文档提供XML声明,则必须自己添加一个。 REXML文档不为您写入默认声明。

REXML灵感来自于Java的Electric XML库。 它的API易于使用,体积小巧,并遵循Ruby方法的方法命名和代码流。

它支持树和流文档解析。 Steam解析比树解析快1.5倍。 但是,在流解析中无法访问某些功能(如XPath)。

REXML功能:

  • 它100%使用Ruby语言编写。
  • 它包含少于2000行代码,因此更轻巧。
  • 它的方法和类很容易理解。
  • 它随Ruby安装一起提供,不需要单独安装。
  • 它用于DOM和SAX解析。

解析XML和访问元素

现在,从解析XML文档开始,下面是一个示例代码:

require "rexml/document"  
file = File.new( "trial-1.xml" )  
doc = REXML::Document.new file

在上面的代码中,第3行用于解析提供的文件。

示例

require 'rexml/document'   
# file : rexml-example.rb

include REXML   

file = File.new("trial-1.xml")   
doc = Document.new(file)   
puts docs

在上面的代码中,require语句加载了REXML库。 然后包括REXML表示不必使用像REXML:: Document这样的名称。创建了trial-1.xml文件。并将文档显示在屏幕上。

F:\worksp\ruby>ruby rexml-example.rb
<?xml version='1.0' encoding='UTF-8'?>
<root>
        Hello, this is first REXML use.
</root>

F:\worksp\ruby>

Document.new方法将IOString对象或Document作为参数。此参数指定必须读取XML文档的内容。

如果Document构造函数使用Document作为参数,则将其所有元素节点克隆到新的Document对象。 如果构造函数接受一个String参数,则字符串将包含一个XML文档。

XML 和 “Here Document”

这里文档(“Here Document”)是一种指定文本块,保留换行符,空格或使用文本标识的方法。

使用“<<”命令后跟令牌字符串构建文档。

在Ruby中,“<<”和令牌字符串之间不应有空格。

实例

#!/usr/bin/env ruby   
# file : rexml-heredoc.rb

require 'rexml/document'   
include REXML   

info = <<XML   
<info>   
 <name>Maxsu</name>   
 <street>人民大道</street>   
 <city>海口</city>   
 <contact>9854126575</contact>   
 <country>中国</country>   
</info>   
XML   

document = Document.new( info )   
puts document

执行上面代码,得到以下结果 -

F:\worksp\ruby>ruby rexml-heredoc.rb
<info>
 <name>Maxsu</name>
 <street>人民大道</street>
 <city>海口</city>
 <contact>9854126575</contact>
 <country>中国</country>
</info>

F:\worksp\ruby>

在这里,在这里使用文档信息。 包括<<EOFEOF之间的所有字符都是信息的一部分。

对于XML解析示例,使用以下XML文件代码作为输入:



执行上面代码,得到以下结果 -

#!/usr/bin/ruby -w   

require 'rexml/document'
# file : rexml-newxml.rb

include REXML   
xmlfile = File.new("trial-2.xml")   
xmldoc = Document.new(xmlfile)   

# Now get the root element   
root = xmldoc.root   
puts "Root element : " + root.attributes["shelf"]   

# This will output all the cloth titles.   
xmldoc.elements.each("collection/clothing"){   
   |e| puts "cloth Title : " + e.attributes["title"]   
}   

# This will output all the cloth types.   
xmldoc.elements.each("collection/clothing/type") {   
   |e| puts "cloth Type : " + e.text   
}   

# This will output all the cloth description.   
xmldoc.elements.each("collection/clothing/description") {   
   |e| puts "cloth Description : " + e.text   
}

Ruby XML DOM类似的解析

这里演示以树形解析XML数据。 将以上文件trial.xml代码作为输入。

#!/usr/bin/ruby -w   

require 'rexml/document'   
include REXML   

xmlfile = File.new("trial.xml")   
xmldoc = Document.new(xmlfile)   

# Now get the root element   
root = xmldoc.root   
puts "Root element : " + root.attributes["shelf"]   

# This will output all the cloth titles.   
xmldoc.elements.each("collection/clothing"){   
   |e| puts "cloth Title : " + e.attributes["title"]   
}   

# This will output all the cloth types.   
xmldoc.elements.each("collection/clothing/type") {   
   |e| puts "cloth Type : " + e.text   
}   

# This will output all the cloth description.   
xmldoc.elements.each("collection/clothing/description") {   
   |e| puts "cloth Description : " + e.text   
}

Ruby XML以SAX类似的解析

这里演示以流的方式解析XML数据。 将文件trial.xml代码作为输入。 在这里将定义一个侦听器类,其方法将被解析器的回调目标。

建议不要对小文件使用类似SAX的解析。

#!/usr/bin/ruby -w   

require 'rexml/document'   
require 'rexml/streamlistener'   
include REXML   

class MyListener   
  include REXML::StreamListener   
  def tag_start(*args)   
    puts "tag_start: #{args.map {|x| x.inspect}.join(', ')}"   
  end   

  def text(data)   
    return if data =~ /^\w*$/     # whitespace only   
    abbrev = data[0..40] + (data.length > 40 ? "..." : "")   
    puts "  text   :   #{abbrev.inspect}"   
  end   
end   

list = MyListener.new   
xmlfile = File.new("trial.xml")   
Document.parse_stream(xmlfile, list)

上一篇: Ruby多线程编程 下一篇: Ruby快速入门(30分钟)