Чтение онлайн

на главную - закладки

Жанры

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

15.1. Разбор XML и REXML

Язык XML (который внешне «похож» на HTML или SGML) стал популярен в 1990-х годах. Благодаря некоторым свойствам он действительно лучше таблицы с фиксированной шириной колонки. Например, он позволяет задавать имена полей, представлять иерархически организованные данные и, самое главное, хранить данные переменной длины.

Конечно, сорок лет назад XML был бы невозможен из-за ограничений на объем памяти. Но представим себе, что он появился бы тогда. Знаменитая проблема 2000 года, которой пресса уделяла так

много внимания в 1999 году (хотя проблема-то и яйца выеденного не стоила!) при наличии XML вообще не возникла бы. Ведь причина была в том, что в унаследованных системах данные хранились в формате с фиксированной длиной. Так что, несмотря на некоторые недостатки, у XML есть сферы применения. В Ruby для работы с XML чаще всего применяется библиотека REXML, написанная Шоном Расселом (Sean Russell). Начиная с 2002 года REXML (произносится «рекс-эм-эль») входит в стандартный дистрибутив Ruby.

Сразу отмечу, что REXML работает довольно медленно. Достаточно ли ее быстродействия для вашего конкретного приложения, решать вам. Не исключено, что со временем вам придется перейти на библиотеку libxml2 (которую мы здесь не рассматриваем). Она, конечно, работает очень быстро (поскольку написана на С), но, пожалуй, не так близка по духу к Ruby.

REXML — это процессор XML, написанный целиком на Ruby в полном соответствии со стандартом XML 1.0. Он не проверяет достоверность документа (соответствие схеме) и удовлетворяет всем тестам OASIS (Organization for the Advancement of Structured Information Standards - организация по внедрению стандартов структурирования информации) для таких процессоров.

Библиотека REXML предлагает несколько API. Сделано это, конечно, для того, чтобы обеспечить большую гибкость, а не внести путаницу. Два классических API — интерфейсы на базе DOM (объектной модели документа) и SAX (потоковый интерфейс). В первом случае весь документ считывается в память и хранится в древовидной форме. Во втором разбор осуществляется по мере чтения документа. Этот способ не требует загрузки документа в память и потому применяется, когда документ слишком велик, а память ограничена.

Во всех примерах мы будем использовать один и тот же XML-файл (см. листинг 15.1), представляющий часть описания личной библиотеки.

Листинг 15.1. Файл books.xml

<library shelf="Recent Acquisitions">

 <section name="Ruby">

<book isbn="0672328844">

<title>The Ruby Way</title>

<author>Hal Fulton</author>

<description>Second edition. The book you are now reading.

Ain't recursion grand? </description>

</book>

 </section>

 <section name="Space">

<book isbn="0684835509">

<title>The Case for Mars</title>

<author>Robert Zubrin</author>

<description>Pushing toward a second home for the human

race. </description>

</book>

<book isbn="074325631X">

<title>First Man: The Life of Neil A. Armstrong</title>

<author>James R. Hansen</author>

<description>Definitive biography of the first man on

the moon. </description>

</book>

 </section>

</library>

15.1.1.

Древовидное представление

Сначала покажем, как работать с ХМL-документом, представленным в виде дерева. Для начала затребуем библиотеку

rexml/document
; обычно для удобства мы включаем также директиву
include rexml
, чтобы импортировать все необходимое в пространство имен верхнего уровня. В листинге 15.2 продемонстрировано несколько полезных приемов.

Листинг 15.2. Разбор документа с применением DOM

require 'rexml/document'

include REXML

input = File.new("books.xml")

doc = Document.new(input)

root = doc.root

puts root.attributes["shelf"] # Недавние приобретения

doc.elements.each("library/section") { |e| puts e.attributes["name"] }

# Выводится:

# Ruby

# Space

doc.elements.each("*/section/book") { |e| puts e.attributes["isbn"] }

# Выводится:

# 0672328844

# 0321445619

# 0684835509

# 074325631X

sec2 = root.elements[2]

author = sec2.elements[1].elements["author"].text # Robert Zubrin

Обратите внимание: атрибуты представляются в виде хэша. Обращаться к элементам можно либо по пути, либо по номеру. В последнем случае учтите, что согласно спецификации XML индексация элементов начинается с 1, а не с 0, как в Ruby.

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

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

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

require 'rexml/document'

require 'rexml/streamlistener'

Поделиться:
Популярные книги

Последний Паладин. Том 10

Саваровский Роман
10. Путь Паладина
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Последний Паладин. Том 10

Ермак. Регент

Валериев Игорь
10. Ермак
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Ермак. Регент

Наша навсегда

Зайцева Мария
2. Наша
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Наша навсегда

Интриганка

Шелдон Сидни
Приключения:
исторические приключения
9.24
рейтинг книги
Интриганка

Магнат

Шимохин Дмитрий
4. Подкидыш
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Магнат

Законы Рода. Том 12

Мельник Андрей
12. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Законы Рода. Том 12

Особый агент

Кулаков Сергей Федорович
Спецназ. Группа Антитеррор
Детективы:
боевики
7.00
рейтинг книги
Особый агент

Как я строил магическую империю 7

Зубов Константин
7. Как я строил магическую империю
Фантастика:
попаданцы
постапокалипсис
аниме
фантастика: прочее
5.00
рейтинг книги
Как я строил магическую империю 7

Имя нам Легион. Том 18

Дорничев Дмитрий
18. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 18

Учитель из прошлого тысячелетия

Еслер Андрей
6. Соприкосновение миров
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Учитель из прошлого тысячелетия

Шайтан Иван 4

Тен Эдуард
4. Шайтан Иван
Фантастика:
попаданцы
альтернативная история
8.00
рейтинг книги
Шайтан Иван 4

Роза ветров

Кас Маркус
6. Артефактор
Фантастика:
городское фэнтези
аниме
фэнтези
5.00
рейтинг книги
Роза ветров

Как я строил магическую империю 13

Зубов Константин
13. Как я строил магическую империю
Фантастика:
постапокалипсис
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Как я строил магическую империю 13

Вечная Война. Книга II

Винокуров Юрий
2. Вечная война.
Фантастика:
юмористическая фантастика
космическая фантастика
8.37
рейтинг книги
Вечная Война. Книга II