Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / i486-linux-gnu-thread-multi / Template / Tutorial / Datafile.pod
1 #============================================================= -*-perl-*-
2 #
3 # Template::Tutorial::Datafile
4 #
5 # DESCRIPTION
6
7 #
8 # AUTHOR
9 #   Dave Cross  <dave@dave.org.uk>
10 #
11 # COPYRIGHT
12 #   Copyright (C) 1996-2008 Andy Wardley.  All Rights Reserved.
13 #
14 #   This module is free software; you can redistribute it and/or
15 #   modify it under the same terms as Perl itself.
16 #
17 #========================================================================
18
19 =head1 NAME
20
21 Template::Tutorial::Datafile - Creating Data Output Files Using the Template Toolkit
22
23 =head1 DESCRIPTION
24
25
26
27 =head1 Introducing the Template Toolkit
28
29 There are a number of Perl modules that are universally 
30 recognised as The Right Thing To Use for certain tasks. If you 
31 accessed a database without using DBI, pulled data from the WWW 
32 without using one of the LWP modules or parsed XML without using 
33 XML::Parser or one of its subclasses then you'd run the risk of 
34 being shunned by polite Perl society.
35
36 I believe that the year 2000 saw the emergence of another 'must 
37 have' Perl module - the Template Toolkit. I don't think I'm 
38 alone in this belief as the Template Toolkit won the 'Best New 
39 Module' award at the Perl Conference last summer. Version 2.0 of 
40 the Template Toolkit (known as TT2 to its friends) was recently 
41 released to the CPAN.
42
43 TT2 was designed and written by Andy Wardley E<lt>abw@wardley.orgE<gt>. 
44 It was born out of Andy's previous templating module, 
45 Text::Metatext, in best Fred Brooks 'plan to throw one away' 
46 manner; and aims to be the most useful (or, at least, the most 
47 I<used>) Perl templating system.
48
49 TT2 provides a way to take a file of fixed boilerplate text 
50 (the template) and embed variable data within it. One obvious 
51 use of this is in the creation of dynamic web pages and this is 
52 where a lot of the attention that TT2 has received has been 
53 focussed. In this article, I hope to demonstrate that TT2 is 
54 just as useful in non-web applications.
55
56 =head1 Using the Template Toolkit
57
58 Let's look at how we'd use TT2 to process a simple data file. 
59 TT2 is an object oriented Perl module. Having downloaded it from 
60 CPAN and installed it in the usual manner, using it in your 
61 program is as easy as putting the lines
62
63     use Template;
64     my $tt = Template->new;
65
66 in your code. The constructor function, C<new>, takes 
67 a number of optional parameters which are documented in the 
68 copious manual pages that come with the module, but for the 
69 purposes of this article we'll keep things as simple as 
70 possible.
71
72 To process the template, you would call the C<process> method 
73 like this
74
75     $tt->process('my_template', \%data)
76         || die $tt->error;
77
78 We pass two parameters to C<process>, the first is the name of 
79 the file containing the template to process (in this case, 
80 my_template) and the second is a reference to a hash which 
81 contains the data items that you want to use in the template. If 
82 processing the template gives  any kind of error, the program 
83 will die with a (hopefully) useful error message.
84
85 So what kinds of things can go in C<%data>? The answer is just 
86 about anything. Here's an example showing data about English 
87 Premier League football teams.
88
89     my @teams = ({ name   => 'Man Utd',
90                    played => 16,
91                    won    => 12,
92                    drawn  => 3,
93                    lost   => 1 },
94                  { name   => 'Bradford',
95                    played => 16,
96                    won    => 2,
97                    drawn  => 5,
98                    lost   => 9 });
99
100     my %data = ( name   => 'English Premier League',
101                  season => '2000/01',
102                  teams  => \@teams );
103
104 This creates three data items which can be accessed within the 
105 template, called C<name>, C<season> and C<teams>. Notice that 
106 C<teams> is a complex data structure.
107
108 Here is a template that we might use to process this data.
109
110     League Standings
111
112     League Name: [% name %]
113     Season     : [% season %]
114
115     Teams:
116     [% FOREACH team = teams -%]
117     [% team.name %] [% team.played -%] 
118      [% team.won %] [% team.drawn %] [% team.lost %]
119     [% END %]
120
121 Running this template with this data gives us the following 
122 output
123
124                 League Standings
125
126     League Name: English Premier League
127     Season     : 2000/01
128
129     Teams:
130     Man Utd 16 12 3 1
131     Bradford 16 2 5 9
132
133 Hopefully the syntax of the template is simple enough to 
134 follow. There are a few points to note.
135
136 =over 4
137
138 =item *
139
140 Template processing directives are written using a simple 
141 language which is not Perl.
142
143 =item *
144
145 The keys of the C<%data> have become the names of the data 
146 variables within the template.
147
148 =item *
149
150 Template processing directives are surrounded by C<[%> and 
151 C<%]> sequences.
152
153 =item *
154
155 If these tags are replaced with C<[%-> C<-%]> then the preceding 
156 or following linefeed is suppressed.
157
158 =item *
159
160 In the C<FOREACH> loop, each element of the C<teams> list was 
161 assigned, in turn, to the temporary variable C<team>.
162
163 =item *
164
165 Each item assigned to the C<team> variable is a Perl hash. 
166 Individual values within the hash are accessed using a dot notation.
167
168 =back
169
170 It's probably the first and last of these points which are the 
171 most important. The first point emphasises the separation of the 
172 data acquisition logic from the presentation logic. The person 
173 creating the presentation template doesn't need to know Perl, 
174 they only need to know the data items which will be passed into
175 the template.
176
177 The last point demonstrates the way that TT2 protects the 
178 template designer from the implementation of the data structures.
179 The data objects passed to the template processor can be scalars,
180 arrays, hashes, objects or even subroutines. The template 
181 processor will just interpret your data correctly and Do The 
182 Right Thing to return the correct value to you. In this example 
183 each team was a hash, but in a larger system each team might be 
184 an object, in which case C<name>, C<played>, etc. would be accessor 
185 methods to the underlying object attributes. No changes would be 
186 required to the template as the template processor would realise 
187 that it needed to call methods rather than access hash values.
188
189 =head2 A more complex example
190
191 Stats about the English Football League are usually presented in
192 a slightly more complex format than the one we used above. A 
193 full set of stats will show the number of games that a team has 
194 won, lost or drawn, the number of goals scored for and against 
195 the team and the number of points that the team therefore has.
196 Teams gain three points for a win and one point for a draw. When
197 teams have the same number of points they are separated by the 
198 goal difference, that is the number of goals the team has scored
199 minus the number of team scored against them. To complicate 
200 things even further, the games won, drawn and lost and the goals 
201 for and against are often split between home and away games.
202
203 Therefore if you have a data source which lists the team name 
204 togther with the games won, drawn and lost and the goals for and 
205 against split into home and away (a total of eleven data items) 
206 you can calculate all of the other items (goal difference, 
207 points awarded and even position in the league). Let's take such 
208 a file, but we'll only look at the top three teams. It will look 
209 something like this:
210
211     Man Utd,7,1,0,26,4,5,2,1,15,6
212     Arsenal,7,1,0,17,4,2,3,3,7,9
213     Leicester,4,3,1,10,8,4,2,2,7,4
214
215 A simple script to read this data into an array of hashes will 
216 look something like this (I've simplified the names of the data 
217 columns - w, d, and l are games won, drawn and lost and f and a 
218 are goals scored for and against; h and a at the front of a data 
219 item name indicates whether it's a home or away statistic):
220
221     my @cols = qw(name hw hd hl hf ha aw ad al af aa);
222
223     my @teams;
224     while (<>) {
225         chomp;
226
227         my %team;
228
229         @team{@cols} = split /,/;
230
231         push @teams, \%team;
232     }
233
234 We can then go thru the teams again and calculate all of the 
235 derived data items:
236
237     foreach (@teams) {
238         $_->{w} = $_->{hw} + $_->{aw};
239         $_->{d} = $_->{hd} + $_->{ad};
240         $_->{l} = $_->{hl} + $_->{al};
241
242         $_->{pl} = $_->{w} + $_->{d} + $_->{l};
243
244         $_->{f} = $_->{hf} + $_->{af};
245         $_->{a} = $_->{ha} + $_->{aa};
246
247         $_->{gd} = $_->{f} - $_->{a};
248         $_->{pt} = (3 * $_->{w}) + $_->{d};
249     }
250
251 And then produce a list sorted in descending order:
252
253     @teams = sort { 
254         $b->{pt} <=> $b->{pt} || $b->{gd} <=> $a->{gd} 
255     } @teams;
256
257 And finally add the league position data item:
258
259     $teams[$_]->{pos} = $_ + 1 
260         foreach 0 .. $#teams;
261
262 Having pulled all of our data into an internal data structure 
263 we can start to produce output using out templates. A template 
264 to create a CSV file containing the data split between home and 
265 away stats would look like this:
266
267     [% FOREACH team = teams -%]
268     [% team.pos %],[% team.name %],[% team.pl %],[% team.hw %],
269     [%- team.hd %],[% team.hl %],[% team.hf %],[% team.ha %],
270     [%- team.aw %],[% team.ad %],[% team.al %],[% team.af %],
271     [%- team.aa %],[% team.gd %],[% team.pt %]
272     [%- END %]
273
274 And processing it like this:
275
276     $tt->process('split.tt', { teams => \@teams }, 'split.csv')
277       || die $tt->error;
278
279 produces the following output:
280
281     1,Man Utd,16,7,1,0,26,4,5,2,1,15,6,31,39
282     2,Arsenal,16,7,1,0,17,4,2,3,3,7,9,11,31
283     3,Leicester,16,4,3,1,10,8,4,2,2,7,4,5,29
284
285 Notice that we've introduced the third parameter to C<process>. 
286 If this parameter is missing then the TT2 sends its output to 
287 C<STDOUT>. If this parameter is a scalar then it is taken as the 
288 name of a file to write the output to. This parameter can also be 
289 (amongst other things) a filehandle or a reference to an object w
290 hich is assumed to implement a C<print> method.
291
292 If we weren't interested in the split between home and away games, 
293 then we could use a simpler template like this:
294
295     [% FOREACH team = teams -%]
296     [% team.pos %],[% team.name %],[% team.pl %],[% team.w %],
297     [%- team.d %],[% team.l %],[% team.f %],[% team.a %],
298     [%- team.aa %],[% team.gd %],[% team.pt %]
299     [% END -%]
300
301 Which would produce output like this:
302
303     1,Man Utd,16,12,3,1,41,10,6,31,39
304     2,Arsenal,16,9,4,3,24,13,9,11,31
305     3,Leicester,16,8,5,3,17,12,4,5,29
306
307 =head1 Producing XML
308
309 This is starting to show some of the power and flexibility of 
310 TT2, but you may be thinking that you could just as easily produce 
311 this output with a C<foreach> loop and a couple of C<print> 
312 statements in your code. This is, of course, true; but that's 
313 because I've chosen a deliberately simple example to explain the 
314 concepts. What if we wanted to produce an XML file containing the 
315 data? And what if (as I mentioned earlier) the league data was held 
316 in an object? The code would then look even easier as most of the code 
317 we've written earlier would be hidden away in C<FootballLeague.pm>.
318
319     use FootballLeague;
320     use Template;
321
322     my $league = FootballLeague->new(name => 'English Premier');
323
324     my $tt = Template->new;
325
326     $tt->process('league_xml.tt', { league => $league })
327         || die $tt->error;
328
329 And the template in C<league_xml.tt> would look something like this:
330
331     <?xml version="1.0"?>
332     <!DOCTYPE LEAGUE SYSTEM "league.dtd">
333
334     <league name="[% league.name %]" season="[% league.season %]">
335     [% FOREACH team = league.teams -%]
336       <team name="[% team.name %]"
337             pos="[% team.pos %]"
338             played="[% team.pl %]"
339             goal_diff="[% team.gd %]"
340             points="[% team.pt %]">
341          <stats type="home">
342                 win="[% team.hw %]"
343                 draw="[%- team.hd %]"
344                 lose="[% team.hl %]"
345                 for="[% team.hf %]"
346                 against="[% team.ha %]" />
347          <stats type="away">
348                 win="[% team.aw %]"
349                 draw="[%- team.ad %]"
350                 lose="[% team.al %]"
351                 for="[% team.af %]"
352                 against="[% team.aa %]" />
353       </team>
354     [% END -%]
355     &/league>
356
357 Notice that as we've passed the whole object into C<process> then 
358 we need to put an extra level of indirection on our template 
359 variables - everything is now a component of the C<league> variable. 
360 Other than that, everything in the template is very similar to what 
361 we've used before. Presumably now C<team.name> calls an accessor 
362 function rather than carrying out a hash lookup, but all of this 
363 is transparent to our template designer.
364
365 =head1 Multiple Formats
366
367 As a final example, let's suppose that we need to create output
368 football league tables in a number of formats. Perhaps we are 
369 passing this data on to other people and they can't all use the 
370 same format. Some of our users need CSV files and others need 
371 XML. Some require data split between home and away matches and 
372 other just want the totals. In total, then, we'll need four 
373 different templates, but the good news is that they can use the 
374 same data object. All the script needs to do is to establish 
375 which template is required and process it.
376
377     use FootballLeague;
378     use Template;
379
380     my ($name, $type, $stats) = @_;
381
382     my $league = FootballLeague->new(name => $name);
383
384     my $tt = Template->new;
385
386     $tt->process("league_${type}_$stats.tt", 
387                  { league => $league }
388                  "league_$stats.$type")
389         || die $tt->error;
390
391 For example, you can call this script as
392
393     league.pl 'English Premier' xml split
394
395 This will process a template called C<league_xml_split.tt> 
396 and put the results in a file called C<league_split.xml>.
397
398 This starts to show the true strength of the Template Toolkit. 
399 If we later wanted to add another file format - perhaps we 
400 wanted to create a league table HTML page or even a LaTeX 
401 document - then we would just need to create the appropriate 
402 template and name it according to our existing naming 
403 convention. We would need to make no changes to the code.
404
405 I hope you can now see why the Template Toolkit is fast becoming
406 an essential part of many people's Perl installation.
407
408 =head1 AUTHOR
409
410 Dave Cross E<lt>dave@dave.org.ukE<gt>
411
412
413
414
415 =head1 VERSION
416
417 Template Toolkit version 2.19, released on 27 April 2007.
418
419 =head1 COPYRIGHT
420
421
422 Copyright (C) 2001 Dave Cross E<lt>dave@dave.org.ukE<gt>
423
424 This module is free software; you can redistribute it and/or
425 modify it under the same terms as Perl itself.
426
427
428
429 =cut
430
431 # Local Variables:
432 # mode: perl
433 # perl-indent-level: 4
434 # indent-tabs-mode: nil
435 # End:
436 #
437 # vim: expandtab shiftwidth=4: