Add built local::lib
[catagits/Gitalist.git] / local-lib5 / man / man3 / Template::Tutorial::Datafile.3pm
CommitLineData
3fea05b9 1.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.3
2.\"
3.\" Standard preamble:
4.\" ========================================================================
5.de Sh \" Subsection heading
6.br
7.if t .Sp
8.ne 5
9.PP
10\fB\\$1\fR
11.PP
12..
13.de Sp \" Vertical space (when we can't use .PP)
14.if t .sp .5v
15.if n .sp
16..
17.de Vb \" Begin verbatim text
18.ft CW
19.nf
20.ne \\$1
21..
22.de Ve \" End verbatim text
23.ft R
24.fi
25..
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<>.
32.tr \(*W-|\(bv\*(Tr
33.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
34.ie n \{\
35. ds -- \(*W-
36. ds PI pi
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
39. ds L" ""
40. ds R" ""
41. ds C` ""
42. ds C' ""
43'br\}
44.el\{\
45. ds -- \|\(em\|
46. ds PI \(*p
47. ds L" ``
48. ds R" ''
49'br\}
50.\"
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.
55.if \nF \{\
56. de IX
57. tm Index:\\$1\t\\n%\t"\\$2"
58..
59. nr % 0
60. rr F
61.\}
62.\"
63.\" For nroff, turn off justification. Always turn off hyphenation; it makes
64.\" way too many mistakes in technical documents.
65.hy 0
66.if n .na
67.\"
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
71.if n \{\
72. ds #H 0
73. ds #V .8m
74. ds #F .3m
75. ds #[ \f1
76. ds #] \fP
77.\}
78.if t \{\
79. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
80. ds #V .6m
81. ds #F 0
82. ds #[ \&
83. ds #] \&
84.\}
85. \" simple accents for nroff and troff
86.if n \{\
87. ds ' \&
88. ds ` \&
89. ds ^ \&
90. ds , \&
91. ds ~ ~
92. ds /
93.\}
94.if t \{\
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'
101.\}
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 \
117\{\
118. ds : e
119. ds 8 ss
120. ds o a
121. ds d- d\h'-1'\(ga
122. ds D- D\h'-1'\(hy
123. ds th \o'bp'
124. ds Th \o'LP'
125. ds ae ae
126. ds Ae AE
127.\}
128.rm #[ #] #H #V #F C
129.\" ========================================================================
130.\"
131.IX Title "Template::Tutorial::Datafile 3"
132.TH Template::Tutorial::Datafile 3 "2008-11-13" "perl v5.8.7" "User Contributed Perl Documentation"
133.SH "NAME"
134Template::Tutorial::Datafile \- Creating Data Output Files Using the Template Toolkit
135.SH "DESCRIPTION"
136.IX Header "DESCRIPTION"
137.SH "Introducing the Template Toolkit"
138.IX Header "Introducing the Template Toolkit"
139There are a number of Perl modules that are universally
140recognised as The Right Thing To Use for certain tasks. If you
141accessed a database without using \s-1DBI\s0, pulled data from the \s-1WWW\s0
142without using one of the \s-1LWP\s0 modules or parsed \s-1XML\s0 without using
143XML::Parser or one of its subclasses then you'd run the risk of
144being shunned by polite Perl society.
145.PP
146I believe that the year 2000 saw the emergence of another 'must
147have' Perl module \- the Template Toolkit. I don't think I'm
148alone in this belief as the Template Toolkit won the 'Best New
149Module' award at the Perl Conference last summer. Version 2.0 of
150the Template Toolkit (known as \s-1TT2\s0 to its friends) was recently
151released to the \s-1CPAN\s0.
152.PP
153\&\s-1TT2\s0 was designed and written by Andy Wardley <abw@wardley.org>.
154It was born out of Andy's previous templating module,
155Text::Metatext, in best Fred Brooks 'plan to throw one away'
156manner; and aims to be the most useful (or, at least, the most
157\&\fIused\fR) Perl templating system.
158.PP
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
161use of this is in the creation of dynamic web pages and this is
162where a lot of the attention that \s-1TT2\s0 has received has been
163focussed. In this article, I hope to demonstrate that \s-1TT2\s0 is
164just as useful in non-web applications.
165.SH "Using the Template Toolkit"
166.IX Header "Using the Template Toolkit"
167Let'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
170program is as easy as putting the lines
171.PP
172.Vb 2
173\& use Template;
174\& my $tt = Template\->new;
175.Ve
176.PP
177in your code. The constructor function, \f(CW\*(C`new\*(C'\fR, takes
178a number of optional parameters which are documented in the
179copious manual pages that come with the module, but for the
180purposes of this article we'll keep things as simple as
181possible.
182.PP
183To process the template, you would call the \f(CW\*(C`process\*(C'\fR method
184like this
185.PP
186.Vb 2
187\& $tt\->process('my_template', \e%data)
188\& || die $tt\->error;
189.Ve
190.PP
191We pass two parameters to \f(CW\*(C`process\*(C'\fR, the first is the name of
192the file containing the template to process (in this case,
193my_template) and the second is a reference to a hash which
194contains the data items that you want to use in the template. If
195processing the template gives any kind of error, the program
196will die with a (hopefully) useful error message.
197.PP
198So what kinds of things can go in \f(CW%data\fR? The answer is just
199about anything. Here's an example showing data about English
200Premier League football teams.
201.PP
202.Vb 10
203\& my @teams = ({ name => 'Man Utd',
204\& played => 16,
205\& won => 12,
206\& drawn => 3,
207\& lost => 1 },
208\& { name => 'Bradford',
209\& played => 16,
210\& won => 2,
211\& drawn => 5,
212\& lost => 9 });
213.Ve
214.PP
215.Vb 3
216\& my %data = ( name => 'English Premier League',
217\& season => '2000/01',
218\& teams => \e@teams );
219.Ve
220.PP
221This creates three data items which can be accessed within the
222template, 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.
224.PP
225Here is a template that we might use to process this data.
226.PP
227.Vb 1
228\& League Standings
229.Ve
230.PP
231.Vb 2
232\& League Name: [% name %]
233\& Season : [% season %]
234.Ve
235.PP
236.Vb 5
237\& Teams:
238\& [% FOREACH team = teams \-%]
239\& [% team.name %] [% team.played \-%]
240\& [% team.won %] [% team.drawn %] [% team.lost %]
241\& [% END %]
242.Ve
243.PP
244Running this template with this data gives us the following
245output
246.PP
247.Vb 1
248\& League Standings
249.Ve
250.PP
251.Vb 2
252\& League Name: English Premier League
253\& Season : 2000/01
254.Ve
255.PP
256.Vb 3
257\& Teams:
258\& Man Utd 16 12 3 1
259\& Bradford 16 2 5 9
260.Ve
261.PP
262Hopefully the syntax of the template is simple enough to
263follow. There are a few points to note.
264.IP "\(bu" 4
265Template processing directives are written using a simple
266language which is not Perl.
267.IP "\(bu" 4
268The keys of the \f(CW%data\fR have become the names of the data
269variables within the template.
270.IP "\(bu" 4
271Template processing directives are surrounded by \f(CW\*(C`[%\*(C'\fR and
272\&\f(CW\*(C`%]\*(C'\fR sequences.
273.IP "\(bu" 4
274If these tags are replaced with \f(CW\*(C`[%\-\*(C'\fR \f(CW\*(C`\-%]\*(C'\fR then the preceding
275or following linefeed is suppressed.
276.IP "\(bu" 4
277In the \f(CW\*(C`FOREACH\*(C'\fR loop, each element of the \f(CW\*(C`teams\*(C'\fR list was
278assigned, in turn, to the temporary variable \f(CW\*(C`team\*(C'\fR.
279.IP "\(bu" 4
280Each item assigned to the \f(CW\*(C`team\*(C'\fR variable is a Perl hash.
281Individual values within the hash are accessed using a dot notation.
282.PP
283It's probably the first and last of these points which are the
284most important. The first point emphasises the separation of the
285data acquisition logic from the presentation logic. The person
286creating the presentation template doesn't need to know Perl,
287they only need to know the data items which will be passed into
288the template.
289.PP
290The last point demonstrates the way that \s-1TT2\s0 protects the
291template designer from the implementation of the data structures.
292The data objects passed to the template processor can be scalars,
293arrays, hashes, objects or even subroutines. The template
294processor will just interpret your data correctly and Do The
295Right Thing to return the correct value to you. In this example
296each team was a hash, but in a larger system each team might be
297an object, in which case \f(CW\*(C`name\*(C'\fR, \f(CW\*(C`played\*(C'\fR, etc. would be accessor
298methods to the underlying object attributes. No changes would be
299required to the template as the template processor would realise
300that it needed to call methods rather than access hash values.
301.Sh "A more complex example"
302.IX Subsection "A more complex example"
303Stats about the English Football League are usually presented in
304a slightly more complex format than the one we used above. A
305full set of stats will show the number of games that a team has
306won, lost or drawn, the number of goals scored for and against
307the team and the number of points that the team therefore has.
308Teams gain three points for a win and one point for a draw. When
309teams have the same number of points they are separated by the
310goal difference, that is the number of goals the team has scored
311minus the number of team scored against them. To complicate
312things even further, the games won, drawn and lost and the goals
313for and against are often split between home and away games.
314.PP
315Therefore if you have a data source which lists the team name
316togther with the games won, drawn and lost and the goals for and
317against split into home and away (a total of eleven data items)
318you can calculate all of the other items (goal difference,
319points awarded and even position in the league). Let's take such
320a file, but we'll only look at the top three teams. It will look
321something like this:
322.PP
323.Vb 3
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
327.Ve
328.PP
329A simple script to read this data into an array of hashes will
330look something like this (I've simplified the names of the data
331columns \- w, d, and l are games won, drawn and lost and f and a
332are goals scored for and against; h and a at the front of a data
333item name indicates whether it's a home or away statistic):
334.PP
335.Vb 1
336\& my @cols = qw(name hw hd hl hf ha aw ad al af aa);
337.Ve
338.PP
339.Vb 3
340\& my @teams;
341\& while (<>) {
342\& chomp;
343.Ve
344.PP
345.Vb 1
346\& my %team;
347.Ve
348.PP
349.Vb 1
350\& @team{@cols} = split /,/;
351.Ve
352.PP
353.Vb 2
354\& push @teams, \e%team;
355\& }
356.Ve
357.PP
358We can then go thru the teams again and calculate all of the
359derived data items:
360.PP
361.Vb 4
362\& foreach (@teams) {
363\& $_\->{w} = $_\->{hw} + $_\->{aw};
364\& $_\->{d} = $_\->{hd} + $_\->{ad};
365\& $_\->{l} = $_\->{hl} + $_\->{al};
366.Ve
367.PP
368.Vb 1
369\& $_\->{pl} = $_\->{w} + $_\->{d} + $_\->{l};
370.Ve
371.PP
372.Vb 2
373\& $_\->{f} = $_\->{hf} + $_\->{af};
374\& $_\->{a} = $_\->{ha} + $_\->{aa};
375.Ve
376.PP
377.Vb 3
378\& $_\->{gd} = $_\->{f} \- $_\->{a};
379\& $_\->{pt} = (3 * $_\->{w}) + $_\->{d};
380\& }
381.Ve
382.PP
383And then produce a list sorted in descending order:
384.PP
385.Vb 3
386\& @teams = sort {
387\& $b\->{pt} <=> $b\->{pt} || $b\->{gd} <=> $a\->{gd}
388\& } @teams;
389.Ve
390.PP
391And finally add the league position data item:
392.PP
393.Vb 2
394\& $teams[$_]\->{pos} = $_ + 1
395\& foreach 0 .. $#teams;
396.Ve
397.PP
398Having pulled all of our data into an internal data structure
399we can start to produce output using out templates. A template
400to create a \s-1CSV\s0 file containing the data split between home and
401away stats would look like this:
402.PP
403.Vb 6
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 %]
409\& [%\- END %]
410.Ve
411.PP
412And processing it like this:
413.PP
414.Vb 2
415\& $tt\->process('split.tt', { teams => \e@teams }, 'split.csv')
416\& || die $tt\->error;
417.Ve
418.PP
419produces the following output:
420.PP
421.Vb 3
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
425.Ve
426.PP
427Notice that we've introduced the third parameter to \f(CW\*(C`process\*(C'\fR.
428If 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
430name 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
432hich is assumed to implement a \f(CW\*(C`print\*(C'\fR method.
433.PP
434If we weren't interested in the split between home and away games,
435then we could use a simpler template like this:
436.PP
437.Vb 5
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 %]
442\& [% END \-%]
443.Ve
444.PP
445Which would produce output like this:
446.PP
447.Vb 3
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
451.Ve
452.SH "Producing XML"
453.IX Header "Producing XML"
454This 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
456this output with a \f(CW\*(C`foreach\*(C'\fR loop and a couple of \f(CW\*(C`print\*(C'\fR
457statements in your code. This is, of course, true; but that's
458because I've chosen a deliberately simple example to explain the
459concepts. What if we wanted to produce an \s-1XML\s0 file containing the
460data? And what if (as I mentioned earlier) the league data was held
461in an object? The code would then look even easier as most of the code
462we've written earlier would be hidden away in \f(CW\*(C`FootballLeague.pm\*(C'\fR.
463.PP
464.Vb 2
465\& use FootballLeague;
466\& use Template;
467.Ve
468.PP
469.Vb 1
470\& my $league = FootballLeague\->new(name => 'English Premier');
471.Ve
472.PP
473.Vb 1
474\& my $tt = Template\->new;
475.Ve
476.PP
477.Vb 2
478\& $tt\->process('league_xml.tt', { league => $league })
479\& || die $tt\->error;
480.Ve
481.PP
482And the template in \f(CW\*(C`league_xml.tt\*(C'\fR would look something like this:
483.PP
484.Vb 2
485\& <?xml version="1.0"?>
486\& <!DOCTYPE LEAGUE SYSTEM "league.dtd">
487.Ve
488.PP
489.Vb 22
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 %]" />
509\& </team>
510\& [% END \-%]
511\& &/league>
512.Ve
513.PP
514Notice that as we've passed the whole object into \f(CW\*(C`process\*(C'\fR then
515we need to put an extra level of indirection on our template
516variables \- everything is now a component of the \f(CW\*(C`league\*(C'\fR variable.
517Other than that, everything in the template is very similar to what
518we've used before. Presumably now \f(CW\*(C`team.name\*(C'\fR calls an accessor
519function rather than carrying out a hash lookup, but all of this
520is transparent to our template designer.
521.SH "Multiple Formats"
522.IX Header "Multiple Formats"
523As a final example, let's suppose that we need to create output
524football league tables in a number of formats. Perhaps we are
525passing this data on to other people and they can't all use the
526same 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
528other just want the totals. In total, then, we'll need four
529different templates, but the good news is that they can use the
530same data object. All the script needs to do is to establish
531which template is required and process it.
532.PP
533.Vb 2
534\& use FootballLeague;
535\& use Template;
536.Ve
537.PP
538.Vb 1
539\& my ($name, $type, $stats) = @_;
540.Ve
541.PP
542.Vb 1
543\& my $league = FootballLeague\->new(name => $name);
544.Ve
545.PP
546.Vb 1
547\& my $tt = Template\->new;
548.Ve
549.PP
550.Vb 4
551\& $tt\->process("league_${type}_$stats.tt",
552\& { league => $league }
553\& "league_$stats.$type")
554\& || die $tt\->error;
555.Ve
556.PP
557For example, you can call this script as
558.PP
559.Vb 1
560\& league.pl 'English Premier' xml split
561.Ve
562.PP
563This will process a template called \f(CW\*(C`league_xml_split.tt\*(C'\fR
564and put the results in a file called \f(CW\*(C`league_split.xml\*(C'\fR.
565.PP
566This starts to show the true strength of the Template Toolkit.
567If we later wanted to add another file format \- perhaps we
568wanted to create a league table \s-1HTML\s0 page or even a LaTeX
569document \- then we would just need to create the appropriate
570template and name it according to our existing naming
571convention. We would need to make no changes to the code.
572.PP
573I hope you can now see why the Template Toolkit is fast becoming
574an essential part of many people's Perl installation.
575.SH "AUTHOR"
576.IX Header "AUTHOR"
577Dave Cross <dave@dave.org.uk>
578.SH "VERSION"
579.IX Header "VERSION"
580Template Toolkit version 2.19, released on 27 April 2007.
581.SH "COPYRIGHT"
582.IX Header "COPYRIGHT"
583Copyright (C) 2001 Dave Cross <dave@dave.org.uk>
584.PP
585This module is free software; you can redistribute it and/or
586modify it under the same terms as Perl itself.