X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FGitalist.git;a=blobdiff_plain;f=local-lib5%2Fman%2Fman3%2FTemplate%3A%3ATutorial%3A%3ADatafile.3pm;fp=local-lib5%2Fman%2Fman3%2FTemplate%3A%3ATutorial%3A%3ADatafile.3pm;h=363d037557208286756ce7f030fea03f50f69e21;hp=0000000000000000000000000000000000000000;hb=3fea05b9fbf95091f4522528b9980a33e0235603;hpb=af746827daa7a8feccee889e1d12ebc74cc9201e diff --git a/local-lib5/man/man3/Template::Tutorial::Datafile.3pm b/local-lib5/man/man3/Template::Tutorial::Datafile.3pm new file mode 100644 index 0000000..363d037 --- /dev/null +++ b/local-lib5/man/man3/Template::Tutorial::Datafile.3pm @@ -0,0 +1,586 @@ +.\" 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 . +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 +\& +\& +.Ve +.PP +.Vb 22 +\& +\& [% FOREACH team = league.teams \-%] +\& +\& +\& win="[% team.hw %]" +\& draw="[%\- team.hd %]" +\& lose="[% team.hl %]" +\& for="[% team.hf %]" +\& against="[% team.ha %]" /> +\& +\& win="[% team.aw %]" +\& draw="[%\- team.ad %]" +\& lose="[% team.al %]" +\& for="[% team.af %]" +\& against="[% team.aa %]" /> +\& +\& [% 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 +.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 +.PP +This module is free software; you can redistribute it and/or +modify it under the same terms as Perl itself.