Rails Builder - Быстрый способ создать XML

Эта статья покажет вам, как установить Builder и затем генерировать с его помощью XML-документы — без помощи «рельсов». Она, конечно, не может описать все возможности Builder — но тех, что она опишет, будет достаточно, чтобы вас заинтересовать во всей этой затее.

После появления Ruby on Rails интерес к языку программирования Ruby, похоже, не прекращет расти. «Рельсы» помогли широкому кругу пользователей увидеть в Ruby то, чем он на самом деле является: элегантный, простой в освоении и приятный в использовании язык, при всём этом пригодный даже для промышленных приложений. Ruby — ровесник Java; но только сейчас к Ruby, наконец, стали относиться с тем вниманием, которого он заслуживает.

Ruby, безусловно, привлёк и моё внимание! Теперь я всё чаще берусь за Ruby, а не за Java, потому что Ruby позволяет мне создавать код быстрее — меньше нажатий клавиш для выполнения той же работы. За последние месяцы мой компилятор Java покрылся слоем пыли. Продолжайте читать, и вы поймёте почему.

Всё дело в Builder. Это простой генератор XML, изначально созданный как часть проекта Ruby on Rails. Теперь это отдельная библиотека для Ruby, для установки просто выполните команду:

gem install builder

Продемонстрировать использование Ruby и Builder лучше всего на простом примере. Запустите из командной строки Интерактивный Ruby ( irb), выключив для наглядности стандартные приглашения:

irb --simple-prompt

Теперь напечатайте в irb выделенные жирным команды, чтобы сгенерировать наш первый XML-документ:

>>
require 'builder'
=> ...
>>
x = Builder::XmlMarkup.new(:target => $stdout, :indent => 1)
<inspect/>
=> #<IO:0x279e7e8>

Строка, начинающаяся с require, загружает (или пытается загрузить) библиотеку с названием builder. (Обычно библиотеку удаётся найти, и эта команда возвращает true.) Следующая строка создаёт объект x, вызывая метод new класса XmlMarkup. Аргумент :target => stdout указывает, что вывод должен записываться в стандартный вывод, а :indent => 1 — что отступы при выводе XML должны составлять один пробел.

Когда перед именем, таким как :target, ставится двоеточие, это имя является символом, а вернее, объектом класса Symbol. Такой символ обозначает имя объекта, тогда как без двоеточия он обозначал бы значение объекта.

Экземпляр (приёмник) x можно использовать для вызова других методов, например instruct!:

>>
x.instruct!
<?xml version="1.0" encoding="UTF-8"?>
=> #<IO:0x279e7e8>

Этот метод создаёт XML-объявление с несколькими псевдо-атрибутами по умолчанию. Восклицательный знак после имени метода обычно указывает, что метод изменит значение приёмника, либо вернёт nil, если изменения не будут произведены. Следующая строка создаст в XML комментарий:

>>
x.comment! "greetings"
<!-- greetings -->
=> #<IO:0x279e7e8>

Обратите внимание, что этот метод вставляет пробелы вокруг текста комментария.

Элемент XML можно создать следующим образом. Имя, указываемое за приёмником, используется как имя элемента, и регистр букв в нём важен.

>>
x.Hello "World!"
<Hello>World!</Hello>
=> #<IO:0x279e7e8>

А вот так можно создать у элемента Hello атрибут:

>>
x.Hello("World!", "type" => "global")
<Hello type="global">World!</Hello>
#<IO:0x279e7e8>

Первый аргумент задаёт содержимое элемента, а второй — создаёт у элемента атрибут type со значением global.

Последний из примеров работы с irb покажет вам, как создавать вложенные элементы. В этом примере элемент date содержит три дочерних элемента — year, month, и day. Эти дочерние элементы указываются внутри фигурных скобок ( {}).

>>
x.date {
?>
x.year "2006"
>>
x.month "01"
>>
x.day "01"
>>
}
<date>
 <year>2006>year>
 <month>01>month>
 <day>01>day>
<date>
=> #>IO:0x279e7e8>
>>

Эти примеры охватывают только самые примитивные из возможностей Builder по генерации XML. Дальнейшие примеры будут демонстрировать более сложные и интересные возможности Builder.

Нижеприведённая программа favs.rb создаёт ассоциативный массив (хэш) с именем favorites и затем, используя Builder, сохраняет его в виде XML.

#!/usr/bin/ruby

