Template Toolkit(русская редакция) |
|
||
|
Работа с данными |
|
ОПИСАНИЕ |
[ Индекс ] [ Пособия ] [ Наверх ] |
Данное пособие является обзором возможностей Template Toolkit по чтению и записи файлов с данными, представленными в различных форматах и стилях. Пособие было написано Дэйвом Кроссом (Dave Cross) и впервые было опубликовано в качестве статьи на http://www.perl.com/ в 2001 году. |
Введение в Template Toolkit |
[ Индекс ] [ Пособия ] [ Наверх ] |
Существует ряд модулей Perl, которые повсеместно признаны "правильными" в определенных задачах. Если Вы обращаетесь к базе данных без использования DBI, тянете данные из Сети без использования одного из модулей LWP или парсите XML без использования XML::Parser или одного из его подклассов, вы рискуете стать изгоем в сообществе Perl. Я надеюсь, что 2000 год станет годом рождения еще одного такого ('must have') модуля - Template Toolkit. Я не одинок в этом убеждении, ведь не случайно Template Toolkit был признан 'лучшим новым модулем ('Best New Module') на прошедшей летом конференции по Perl (Perl Conference). Template Toolkit версии 2.0 (известный среди почитателей как TT2) был на днях включен в архив CPAN. Спроектировал и написал TT2 Энди Уардли (Andy Wardley <abw@wardley.org>). Модуль вырос из предыдущего модуля Энди по работе с шаблонами Text::Metatext, который по совету Фреда Брукса (Fred Brooks) был полностью переписан, и преследует цель стать наиболее полезной (или, по крайней мере, наиболее используемой) системой по работе с шаблонами для Perl. TT2 предоставляет возможность взять файл-полуфабрикат (шаблон) и внедрить в него переменные данные. Одно из очевидных применений - создание динамических веб-страниц и большую часть внимания TT2 получил именно благодаря этой возможности. В этой статье я надеюсь показать, что TT2 полезен не только в веб-приложениях. |
Использование Template Toolkit |
[ Индекс ] [ Пособия ] [ Наверх ] |
Давайте посмотрим как мы будем использовать TT2 для обработки простого файла с данными. TT2 - объектно-ориентированный модуль. После загрузки его с CPAN, и стандартной установки, использовать его в вашей программе настолько просто, насколько просто добавить в ваш код строки: use Template; my $tt = Template->new;
Конструктор,
Для обработки шаблона, вам нужно вызвать метод $tt->process('my_template', \%data) || die $tt->error;
Мы передаем
Что можно включать в my @teams = ({ name => 'Man Utd', played => 16, won => 12, drawn => 3, lost => 1 }, { name => 'Bradford', played => 16, won => 2, drawn => 5, lost => 9 }); my %data = ( name => 'English Premier League', season => '2000/01', teams => \@teams );
Мы создали три элемента с данными, к которым можно получить доступ из
шаблона: Ниже шаблон, который мы можем использовать для обработки этих данных. League Standings League Name: [% name %] Season: [% season %] Teams: [% FOREACH team = teams -%] [% team.name %] [% team.played -%] [% team.won %] [% team.drawn %] [% team.lost %] [% END %] Обработка этого шаблона с этими данными дает следующий результат: League Standings League Name: English Premier League Season: 2000/01 Teams: Man Utd 16 12 3 1 Bradford 16 2 5 9 Будем надеяться, что синтаксис шаблона прост для понимания. Сделаем несколько пояснений.
Вероятно первое и последнее замечания, являются наиболее важными. Первое делает акцент на разделение логики подготовки данных и логики представления. Людям, создающим шаблоны представления, нет необходимости знать Perl, им нужно знать только элементы данных передаваемых в шаблон.
Последнее замечание показывает способ, каким TT2 ограждает
дизайнера шаблона от внутренней реализации структуры данных.
Данные, передаваемые процессору шаблонов могут быть скалярами,
массивами, хэшами, объектами и даже функциями. Процессор
правильно проинтерпретирует ваши данные и "сделает правильный
выбор", чтобы возвратить корректное значение. В этом примере
каждая команда была хэшем, но более крупной системе команда
может быть объектом, в котором доступ к соответсвующим свойствам
будет осуществляться посредством методов Более сложный примерСтатистика английской футбольной лиги, как правило, представляется в более сложном формате, чем тот который мы использовали выше. Полный набор статистики содержит количество побед, поражений и ничьих команды, количество забитых и пропущенных мячей и набранных в итоге очков. Команды получают три очка в случае победы и одно очко за ничью. Если команды имеют одинаковое число очков, учитывается разница между забитыми и пропущенными мячами. Если и это не помогает, победы, ничьи и поражения, а также забитые и пропущенные мячи часто разделяются на домашние и выездные. Следовательно, если у вас есть данные со списками, в которых содержится имя команды вместе с количеством побед, ничьих и поражений, забитых и пропущенных мячей, разбитых на домашние и выездные (всего одинадцать элементов), вы можете все остальные элементы (разница мячей, набранные очки и даже место в лиге). Давайте рассмотрим такой файл, но ограничимся верхними тремя командами. Он будет выглядеть примерно так: Man Utd,7,1,0,26,4,5,2,1,15,6 Arsenal,7,1,0,17,4,2,3,3,7,9 Leicester,4,3,1,10,8,4,2,2,7,4 Простой скрипт, который разложит эти данные в массив хэшей будет выглядеть примерно так (для краткости я упростил названия колонок данных - w, d и l обозначают победы, ничьи и поражения соответственно, f и a - забитые и пропущенные мячи; префиксы h и a перед названиями колонок обозначают соответственно домашнюю и выездную статистику): my @cols = qw(name hw hd hl hf ha aw ad al af aa); my @teams; while (<>) { chomp; my %team; @team{@cols} = split /,/; push @teams, \%team; } Теперь мы можем снова пройти по списку команд и рассчитать все производные элементы: foreach (@teams) { $_->{w} = $_->{hw} + $_->{aw}; $_->{d} = $_->{hd} + $_->{ad}; $_->{l} = $_->{hl} + $_->{al}; $_->{pl} = $_->{w} + $_->{d} + $_->{l}; $_->{f} = $_->{hf} + $_->{af}; $_->{a} = $_->{ha} + $_->{aa}; $_->{gd} = $_->{f} - $_->{a}; $_->{pt} = (3 * $_->{w}) + $_->{d}; } И затем отсортировать список по убыванию: @teams = sort { $b->{pt} <=> $b->{pt} || $b->{gd} <=> $a->{gd} } @teams; И, наконец, добавим элемент, обозначающий место в лиге: $teams[$_]->{pos} = $_ + 1 foreach 0 .. $#teams; Загнав все данные во внутреннюю структуру данных мы можем сгенерировать результат с использованием выходного шаблона. Шаблон для CSV файла, содержащего данные с разделенной домашней и выездной статистикой, будет выглядеть следующим образом: [% FOREACH team = teams -%] [% team.pos %],[% team.name %],[% team.pl %],[% team.hw %], [%- team.hd %],[% team.hl %],[% team.hf %],[% team.ha %], [%- team.aw %],[% team.ad %],[% team.al %],[% team.af %], [%- team.aa %],[% team.gd %],[% team.pt %] [%- END %] После обработки процессором: $tt->process('split.tt', { teams => \@teams }, 'split.csv') || die $tt->error; мы получаем следующий вывод: 1,Man Utd,16,7,1,0,26,4,5,2,1,15,6,31,39 2,Arsenal,16,7,1,0,17,4,2,3,3,7,9,11,31 3,Leicester,16,4,3,1,10,8,4,2,2,7,4,5,29
Обратите внимание, мы использовали третий аргумент в вызове
Если бы нас не интересовало разделение на домашние и выездные игры, мы могли бы использовать более простой шаблон: [% FOREACH team = teams -%] [% team.pos %],[% team.name %],[% team.pl %],[% team.w %], [%- team.d %],[% team.l %],[% team.f %],[% team.a %], [%- team.aa %],[% team.gd %],[% team.pt %] [% END -%] А вывод выглядел бы следующим образом: 1,Man Utd,16,12,3,1,41,10,6,31,39 2,Arsenal,16,9,4,3,24,13,9,11,31 3,Leicester,16,8,5,3,17,12,4,5,29 |
Генерация XML |
[ Индекс ] [ Пособия ] [ Наверх ] |
Посмотрим теперь насколько мощен и гибок TT2, ведь вы, наверняка,
отметили, что весь этот вывод можно легко реализовать парой вызовов
use FootballLeague; use Template; my $league = FootballLeague->new(name => 'English Premier'); my $tt = Template->new; $tt->process('league_xml.tt', { league => $league }) || die $tt->error;
А шаблон <?xml version="1.0"?> <!DOCTYPE LEAGUE SYSTEM "league.dtd"> <league name="[% league.name %]" season="[% league.season %]"> [% FOREACH team = league.teams -%] <team name="[% team.name %]" pos="[% team.pos %]" played="[% team.pl %]" goal_diff="[% team.gd %]" points="[% team.pt %]"> <stats type="home" win="[% team.hw %]" draw="[%- team.hd %]" lose="[% team.hl %]" for="[% team.hf %]" against="[% team.ha %]" /> <stats type="away" win="[% team.aw %]" draw="[%- team.ad %]" lose="[% team.al %]" for="[% team.af %]" against="[% team.aa %]" /> </team> [% END -%] </league>
Обратите внимание, что поскольку мы передали методу |
Различные форматы |
[ Индекс ] [ Пособия ] [ Наверх ] |
В качестве последнего примера предположим, что нам нужно создать таблицы футбольной лиги в различных форматах. Возможно мы передаем эти данные различным людям и не все они могут использовать одинаковый формат. Одним пользователям нужны CSV файлы, а другим XML. Кому-то нужны данные с разбивкой на домашнюю и выездную статистику, а кому-то только итоговые цифры. В общем, нам понадобятся четыре различных шаблона, но хорошее обстоятельство заключается в том, что мы можем использовать один объект данных. Все что будет необходимо сделать скрипту, это установить какой шаблон нужно использовать и обработать его. use FootballLeague; use Template; my ($name, $type, $stats) = @_; my $league = FootballLeague->new(name => $name); my $tt = Template->new; $tt->process("league_${type}_$stats.tt", { league => $league } "league_$stats.$type") || die $tt->error; Например, вы можете вызвать скрипт следующим образом: league.pl 'English Premier' xml split
В результате будет обработан шаблон Это уже начинает прояснять истинную мощь Template Toolkit. Если позже мы захотим добавить другой формат - например, мы захотим создать HTML страницу с таблицей лиги и даже документ LaTeX - все что нам будет нужно сделать это создать подходящий шаблон и назвать его в соответствии с существующим соглашением об именах. Нам не нужно будет делать никаких изменений в коде. Надеюсь, теперь вы понимаете, почему для многих людей Template Toolkit так быстро становится существенной частью установки Perl. |
АВТОР |
[ Индекс ] [ Пособия ] [ Наверх ] |
Дэйв Кросс (Dave Cross <dave@dave.org.uk>) |
ВЕРСИЯ |
[ Индекс ] [ Пособия ] [ Наверх ] |
Template Toolkit версия 2.14, дата релиза - 4 октября 2004. |
АВТОРСКИЕ ПРАВА |
[ Индекс ] [ Пособия ] [ Наверх ] |
Copyright (C) 2001 Dave Cross <dave@dave.org.uk> Этот модуль является свободно-распространяемым программным обеспечением; вы можете распространять и/или модифицировать его на тех же условиях, что и Perl. |