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'

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

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату