Книга: Программирование на языке Ruby

15.1.2. Потоковый разбор

15.1.2. Потоковый разбор

А теперь попробуем разобрать тот же самый файл в потоковом стиле (на практике это вряд ли понадобилось бы, потому что размер файла невелик). У этого подхода несколько вариантов, в листинге 15.3 показан один из них. Идея в том, чтобы определить класс слушателя, методы которого анализатор будет вызывать для обработки событий.

Листинг 15.3. SAX-разбор

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*$/ # Ничего, кроме пропусков.
  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_open. Можете считать это чем-то вроде метода method_missing, которому в качестве параметра передается имя тега (и все его атрибуты в форме хэша). Аналогично работает метод text; о других методах вы можете прочитать в документации на сайте http://ruby-doc.org или в каком-нибудь другом месте.

Программа в листинге 15.3 протоколирует обнаружение каждого открывающего и каждого закрывающего тега. Результат работы показан в листинге 15.4 (для краткости текст приведен не полностью).

Листинг 15.4. Результат работы программы потокового разбора

tag_start: "library", {"shelf"=>"Recent Acquisitions"}
tag_start: "section", {"name"=>"Ruby"}
tag_start: "book", {"isbn"=>"0672328844"}
tag_start: "title", {}
  text   :  "The Ruby Way"
tag_start: "author", {}
  text   :  "Hal Fulton"
tag_start: "description", {}
  text   :  "Second edition. The book you are now read..."
tag_start: "section", {"name"=>"Space"}
tag_start: "book", {"isbn"=>"0684835509"}
tag_start: "title", {}
  text   :  "The Case for Mars"
tag_start: "author", {}
  text   :  "Robert Zubrin"
tag_start: "description", {}
  text   :  "Pushing toward a second home for the huma..."
tag_start: "book", {"isbn"=>"074325631X"}
tag_start: "title", {}
  text   :  "First Man: The Life of Neil A. Armstrong"
tag_start: "author", {}
  text   : "James R. Hansen"
tag_start: "description", {}
  text   : "Definitive biography of the first man on ..."

Оглавление книги


Генерация: 1.555. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз