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 (для краткости текст приведен не полностью).
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.3. XPath и другие интерфейсы
Альтернативным способом работы с ХМL-документом является язык XPath, с помощью которого описывается, как обратиться к конкретным элементам и атрибутам XML-документа.
Библиотека REXML поддерживает XPath с помощью класса XPath. Предполагается, что документ представлен в виде DOM (см. выше листинг 15.2). Рассмотрим следующий код:
# (Этап подготовки опущен.)
book1 = XPath.first(doc, '//book') # Найдена информация о первой книге
р book1
# Распечатать названия всех книг.
XPath.each(doc, '//title') { |e| puts e.text }
# Получить массив всех элементов 'author'.
names = XPath.match(doc, '//author').map {|x| x.text }
p names
Вот что он напечатает:
<book isbn='0672328844'> ... </>
The Ruby Way
The Case for Mars
First Man: The Life of Neil A. Armstrong
['Hal Fulton', 'Robert Zubrin', 'James R. Hansen']
REXML поддерживает также API на основе стандарта SAX2 (с некоторыми добавлениями в духе Ruby) и экспериментальный анализатор на основе технологии «вытягивания». Они в этой книге не рассматриваются - можете обратиться к сайту http://ruby-doc.org или аналогичному ресурсу.
15.2. RSS и Atom
Часто изменяющийся контент распространяется в Интернете с помощью
Наверное, из всех форматов подобного рода наиболее распространен формат
В сети Web очень много временной или часто изменяемой информации: записи в блогах, статьи в онлайновых журналах и т.д. Канал представляет собой естественный способ распространения и синдицирования такого контента.
Еще одним популярным форматом является
Мы вкратце рассмотрим обработку форматов RSS и Atom. В первом случае применяется стандартная библиотека Ruby, во втором — библиотека, еще не вошедшая в стандартный дистрибутив.
15.2.1. Стандартная библиотека rss
Формат RSS основан на XML, поэтому разбирать его можно как обычный XML-документ. Но, поскольку это все-таки специализированный вариант, для него имеет смысл разработать специальный анализатор. Кроме того, запутанность стандарта RSS уже стала притчей во языцех — некорректно написанные программы могут генерировать такие RSS-документы, которые будет очень трудно разобрать.
Ситуация осложняется еще и тем, что существуют несовместимые версии стандарта; чаще всего