--- /dev/null
+.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.3
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sh \" Subsection heading
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings. \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote. | will give a
+.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to
+.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C'
+.\" expand to `' in nroff, nothing in troff, for use with C<>.
+.tr \(*W-|\(bv\*(Tr
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+. ds -- \(*W-
+. ds PI pi
+. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+. ds L" ""
+. ds R" ""
+. ds C` ""
+. ds C' ""
+'br\}
+.el\{\
+. ds -- \|\(em\|
+. ds PI \(*p
+. ds L" ``
+. ds R" ''
+'br\}
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
+.\" entries marked with X<> in POD. Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.if \nF \{\
+. de IX
+. tm Index:\\$1\t\\n%\t"\\$2"
+..
+. nr % 0
+. rr F
+.\}
+.\"
+.\" For nroff, turn off justification. Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.hy 0
+.if n .na
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear. Run. Save yourself. No user-serviceable parts.
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds /
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "Template::Tutorial::Datafile 3"
+.TH Template::Tutorial::Datafile 3 "2008-11-13" "perl v5.8.7" "User Contributed Perl Documentation"
+.SH "NAME"
+Template::Tutorial::Datafile \- Creating Data Output Files Using the Template Toolkit
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+.SH "Introducing the Template Toolkit"
+.IX Header "Introducing the Template Toolkit"
+There are a number of Perl modules that are universally
+recognised as The Right Thing To Use for certain tasks. If you
+accessed a database without using \s-1DBI\s0, pulled data from the \s-1WWW\s0
+without using one of the \s-1LWP\s0 modules or parsed \s-1XML\s0 without using
+XML::Parser or one of its subclasses then you'd run the risk of
+being shunned by polite Perl society.
+.PP
+I believe that the year 2000 saw the emergence of another 'must
+have' Perl module \- the Template Toolkit. I don't think I'm
+alone in this belief as the Template Toolkit won the 'Best New
+Module' award at the Perl Conference last summer. Version 2.0 of
+the Template Toolkit (known as \s-1TT2\s0 to its friends) was recently
+released to the \s-1CPAN\s0.
+.PP
+\&\s-1TT2\s0 was designed and written by Andy Wardley <abw@wardley.org>.
+It was born out of Andy's previous templating module,
+Text::Metatext, in best Fred Brooks 'plan to throw one away'
+manner; and aims to be the most useful (or, at least, the most
+\&\fIused\fR) Perl templating system.
+.PP
+\&\s-1TT2\s0 provides a way to take a file of fixed boilerplate text
+(the template) and embed variable data within it. One obvious
+use of this is in the creation of dynamic web pages and this is
+where a lot of the attention that \s-1TT2\s0 has received has been
+focussed. In this article, I hope to demonstrate that \s-1TT2\s0 is
+just as useful in non-web applications.
+.SH "Using the Template Toolkit"
+.IX Header "Using the Template Toolkit"
+Let's look at how we'd use \s-1TT2\s0 to process a simple data file.
+\&\s-1TT2\s0 is an object oriented Perl module. Having downloaded it from
+\&\s-1CPAN\s0 and installed it in the usual manner, using it in your
+program is as easy as putting the lines
+.PP
+.Vb 2
+\& use Template;
+\& my $tt = Template\->new;
+.Ve
+.PP
+in your code. The constructor function, \f(CW\*(C`new\*(C'\fR, takes
+a number of optional parameters which are documented in the
+copious manual pages that come with the module, but for the
+purposes of this article we'll keep things as simple as
+possible.
+.PP
+To process the template, you would call the \f(CW\*(C`process\*(C'\fR method
+like this
+.PP
+.Vb 2
+\& $tt\->process('my_template', \e%data)
+\& || die $tt\->error;
+.Ve
+.PP
+We pass two parameters to \f(CW\*(C`process\*(C'\fR, the first is the name of
+the file containing the template to process (in this case,
+my_template) and the second is a reference to a hash which
+contains the data items that you want to use in the template. If
+processing the template gives any kind of error, the program
+will die with a (hopefully) useful error message.
+.PP
+So what kinds of things can go in \f(CW%data\fR? The answer is just
+about anything. Here's an example showing data about English
+Premier League football teams.
+.PP
+.Vb 10
+\& my @teams = ({ name => 'Man Utd',
+\& played => 16,
+\& won => 12,
+\& drawn => 3,
+\& lost => 1 },
+\& { name => 'Bradford',
+\& played => 16,
+\& won => 2,
+\& drawn => 5,
+\& lost => 9 });
+.Ve
+.PP
+.Vb 3
+\& my %data = ( name => 'English Premier League',
+\& season => '2000/01',
+\& teams => \e@teams );
+.Ve
+.PP
+This creates three data items which can be accessed within the
+template, called \f(CW\*(C`name\*(C'\fR, \f(CW\*(C`season\*(C'\fR and \f(CW\*(C`teams\*(C'\fR. Notice that
+\&\f(CW\*(C`teams\*(C'\fR is a complex data structure.
+.PP
+Here is a template that we might use to process this data.
+.PP
+.Vb 1
+\& League Standings
+.Ve
+.PP
+.Vb 2
+\& League Name: [% name %]
+\& Season : [% season %]
+.Ve
+.PP
+.Vb 5
+\& Teams:
+\& [% FOREACH team = teams \-%]
+\& [% team.name %] [% team.played \-%]
+\& [% team.won %] [% team.drawn %] [% team.lost %]
+\& [% END %]
+.Ve
+.PP
+Running this template with this data gives us the following
+output
+.PP
+.Vb 1
+\& League Standings
+.Ve
+.PP
+.Vb 2
+\& League Name: English Premier League
+\& Season : 2000/01
+.Ve
+.PP
+.Vb 3
+\& Teams:
+\& Man Utd 16 12 3 1
+\& Bradford 16 2 5 9
+.Ve
+.PP
+Hopefully the syntax of the template is simple enough to
+follow. There are a few points to note.
+.IP "\(bu" 4
+Template processing directives are written using a simple
+language which is not Perl.
+.IP "\(bu" 4
+The keys of the \f(CW%data\fR have become the names of the data
+variables within the template.
+.IP "\(bu" 4
+Template processing directives are surrounded by \f(CW\*(C`[%\*(C'\fR and
+\&\f(CW\*(C`%]\*(C'\fR sequences.
+.IP "\(bu" 4
+If these tags are replaced with \f(CW\*(C`[%\-\*(C'\fR \f(CW\*(C`\-%]\*(C'\fR then the preceding
+or following linefeed is suppressed.
+.IP "\(bu" 4
+In the \f(CW\*(C`FOREACH\*(C'\fR loop, each element of the \f(CW\*(C`teams\*(C'\fR list was
+assigned, in turn, to the temporary variable \f(CW\*(C`team\*(C'\fR.
+.IP "\(bu" 4
+Each item assigned to the \f(CW\*(C`team\*(C'\fR variable is a Perl hash.
+Individual values within the hash are accessed using a dot notation.
+.PP
+It's probably the first and last of these points which are the
+most important. The first point emphasises the separation of the
+data acquisition logic from the presentation logic. The person
+creating the presentation template doesn't need to know Perl,
+they only need to know the data items which will be passed into
+the template.
+.PP
+The last point demonstrates the way that \s-1TT2\s0 protects the
+template designer from the implementation of the data structures.
+The data objects passed to the template processor can be scalars,
+arrays, hashes, objects or even subroutines. The template
+processor will just interpret your data correctly and Do The
+Right Thing to return the correct value to you. In this example
+each team was a hash, but in a larger system each team might be
+an object, in which case \f(CW\*(C`name\*(C'\fR, \f(CW\*(C`played\*(C'\fR, etc. would be accessor
+methods to the underlying object attributes. No changes would be
+required to the template as the template processor would realise
+that it needed to call methods rather than access hash values.
+.Sh "A more complex example"
+.IX Subsection "A more complex example"
+Stats about the English Football League are usually presented in
+a slightly more complex format than the one we used above. A
+full set of stats will show the number of games that a team has
+won, lost or drawn, the number of goals scored for and against
+the team and the number of points that the team therefore has.
+Teams gain three points for a win and one point for a draw. When
+teams have the same number of points they are separated by the
+goal difference, that is the number of goals the team has scored
+minus the number of team scored against them. To complicate
+things even further, the games won, drawn and lost and the goals
+for and against are often split between home and away games.
+.PP
+Therefore if you have a data source which lists the team name
+togther with the games won, drawn and lost and the goals for and
+against split into home and away (a total of eleven data items)
+you can calculate all of the other items (goal difference,
+points awarded and even position in the league). Let's take such
+a file, but we'll only look at the top three teams. It will look
+something like this:
+.PP
+.Vb 3
+\& 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
+.Ve
+.PP
+A simple script to read this data into an array of hashes will
+look something like this (I've simplified the names of the data
+columns \- w, d, and l are games won, drawn and lost and f and a
+are goals scored for and against; h and a at the front of a data
+item name indicates whether it's a home or away statistic):
+.PP
+.Vb 1
+\& my @cols = qw(name hw hd hl hf ha aw ad al af aa);
+.Ve
+.PP
+.Vb 3
+\& my @teams;
+\& while (<>) {
+\& chomp;
+.Ve
+.PP
+.Vb 1
+\& my %team;
+.Ve
+.PP
+.Vb 1
+\& @team{@cols} = split /,/;
+.Ve
+.PP
+.Vb 2
+\& push @teams, \e%team;
+\& }
+.Ve
+.PP
+We can then go thru the teams again and calculate all of the
+derived data items:
+.PP
+.Vb 4
+\& foreach (@teams) {
+\& $_\->{w} = $_\->{hw} + $_\->{aw};
+\& $_\->{d} = $_\->{hd} + $_\->{ad};
+\& $_\->{l} = $_\->{hl} + $_\->{al};
+.Ve
+.PP
+.Vb 1
+\& $_\->{pl} = $_\->{w} + $_\->{d} + $_\->{l};
+.Ve
+.PP
+.Vb 2
+\& $_\->{f} = $_\->{hf} + $_\->{af};
+\& $_\->{a} = $_\->{ha} + $_\->{aa};
+.Ve
+.PP
+.Vb 3
+\& $_\->{gd} = $_\->{f} \- $_\->{a};
+\& $_\->{pt} = (3 * $_\->{w}) + $_\->{d};
+\& }
+.Ve
+.PP
+And then produce a list sorted in descending order:
+.PP
+.Vb 3
+\& @teams = sort {
+\& $b\->{pt} <=> $b\->{pt} || $b\->{gd} <=> $a\->{gd}
+\& } @teams;
+.Ve
+.PP
+And finally add the league position data item:
+.PP
+.Vb 2
+\& $teams[$_]\->{pos} = $_ + 1
+\& foreach 0 .. $#teams;
+.Ve
+.PP
+Having pulled all of our data into an internal data structure
+we can start to produce output using out templates. A template
+to create a \s-1CSV\s0 file containing the data split between home and
+away stats would look like this:
+.PP
+.Vb 6
+\& [% 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 %]
+.Ve
+.PP
+And processing it like this:
+.PP
+.Vb 2
+\& $tt\->process('split.tt', { teams => \e@teams }, 'split.csv')
+\& || die $tt\->error;
+.Ve
+.PP
+produces the following output:
+.PP
+.Vb 3
+\& 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
+.Ve
+.PP
+Notice that we've introduced the third parameter to \f(CW\*(C`process\*(C'\fR.
+If this parameter is missing then the \s-1TT2\s0 sends its output to
+\&\f(CW\*(C`STDOUT\*(C'\fR. If this parameter is a scalar then it is taken as the
+name of a file to write the output to. This parameter can also be
+(amongst other things) a filehandle or a reference to an object w
+hich is assumed to implement a \f(CW\*(C`print\*(C'\fR method.
+.PP
+If we weren't interested in the split between home and away games,
+then we could use a simpler template like this:
+.PP
+.Vb 5
+\& [% 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 \-%]
+.Ve
+.PP
+Which would produce output like this:
+.PP
+.Vb 3
+\& 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
+.Ve
+.SH "Producing XML"
+.IX Header "Producing XML"
+This is starting to show some of the power and flexibility of
+\&\s-1TT2\s0, but you may be thinking that you could just as easily produce
+this output with a \f(CW\*(C`foreach\*(C'\fR loop and a couple of \f(CW\*(C`print\*(C'\fR
+statements in your code. This is, of course, true; but that's
+because I've chosen a deliberately simple example to explain the
+concepts. What if we wanted to produce an \s-1XML\s0 file containing the
+data? And what if (as I mentioned earlier) the league data was held
+in an object? The code would then look even easier as most of the code
+we've written earlier would be hidden away in \f(CW\*(C`FootballLeague.pm\*(C'\fR.
+.PP
+.Vb 2
+\& use FootballLeague;
+\& use Template;
+.Ve
+.PP
+.Vb 1
+\& my $league = FootballLeague\->new(name => 'English Premier');
+.Ve
+.PP
+.Vb 1
+\& my $tt = Template\->new;
+.Ve
+.PP
+.Vb 2
+\& $tt\->process('league_xml.tt', { league => $league })
+\& || die $tt\->error;
+.Ve
+.PP
+And the template in \f(CW\*(C`league_xml.tt\*(C'\fR would look something like this:
+.PP
+.Vb 2
+\& <?xml version="1.0"?>
+\& <!DOCTYPE LEAGUE SYSTEM "league.dtd">
+.Ve
+.PP
+.Vb 22
+\& <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>
+.Ve
+.PP
+Notice that as we've passed the whole object into \f(CW\*(C`process\*(C'\fR then
+we need to put an extra level of indirection on our template
+variables \- everything is now a component of the \f(CW\*(C`league\*(C'\fR variable.
+Other than that, everything in the template is very similar to what
+we've used before. Presumably now \f(CW\*(C`team.name\*(C'\fR calls an accessor
+function rather than carrying out a hash lookup, but all of this
+is transparent to our template designer.
+.SH "Multiple Formats"
+.IX Header "Multiple Formats"
+As a final example, let's suppose that we need to create output
+football league tables in a number of formats. Perhaps we are
+passing this data on to other people and they can't all use the
+same format. Some of our users need \s-1CSV\s0 files and others need
+\&\s-1XML\s0. Some require data split between home and away matches and
+other just want the totals. In total, then, we'll need four
+different templates, but the good news is that they can use the
+same data object. All the script needs to do is to establish
+which template is required and process it.
+.PP
+.Vb 2
+\& use FootballLeague;
+\& use Template;
+.Ve
+.PP
+.Vb 1
+\& my ($name, $type, $stats) = @_;
+.Ve
+.PP
+.Vb 1
+\& my $league = FootballLeague\->new(name => $name);
+.Ve
+.PP
+.Vb 1
+\& my $tt = Template\->new;
+.Ve
+.PP
+.Vb 4
+\& $tt\->process("league_${type}_$stats.tt",
+\& { league => $league }
+\& "league_$stats.$type")
+\& || die $tt\->error;
+.Ve
+.PP
+For example, you can call this script as
+.PP
+.Vb 1
+\& league.pl 'English Premier' xml split
+.Ve
+.PP
+This will process a template called \f(CW\*(C`league_xml_split.tt\*(C'\fR
+and put the results in a file called \f(CW\*(C`league_split.xml\*(C'\fR.
+.PP
+This starts to show the true strength of the Template Toolkit.
+If we later wanted to add another file format \- perhaps we
+wanted to create a league table \s-1HTML\s0 page or even a LaTeX
+document \- then we would just need to create the appropriate
+template and name it according to our existing naming
+convention. We would need to make no changes to the code.
+.PP
+I hope you can now see why the Template Toolkit is fast becoming
+an essential part of many people's Perl installation.
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+Dave Cross <dave@dave.org.uk>
+.SH "VERSION"
+.IX Header "VERSION"
+Template Toolkit version 2.19, released on 27 April 2007.
+.SH "COPYRIGHT"
+.IX Header "COPYRIGHT"
+Copyright (C) 2001 Dave Cross <dave@dave.org.uk>
+.PP
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.