首先,包含 Ruby 的 REXML 模块,该模块拥有解析 XML 文件的方法。
打开 shoppingcart.xml 文件并从该文件创建一个 Document 对象,该对象包含解析后的 XML 文件。
将文档的根分配给元素对象 root。这将指向 XML 文件中的 cart 标记。
每个元素对象拥有一个属性对象,该属性对象是元素属性的 hash 表,其中属性名称作为键名,属性值作为键值。这里,root.attributes['id'] 将提供 root 元素的 id 属性的值(本例中为 userid)。
下面,将 sumtotals 初始化为 0 并打印标头。
每个元素对象还有一个对象 elements,该对象拥有 each 和 [] 方法,以便访问子元素。这个对象遍历所有带有 item 名称(通过 XPath 表达式 //item 指定)的 root 元素的子元素。每个元素还有一个属性 text,该属性容纳元素的文本值。
下一步,获取 item 元素的 code 属性以及 price 和 qty 元素的文本值,然后计算项目合计(Total)。将详细信息打印到账单并将项目合计添加到采购总计(Sum total)。
最后,打印采购总计。
这个示例展示了使用 REXML 和 Ruby 解析 XML 文件有多么简单!同样,在运行中生成 XML 文件,添加和删除元素及它们的属性也很简单。
清单 11. 处理 XML 文件:生成 XML 文件
doc = Document.new
doc.add_element("cart1", {"id" => "user2"})
cart = doc.root.elements[1]
item = Element.new("item")
item.add_element("price")
item.elements["price"].text = "100"
item.add_element("qty")
item.elements["qty"].text = "4"
cart .elements << item
清单 11 中的代码通过创建一个 cart 元素、一个 item 元素和它的子元素来创建 XML 结构,然后使用值填充这些子元素并将它们添加到 Document 根。
类似地,要删除元素和属性,使用 Elements 对象的 delete_element 和 delete_attribute 方法。
以上示例中的方法称为树解析(tree parsing)。另一种 XML 文档解析方法称为流解析(stream parsing)。“流解析” 比 “树解析” 更快,可以用于要求快速解析的情况。“流解析” 是基于事件的,它使用监听器。当解析流遇到一个标记时,它将调用监听器并执行处理。
清单 12 展示了一个示例:
清单 12. 处理 XML 文件:流解析
require 'rexml/document'
require 'rexml/streamlistener'
include REXML
class Listener
include StreamListener
def tag_start(name, attributes)
puts "Start #{name}"
end
def tag_end(name)
puts "End #{name}"
end
end
listener = Listener.new
parser = Parsers::StreamParser.new(File.new("shoppingcart.xml"), listener)
parser.parse
清单 13 显示输出:
清单 13. 处理 XML 文件:流解析输出
Start cart Start item Start price End price Start qty End qty End item Start item Start price End price Start qty End qty End item Start item Start price End price Start qty End qty End item Start item Start price End price Start qty End qty End item End cart










