发布于 2015-07-11 02:53:03 | 206 次阅读 | 评论: 0 | 来源: 网络整理
可扩展标记语言(XML)是一种标记语言,就像HTML或SGML。由万维网联盟推荐使用,可作为一个开放的标准。
XML是一种便携式,开源语言,它允许程序员开发应用程序,可以由其他应用程序读取,而不管操作系统和/或语言发展。
XML是非常有用的跟踪小到中量的数据,而不需要一个SQL为基础框架。
有两种不同风格的XML解析器:
SAX-like (Stream interfaces) : 在这里,有用的事件注册回调让解析器通过文件进行。当文件比较大或者有内存限制,这是非常有用的,它解析的文件,它从磁盘读取,整个文件是永远不会存储在内存中。
DOM-like (Object tree interfaces) : 这是万维网协会建议,其中将整个文件读入内存,并存储在一个层次(树)的形式来表示XML文档的所有功能。
在处理大型文件时SAX显然没有 DOM 那样快, 另一方面,使用DOM独占太多资源,特别是用了很多小文件。
SAX是只读的,而DOM允许更改的XML文件。由于这两个不同的API从字面上互相补充没有任何理由不能使用这两个在大型项目中。
最常见的用来操作XML方式是由肖恩·罗素REXML库。 2002年以来,REXML一直是Ruby标准的一部分。
REXML是一个纯Ruby的XML处理器符合XML 1.0标准。这是一个验证处理器,通过所有的OASIS非验证一致性测试。
REXML解析器超过其他可用的解析器具有以下优点:
100% 是Ruby语言编写实现
它可以被用来SAX和DOM解析
它是轻量级的,一共不到2000行代码
是很容易理解的方法和类
基于SAX2 API和完整的XPath支持
对于我们所有的XML代码的例子,让我们用一个简单的XML文件作为输入:
<collection shelf="New Arrivals">
<movie title="Enemy Behind">
<type>War, Thriller</type>
<format>DVD</format>
<year>2003</year>
<rating>PG</rating>
<stars>10</stars>
<description>Talk about a US-Japan war</description>
</movie>
<movie title="Transformers">
<type>Anime, Science Fiction</type>
<format>DVD</format>
<year>1989</year>
<rating>R</rating>
<stars>8</stars>
<description>A schientific fiction</description>
</movie>
<movie title="Trigun">
<type>Anime, Action</type>
<format>DVD</format>
<episodes>4</episodes>
<rating>PG</rating>
<stars>10</stars>
<description>Vash the Stampede!</description>
</movie>
<movie title="Ishtar">
<type>Comedy</type>
<format>VHS</format>
<rating>PG</rating>
<stars>2</stars>
<description>Viewable boredom</description>
</movie>
</collection>
让我们先来解析XML数据树的形式。首先,我们需要 rexml/document; 为方便起见,我们经常做导入到顶层的命名空间,包含REXML。
#!/usr/bin/ruby -w
require 'rexml/document'
include REXML
xmlfile = File.new("movies.xml")
xmldoc = Document.new(xmlfile)
# Now get the root element
root = xmldoc.root
puts "Root element : " + root.attributes["shelf"]
# This will output all the movie titles.
xmldoc.elements.each("collection/movie"){
|e| puts "Movie Title : " + e.attributes["title"]
}
# This will output all the movie types.
xmldoc.elements.each("collection/movie/type") {
|e| puts "Movie Type : " + e.text
}
# This will output all the movie description.
xmldoc.elements.each("collection/movie/description") {
|e| puts "Movie Description : " + e.text
}
这将产生以下结果:
Root element : New Arrivals
Movie Title : Enemy Behind
Movie Title : Transformers
Movie Title : Trigun
Movie Title : Ishtar
Movie Type : War, Thriller
Movie Type : Anime, Science Fiction
Movie Type : Anime, Action
Movie Type : Comedy
Movie Description : Talk about a US-Japan war
Movie Description : A schientific fiction
Movie Description : Vash the Stampede!
Movie Description : Viewable boredom
要处理相同的数据:movies.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("movies.xml")
Document.parse_stream(xmlfile, list)
这将产生以下结果:
tag_start: "collection", {"shelf"=>"New Arrivals"}
tag_start: "movie", {"title"=>"Enemy Behind"}
tag_start: "type", {}
text : "War, Thriller"
tag_start: "format", {}
tag_start: "year", {}
tag_start: "rating", {}
tag_start: "stars", {}
tag_start: "description", {}
text : "Talk about a US-Japan war"
tag_start: "movie", {"title"=>"Transformers"}
tag_start: "type", {}
text : "Anime, Science Fiction"
tag_start: "format", {}
tag_start: "year", {}
tag_start: "rating", {}
tag_start: "stars", {}
tag_start: "description", {}
text : "A schientific fiction"
tag_start: "movie", {"title"=>"Trigun"}
tag_start: "type", {}
text : "Anime, Action"
tag_start: "format", {}
tag_start: "episodes", {}
tag_start: "rating", {}
tag_start: "stars", {}
tag_start: "description", {}
text : "Vash the Stampede!"
tag_start: "movie", {"title"=>"Ishtar"}
tag_start: "type", {}
tag_start: "format", {}
tag_start: "rating", {}
tag_start: "stars", {}
tag_start: "description", {}
text : "Viewable boredom"
查看XML的另一种方法是XPath。这是一种伪语言,介绍了如何找到特定的XML文档中的元素和属性,把该文件作为一个逻辑有序树。
REXML XPath支持通过XPath类。正如我们已经看到的,它假定基于树的解析(文档对象模型)。
#!/usr/bin/ruby -w
require 'rexml/document'
include REXML
xmlfile = File.new("movies.xml")
xmldoc = Document.new(xmlfile)
# Info for the first movie found
movie = XPath.first(xmldoc, "//movie")
p movie
# Print out all the movie types
XPath.each(xmldoc, "//type") { |e| puts e.text }
# Get an array of all of the movie formats.
names = XPath.match(xmldoc, "//format").map {|x| x.text }
p names
这将产生以下结果:
<movie title='Enemy Behind'> ... </>
War, Thriller
Anime, Science Fiction
Anime, Action
Comedy
["DVD", "DVD", "DVD", "VHS"]
有两个XSLT解析器Ruby可以使用。每个在这里给出一个简短的描述:
这个解析器由 Masayoshi Takahashi 编写和维护。这主要是写Linux操作系统,需要以下库:
Sablot
Iconv
Expat
可以找到这个模块 Ruby-Sablotron.
XSLT4R由迈克尔·诺伊曼(Michael Neumann)开发维护,可以发现了RAA的库部分在XML。 XSLT4R使用一个简单的命令行界面,虽然它也可以被用来在第三方应用程序来转换XML文档。
XSLT4R需要操作XMLScan的,它是包含内XSLT4R归档文件,这也是一个100%的Ruby模块。这些模块可以安装使用标准的Ruby安装方法(即Ruby的install.rb)。
XSLT4R的语法如下:
ruby xslt.rb stylesheet.xsl document.xml [arguments]
如果想使用XSLT4R从应用程序中可以包括XSLT和输入所需的参数。下面的例子:
require "xslt"
stylesheet = File.readlines("stylesheet.xsl").to_s
xml_doc = File.readlines("document.xml").to_s
arguments = { 'image_dir' => '/....' }
sheet = XSLT::Stylesheet.new( stylesheet, arguments )
# output to StdOut
sheet.apply( xml_doc )
# output to 'str'
str = ""
sheet.output = [ str ]
sheet.apply( xml_doc )
REXML分析器对于一个完整的细节,请参考标准文档 REXML Parser Documentation.
可以下载XSLT4R RAA Repository.