Программирование на языке Ruby - [182]

Шрифт
Интервал

А теперь попробуем разобрать тот же самый файл в потоковом стиле (на практике это вряд ли понадобилось бы, потому что размер файла невелик). У этого подхода несколько вариантов, в листинге 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.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


Вот что он напечатает:

> ...

>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

Часто изменяющийся контент распространяется в Интернете с помощью синдицированных каналов, или просто каналов. Обычно данные описываются на некотором диалекте языка XML.

Наверное, из всех форматов подобного рода наиболее распространен формат RSS. Эта аббревиатура означает Rich Site Summary (обогащенная сводка сайта), хотя некоторые расшифровывают ее как RDF Site Summary, понимая под RDF Resource Description Format (формат описания ресурса).

В сети Web очень много временной или часто изменяемой информации: записи в блогах, статьи в онлайновых журналах и т.д. Канал представляет собой естественный способ распространения и синдицирования такого контента.

Еще одним популярным форматом является Atom; некоторые даже считают, что он превосходит RSS. Но вообще-то сейчас предпочитают говорить не «RSS-канал» или «Atom-канал», а просто «канал».

Мы вкратце рассмотрим обработку форматов RSS и Atom. В первом случае применяется стандартная библиотека Ruby, во втором — библиотека, еще не вошедшая в стандартный дистрибутив.

15.2.1. Стандартная библиотека rss

Формат RSS основан на XML, поэтому разбирать его можно как обычный XML-документ. Но, поскольку это все-таки специализированный вариант, для него имеет смысл разработать специальный анализатор. Кроме того, запутанность стандарта RSS уже стала притчей во языцех — некорректно написанные программы могут генерировать такие RSS-документы, которые будет очень трудно разобрать.

Ситуация осложняется еще и тем, что существуют несовместимые версии стандарта; чаще всего используются 0.9,1.0 и 2.0. В общем, подобно производству колбасы, RSS — такая вещь, в детали которой лучше не вникать.


Рекомендуем почитать
Графика DirectX в Delphi

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Вторая жизнь старых компьютеров

Сейчас во многих школах, институтах и других учебных заведениях можно встретить компьютеры старого парка, уже отслужившие свое как морально, так и физически. На таких компьютерах можно изучать разве что Dos, что далеко от реалий сегодняшнего дня. К тому же у большинства, как правило, жесткий диск уже в нерабочем состоянии. Но и выбросить жалко, а новых никто не дает. Различные спонсоры, меценаты, бывает, подарят компьютер (один) и радуются, как дети. Спасибо, конечно, большое, но проблемы, как вы понимаете, этот компьютер в общем не решает, даже наоборот, усугубляет, работать на старых уже как-то не хочется, теперь просто есть с чем сравнивать.


DirectX 8. Начинаем работу с DirectX Graphics

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Симуляция частичной специализации

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Обработка событий в С++

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.