Книга: Программирование на языке 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 ..."
- 15.1. Разбор XML и REXML
- 4.3 Потоковый редактор sed
- Разбор XPath-выражений
- 2.3. Разбор опций: getopt() и getopt_long()
- Кошачьи разборки
- 2.23. Разбор данных, разделенных запятыми
- Разбор
- 11.12. Синтаксический разбор XML с помощью NSXMLParser
- 1. Разборчивость
- Разбор полетов
- 28. Сценарное планирование — подробный разбор
- Приложение 1. Разбор задачи для собеседования с программистами