require 'builder'

favorites = {
  'candy' => 'Neccos', 'novel' => 'Empire of the Sun', 'holiday' => 'Easter'
}

xml = Builder::XmlMarkup.new( :target => $stdout, :indent => 2 )

xml.instruct! :xml, :version => "1.1", :encoding => "US-ASCII"

xml.favorites do
 favorites.each do | name, choice |
  xml.favorite( choice, :item => name )
 end
end

Чтобы запустить эту программу, выполните ruby favs.rb, либо просто favs. Вывод будет иметь следующий вид:

<?xml version="1.1" encoding="US-ASCII"?>
<favorites>
  <favorite item="candy">Neccos<favorite>
  <favorite item="holiday">Easter<favorite>
  <favorite item="novel">Empire of the Sun<favorite>
<favorites>

Первая строка кода указывает путь, по которому располагается интерпретатор Ruby: /usr/bin/ruby. Затем загружается библиотека Builder, и определяется хэш favorites, состоящий из трёх пар имя-значение. Создаётся xml — экземпляр класса Builder::XmlMarkup. Метод instruct! создаёт XML-объявление с указанными явно приёмником и псевдо-атрибутами. Хотя этот документ соответствует XML 1.0, я изменил псевдо-атрибут version на 1.1, чтобы показать вам, как это делается.

С объектом favorites выполняется блок команд (операторы do–end можно было бы заменить фигурными скобками). Для каждой пары имя-значение создаётся новый XML-элемент, причём имя пары используется как значение атрибута, а значение пары (считанное в аргумент choice) — как содержимое элемента. Легко догадаться, что использование Builder помогает удобно и быстро экспортировать в XML большое количество таких пар.
Создание XHTML-документа

Наконец, я затрону ещё несколько методов, позволяющих с помощью Builder сгенерировать соответствующий стандартам XHTML-документ. Вот программа xhtml.rb, которая это делает:

#!/usr/bin/ruby

require 'builder'

x = Builder::XmlMarkup.new(:target => $stdout, :indent => 1)

x.instruct!

x.declare! :DOCTYPE, :html, :PUBLIC, "-//W3C//DTD XHTML 1.0 Strict//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"

x.html( "xmlns" => "http://www.w3.org/1999/xhtml" ) {

 x.head {

  x.title "XHTML 1.0 example" 

  x.style( "type"=>text/css" ) { x.text! "h1 {font-family:tahoma,sans-serif;font-size:18pt;color:blue} body{font-family:georgia,serif}"

  }

 }

 x.body {

  x.h1 "Hello from Builder"

  x.p "A Ruby library that facilitates the programatic generation of XML."

  x.p { |y| y <<"Methods of interest from <code<Builder::XmlMarkup</code> }

  x.ul {
    x.li "cdata!"
    x.li "comment!"
    x.li "declare!"
    x.li "instruct!"
    x.li "new"
  }

  x.p{ |y| y << "Methods of interest from "; x.code "Builder::XmlBase"; y << ":" }

  x.ul {
    x.li "<<"
    x.li "new"
    x.li "text!"
  }

 }
}

Метод declare! создаёт объявление типа документа (DOCTYPE), соответствующее строгому варианту XHTML 1.0. При этом используются как символы, так и строки. Элемент style содержит атрибут type; затем используется метод text!, чтобы записать в этот элемент небольшую CSS-таблицу. Этот метод является альтернативой заданию всего содержимого элемента при его создании — так, как в этом примере:

x.style("h1 {font-family:tahoma,sans-serif;font-size:18pt;color:blue} body{font-
family:georgia,serif}"
, "type"=>"text/css" )

Наверное, самый интересный код здесь — две строки, создающие абзацы со смешанным содержимым, содержащим внутри себя текст и теги code. Обе эти строки используют в качестве аргумента блок |y|, к которому в дальнейшем дописывается текст при помощи метода <<. Первая из этих двух строк вставляет внутрь текста теги code; вторая — создаёт как часть содержимого элемента p элемент code. В последнем случае команды, задающие содержимое элемента, разделены точками с запятыми.

Builder — это один из самых лёгких в использовании инструментов для быстрого создания XML-документов на любом языке. Хотя я затронул лишь самые простые способы его использования, я надеюсь, что вас заинтересовал приведённый код, вы поняли его основные принципы, и уже готовы найти Builder собственное применение.

Вход для пользователей