1 .\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.3
4 .\" ========================================================================
5 .de Sh \" Subsection heading
13 .de Sp \" Vertical space (when we can't use .PP)
17 .de Vb \" Begin verbatim text
22 .de Ve \" End verbatim text
26 .\" Set up some character translations and predefined strings. \*(-- will
27 .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
28 .\" double quote, and \*(R" will give a right double quote. | will give a
29 .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to
30 .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C'
31 .\" expand to `' in nroff, nothing in troff, for use with C<>.
33 .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
37 . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
38 . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
51 .\" If the F register is turned on, we'll generate index entries on stderr for
52 .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
53 .\" entries marked with X<> in POD. Of course, you'll have to process the
54 .\" output yourself in some meaningful fashion.
57 . tm Index:\\$1\t\\n%\t"\\$2"
63 .\" For nroff, turn off justification. Always turn off hyphenation; it makes
64 .\" way too many mistakes in technical documents.
68 .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
69 .\" Fear. Run. Save yourself. No user-serviceable parts.
70 . \" fudge factors for nroff and troff
79 . ds #H ((1u-(\\\\n(.fu%2u))*.13m)
85 . \" simple accents for nroff and troff
95 . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
96 . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
97 . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
98 . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
99 . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
100 . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
102 . \" troff and (daisy-wheel) nroff accents
103 .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
104 .ds 8 \h'\*(#H'\(*b\h'-\*(#H'
105 .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
106 .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
107 .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
108 .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
109 .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
110 .ds ae a\h'-(\w'a'u*4/10)'e
111 .ds Ae A\h'-(\w'A'u*4/10)'E
112 . \" corrections for vroff
113 .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
114 .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
115 . \" for low resolution devices (crt and lpr)
116 .if \n(.H>23 .if \n(.V>19 \
129 .\" ========================================================================
131 .IX Title "Template::Tutorial::Datafile 3"
132 .TH Template::Tutorial::Datafile 3 "2008-11-13" "perl v5.8.7" "User Contributed Perl Documentation"
134 Template::Tutorial::Datafile \- Creating Data Output Files Using the Template Toolkit
136 .IX Header "DESCRIPTION"
137 .SH "Introducing the Template Toolkit"
138 .IX Header "Introducing the Template Toolkit"
139 There are a number of Perl modules that are universally
140 recognised as The Right Thing To Use for certain tasks. If you
141 accessed a database without using \s-1DBI\s0, pulled data from the \s-1WWW\s0
142 without using one of the \s-1LWP\s0 modules or parsed \s-1XML\s0 without using
143 XML::Parser or one of its subclasses then you'd run the risk of
144 being shunned by polite Perl society.
146 I believe that the year 2000 saw the emergence of another 'must
147 have' Perl module \- the Template Toolkit. I don't think I'm
148 alone in this belief as the Template Toolkit won the 'Best New
149 Module' award at the Perl Conference last summer. Version 2.0 of
150 the Template Toolkit (known as \s-1TT2\s0 to its friends) was recently
151 released to the \s-1CPAN\s0.
153 \&\s-1TT2\s0 was designed and written by Andy Wardley <abw@wardley.org>.
154 It was born out of Andy's previous templating module,
155 Text::Metatext, in best Fred Brooks 'plan to throw one away'
156 manner; and aims to be the most useful (or, at least, the most
157 \&\fIused\fR) Perl templating system.
159 \&\s-1TT2\s0 provides a way to take a file of fixed boilerplate text
160 (the template) and embed variable data within it. One obvious
161 use of this is in the creation of dynamic web pages and this is
162 where a lot of the attention that \s-1TT2\s0 has received has been
163 focussed. In this article, I hope to demonstrate that \s-1TT2\s0 is
164 just as useful in non-web applications.
165 .SH "Using the Template Toolkit"
166 .IX Header "Using the Template Toolkit"
167 Let's look at how we'd use \s-1TT2\s0 to process a simple data file.
168 \&\s-1TT2\s0 is an object oriented Perl module. Having downloaded it from
169 \&\s-1CPAN\s0 and installed it in the usual manner, using it in your
170 program is as easy as putting the lines
174 \& my $tt = Template\->new;
177 in your code. The constructor function, \f(CW\*(C`new\*(C'\fR, takes
178 a number of optional parameters which are documented in the
179 copious manual pages that come with the module, but for the
180 purposes of this article we'll keep things as simple as
183 To process the template, you would call the \f(CW\*(C`process\*(C'\fR method
187 \& $tt\->process('my_template', \e%data)
188 \& || die $tt\->error;
191 We pass two parameters to \f(CW\*(C`process\*(C'\fR, the first is the name of
192 the file containing the template to process (in this case,
193 my_template) and the second is a reference to a hash which
194 contains the data items that you want to use in the template. If
195 processing the template gives any kind of error, the program
196 will die with a (hopefully) useful error message.
198 So what kinds of things can go in \f(CW%data\fR? The answer is just
199 about anything. Here's an example showing data about English
200 Premier League football teams.
203 \& my @teams = ({ name => 'Man Utd',
208 \& { name => 'Bradford',
216 \& my %data = ( name => 'English Premier League',
217 \& season => '2000/01',
218 \& teams => \e@teams );
221 This creates three data items which can be accessed within the
222 template, called \f(CW\*(C`name\*(C'\fR, \f(CW\*(C`season\*(C'\fR and \f(CW\*(C`teams\*(C'\fR. Notice that
223 \&\f(CW\*(C`teams\*(C'\fR is a complex data structure.
225 Here is a template that we might use to process this data.
232 \& League Name: [% name %]
233 \& Season : [% season %]
238 \& [% FOREACH team = teams \-%]
239 \& [% team.name %] [% team.played \-%]
240 \& [% team.won %] [% team.drawn %] [% team.lost %]
244 Running this template with this data gives us the following
252 \& League Name: English Premier League
262 Hopefully the syntax of the template is simple enough to
263 follow. There are a few points to note.
265 Template processing directives are written using a simple
266 language which is not Perl.
268 The keys of the \f(CW%data\fR have become the names of the data
269 variables within the template.
271 Template processing directives are surrounded by \f(CW\*(C`[%\*(C'\fR and
272 \&\f(CW\*(C`%]\*(C'\fR sequences.
274 If these tags are replaced with \f(CW\*(C`[%\-\*(C'\fR \f(CW\*(C`\-%]\*(C'\fR then the preceding
275 or following linefeed is suppressed.
277 In the \f(CW\*(C`FOREACH\*(C'\fR loop, each element of the \f(CW\*(C`teams\*(C'\fR list was
278 assigned, in turn, to the temporary variable \f(CW\*(C`team\*(C'\fR.
280 Each item assigned to the \f(CW\*(C`team\*(C'\fR variable is a Perl hash.
281 Individual values within the hash are accessed using a dot notation.
283 It's probably the first and last of these points which are the
284 most important. The first point emphasises the separation of the
285 data acquisition logic from the presentation logic. The person
286 creating the presentation template doesn't need to know Perl,
287 they only need to know the data items which will be passed into
290 The last point demonstrates the way that \s-1TT2\s0 protects the
291 template designer from the implementation of the data structures.
292 The data objects passed to the template processor can be scalars,
293 arrays, hashes, objects or even subroutines. The template
294 processor will just interpret your data correctly and Do The
295 Right Thing to return the correct value to you. In this example
296 each team was a hash, but in a larger system each team might be
297 an object, in which case \f(CW\*(C`name\*(C'\fR, \f(CW\*(C`played\*(C'\fR, etc. would be accessor
298 methods to the underlying object attributes. No changes would be
299 required to the template as the template processor would realise
300 that it needed to call methods rather than access hash values.
301 .Sh "A more complex example"
302 .IX Subsection "A more complex example"
303 Stats about the English Football League are usually presented in
304 a slightly more complex format than the one we used above. A
305 full set of stats will show the number of games that a team has
306 won, lost or drawn, the number of goals scored for and against
307 the team and the number of points that the team therefore has.
308 Teams gain three points for a win and one point for a draw. When
309 teams have the same number of points they are separated by the
310 goal difference, that is the number of goals the team has scored
311 minus the number of team scored against them. To complicate
312 things even further, the games won, drawn and lost and the goals
313 for and against are often split between home and away games.
315 Therefore if you have a data source which lists the team name
316 togther with the games won, drawn and lost and the goals for and
317 against split into home and away (a total of eleven data items)
318 you can calculate all of the other items (goal difference,
319 points awarded and even position in the league). Let's take such
320 a file, but we'll only look at the top three teams. It will look
324 \& Man Utd,7,1,0,26,4,5,2,1,15,6
325 \& Arsenal,7,1,0,17,4,2,3,3,7,9
326 \& Leicester,4,3,1,10,8,4,2,2,7,4
329 A simple script to read this data into an array of hashes will
330 look something like this (I've simplified the names of the data
331 columns \- w, d, and l are games won, drawn and lost and f and a
332 are goals scored for and against; h and a at the front of a data
333 item name indicates whether it's a home or away statistic):
336 \& my @cols = qw(name hw hd hl hf ha aw ad al af aa);
350 \& @team{@cols} = split /,/;
354 \& push @teams, \e%team;
358 We can then go thru the teams again and calculate all of the
362 \& foreach (@teams) {
363 \& $_\->{w} = $_\->{hw} + $_\->{aw};
364 \& $_\->{d} = $_\->{hd} + $_\->{ad};
365 \& $_\->{l} = $_\->{hl} + $_\->{al};
369 \& $_\->{pl} = $_\->{w} + $_\->{d} + $_\->{l};
373 \& $_\->{f} = $_\->{hf} + $_\->{af};
374 \& $_\->{a} = $_\->{ha} + $_\->{aa};
378 \& $_\->{gd} = $_\->{f} \- $_\->{a};
379 \& $_\->{pt} = (3 * $_\->{w}) + $_\->{d};
383 And then produce a list sorted in descending order:
387 \& $b\->{pt} <=> $b\->{pt} || $b\->{gd} <=> $a\->{gd}
391 And finally add the league position data item:
394 \& $teams[$_]\->{pos} = $_ + 1
395 \& foreach 0 .. $#teams;
398 Having pulled all of our data into an internal data structure
399 we can start to produce output using out templates. A template
400 to create a \s-1CSV\s0 file containing the data split between home and
401 away stats would look like this:
404 \& [% FOREACH team = teams \-%]
405 \& [% team.pos %],[% team.name %],[% team.pl %],[% team.hw %],
406 \& [%\- team.hd %],[% team.hl %],[% team.hf %],[% team.ha %],
407 \& [%\- team.aw %],[% team.ad %],[% team.al %],[% team.af %],
408 \& [%\- team.aa %],[% team.gd %],[% team.pt %]
412 And processing it like this:
415 \& $tt\->process('split.tt', { teams => \e@teams }, 'split.csv')
416 \& || die $tt\->error;
419 produces the following output:
422 \& 1,Man Utd,16,7,1,0,26,4,5,2,1,15,6,31,39
423 \& 2,Arsenal,16,7,1,0,17,4,2,3,3,7,9,11,31
424 \& 3,Leicester,16,4,3,1,10,8,4,2,2,7,4,5,29
427 Notice that we've introduced the third parameter to \f(CW\*(C`process\*(C'\fR.
428 If this parameter is missing then the \s-1TT2\s0 sends its output to
429 \&\f(CW\*(C`STDOUT\*(C'\fR. If this parameter is a scalar then it is taken as the
430 name of a file to write the output to. This parameter can also be
431 (amongst other things) a filehandle or a reference to an object w
432 hich is assumed to implement a \f(CW\*(C`print\*(C'\fR method.
434 If we weren't interested in the split between home and away games,
435 then we could use a simpler template like this:
438 \& [% FOREACH team = teams \-%]
439 \& [% team.pos %],[% team.name %],[% team.pl %],[% team.w %],
440 \& [%\- team.d %],[% team.l %],[% team.f %],[% team.a %],
441 \& [%\- team.aa %],[% team.gd %],[% team.pt %]
445 Which would produce output like this:
448 \& 1,Man Utd,16,12,3,1,41,10,6,31,39
449 \& 2,Arsenal,16,9,4,3,24,13,9,11,31
450 \& 3,Leicester,16,8,5,3,17,12,4,5,29
453 .IX Header "Producing XML"
454 This is starting to show some of the power and flexibility of
455 \&\s-1TT2\s0, but you may be thinking that you could just as easily produce
456 this output with a \f(CW\*(C`foreach\*(C'\fR loop and a couple of \f(CW\*(C`print\*(C'\fR
457 statements in your code. This is, of course, true; but that's
458 because I've chosen a deliberately simple example to explain the
459 concepts. What if we wanted to produce an \s-1XML\s0 file containing the
460 data? And what if (as I mentioned earlier) the league data was held
461 in an object? The code would then look even easier as most of the code
462 we've written earlier would be hidden away in \f(CW\*(C`FootballLeague.pm\*(C'\fR.
465 \& use FootballLeague;
470 \& my $league = FootballLeague\->new(name => 'English Premier');
474 \& my $tt = Template\->new;
478 \& $tt\->process('league_xml.tt', { league => $league })
479 \& || die $tt\->error;
482 And the template in \f(CW\*(C`league_xml.tt\*(C'\fR would look something like this:
485 \& <?xml version="1.0"?>
486 \& <!DOCTYPE LEAGUE SYSTEM "league.dtd">
490 \& <league name="[% league.name %]" season="[% league.season %]">
491 \& [% FOREACH team = league.teams \-%]
492 \& <team name="[% team.name %]"
493 \& pos="[% team.pos %]"
494 \& played="[% team.pl %]"
495 \& goal_diff="[% team.gd %]"
496 \& points="[% team.pt %]">
497 \& <stats type="home">
498 \& win="[% team.hw %]"
499 \& draw="[%\- team.hd %]"
500 \& lose="[% team.hl %]"
501 \& for="[% team.hf %]"
502 \& against="[% team.ha %]" />
503 \& <stats type="away">
504 \& win="[% team.aw %]"
505 \& draw="[%\- team.ad %]"
506 \& lose="[% team.al %]"
507 \& for="[% team.af %]"
508 \& against="[% team.aa %]" />
514 Notice that as we've passed the whole object into \f(CW\*(C`process\*(C'\fR then
515 we need to put an extra level of indirection on our template
516 variables \- everything is now a component of the \f(CW\*(C`league\*(C'\fR variable.
517 Other than that, everything in the template is very similar to what
518 we've used before. Presumably now \f(CW\*(C`team.name\*(C'\fR calls an accessor
519 function rather than carrying out a hash lookup, but all of this
520 is transparent to our template designer.
521 .SH "Multiple Formats"
522 .IX Header "Multiple Formats"
523 As a final example, let's suppose that we need to create output
524 football league tables in a number of formats. Perhaps we are
525 passing this data on to other people and they can't all use the
526 same format. Some of our users need \s-1CSV\s0 files and others need
527 \&\s-1XML\s0. Some require data split between home and away matches and
528 other just want the totals. In total, then, we'll need four
529 different templates, but the good news is that they can use the
530 same data object. All the script needs to do is to establish
531 which template is required and process it.
534 \& use FootballLeague;
539 \& my ($name, $type, $stats) = @_;
543 \& my $league = FootballLeague\->new(name => $name);
547 \& my $tt = Template\->new;
551 \& $tt\->process("league_${type}_$stats.tt",
552 \& { league => $league }
553 \& "league_$stats.$type")
554 \& || die $tt\->error;
557 For example, you can call this script as
560 \& league.pl 'English Premier' xml split
563 This will process a template called \f(CW\*(C`league_xml_split.tt\*(C'\fR
564 and put the results in a file called \f(CW\*(C`league_split.xml\*(C'\fR.
566 This starts to show the true strength of the Template Toolkit.
567 If we later wanted to add another file format \- perhaps we
568 wanted to create a league table \s-1HTML\s0 page or even a LaTeX
569 document \- then we would just need to create the appropriate
570 template and name it according to our existing naming
571 convention. We would need to make no changes to the code.
573 I hope you can now see why the Template Toolkit is fast becoming
574 an essential part of many people's Perl installation.
577 Dave Cross <dave@dave.org.uk>
580 Template Toolkit version 2.19, released on 27 April 2007.
582 .IX Header "COPYRIGHT"
583 Copyright (C) 2001 Dave Cross <dave@dave.org.uk>
585 This module is free software; you can redistribute it and/or
586 modify it under the same terms as Perl itself.