实例解析Ruby程序中调用REXML来解析XML格式数据的用法
REXML是Ruby纯XML解析库,支持DOM风格树解析、SAX风格流解析及XPath查询。DOM方式通过attributes哈希和路径索引访问元素;SAX方式定义监听器回调处理标签和文本;XPath支持跨文档查询节点。示例展示了book.xml的各类操作。
说到 Ruby 里的 XML 解析库,REXML 绝对是个绕不开的名字。它由 Sean Russell 一手打造,纯 Ruby 实现,虽然市面上还有其他选择(比如 NQXML 也是纯 Ruby,而 XMLParser 则封装了 C 写的 Jade 库),但 REXML 始终是很多 Ruby 开发者的首选。Russell 自己就吐槽过:“我特别受不了那些令人抓狂的 API。Ja va 的 XML 解析器 API 基本都走 DOM 或 SAX 的路子,但设计得像从没用过自家 API 的理论家搞出来的……现有的 XML API 简直让人头大。明明 XML 本身就是个简单、优雅、功能强大的标记语言,结果被一堆臃肿、冗余的 API 裹成了粽子。连最基本的树操作都让我得翻 API 文档,完全不直观,每个操作都复杂得离谱。”虽然还没到他那份上,但不得不承认,很多 XML API 确实给开发者添了不少麻烦。

示例
看下面的 book.xml:
The Ruby Way Hal Fulton Second edition. The book you are now reading. Ain't recursion grand? The Case for Mars Robert Zubrin Pushing toward a second home for the human race. First Man: The Life of Neil A. Armstrong James R. Hansen Definitive biography of the first man on the moon.
1 Tree Parsing(也就是 DOM-like)
使用 DOM 风格前,得先 require 一下 rexml/document,顺便 include REXML:
require 'rexml/document'
include REXML
input = File.new("books.xml")
doc = Document.new(input)
root = doc.root
puts root.attributes["shelf"] # Recent Acquisitions
doc.elements.each("library/section") { |e| puts e.attributes["name"] }
# Output:
# Ruby
# Space
doc.elements.each("*/section/book") { |e| puts e.attributes["isbn"] }
# Output:
# 0672328844
# 0321445619
# 0684835509
# 074325631X
sec2 = root.elements[2]
author = sec2.elements[1].elements["author"].text # Robert Zubrin
需要留意的点是,XML 的属性及其值在 REXML 里以哈希(Hash)的形式存在,所以通过 attributes[] 就能直接拿到想要的属性值。元素本身也能用路径字符串或者序号来索引——这里有个坑:序号是从 1 开始计数的,不是 0。
2 Stream Parsing(也就是 SAX-like Parsing)
SAX 风格更轻量,设计思路是定义一个监听器(listener)类,在解析过程中通过回调拿到数据:
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
source = File.new "books.xml"
Document.parse_stream(source, list)
StreamListener 模块预先定义了几个空回调方法,你只要覆盖它们就能实现自定义逻辑。当解析器进入一个标签时,会调用 tag_start 方法;读取到文本数据时,则触发 text 方法。上面例子的输出大致是这样:
tag_start: "library", {"shelf"=>"Recent Acquisitions"}
tag_start: "section", {"name"=>"Ruby"}
tag_start: "book", {"isbn"=>"0672328844"}
tag_start: "title", {}
text : "The Ruby Way"
3 XPath
XPath 查询是 XML 操作的重头戏,REXML 通过 XPath 类原生支持,同样兼容 DOM 和 SAX 两种风格。还是拿之前的 books.xml 举例,用 XPath 可以这样玩:
book1 = XPath.first(doc, "//book") # Info for first book found
p book1
# Print out all titles
XPath.each(doc, "//title") { |e| puts e.text }
# Get an array of all of the "author" elements in the document.
names = XPath.match(doc, "//author").map {|x| x.text }
p names
输出类似下面这样:
... > The Ruby Way The Case for Mars First Man: The Life of Neil A. Armstrong ["Hal Fulton", "Robert Zubrin", "James R. Hansen"]
Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。
极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。
















