NAME

dTemplate - A powerful template handling logic with advanced features.

SYNOPSIS

use dTemplate;

$mail_template = define dTemplate "mail_tmpl.txt";# definition

$mail = $mail_template->parse(                    # parsing
  TO      => "foo@bar.com",
  SUBJECT => $subject,
  BODY    => 
    sub { $email_type==3 ? $body_for_type_3 : $body_for_others },
  SIGNATURE=> $signature_template->parse( KEY => "value" )
);

print "Please send this mail: $mail";

where mail_tmpl.txt is:

  From    : Me
  To      : $TO$
  Subject : $SUBJECT$

  Message body:
  $BODY$

  $SIGNATURE$

# Advanced feature: Styling

$style={lang =>'hungarian',color=>'white'};     # Style definition

$html_template = choose dTemplate( $style,      # Selector definition
  'hungarian+white' => 
          define dTemplate("hun_white_template.html"),
  'spanish'         => 
          define dTemplate("spanish.html"),
  'black+hungarian' => 
          define dTemplate("hun_black_template.html"),
  'english'         => 
          define dTemplate("english_template.html"),
  'empty'           => 
    "<html>This is a text, $BODY$ is NOT substituted!!!!"</html>",
  ''                => 
          text dTemplate "<html>$BODY$</html>",  # default
);

$body_template= choose dTemplate( $style,       # Selector definition
  'hungarian'       => 
          define dTemplate("sziasztok_emberek.html"),
  'spanish'         => 
          define dTemplate("adios_amigos.html"),
  ''                => 
          define dTemplate("bye_bye.html"),
);

print $html_template->parse(BODY => $body_template->parse());
  # will print "sziasztok_emberek.html" in the
  #"hun_white_template.html"

%$style=();
print $html_template->parse(BODY => $body_template->parse());
  # will print "bye_bye.html" surrounded by "<html>" and "</html>" tags.

%$style=( lang => 'english' );
print $html_template->parse(BODY => $body_template->parse());
  # will print the "bye_bye.html" in of the "english_template.html"

DESCRIPTION

This module is aimed to be a simple, general-purpose, lightweight, but very powerful templating system.

You can write template-parsing routines in the way the templates are structured logically. Starting from the biggest to the smallest. Your program code will be very clear, structured and easy to understand. This logic can be attained by using inline subroutines as values of template variables. (Look at the example at the end of the document)

USAGE

First, you need to know how a template looks like, then you need to know how to define a template in a perl program, then you can parse it.

After that you can see how to make new encoders.

How a template looks like

A template is a simple text file, which contains template variable placeholders.

The full format of a placeholder is:

$Template_Variable%printf_style_format_string*encoder1*encoder2$

Where:

Template_Variable

It is a mandatory part of the placeholder. Can contain any (locale-aware) alphanumeric characters and '.' .

%printf_style_format_string

This is an optional part. Used when you want to format the output. You can use as many '%' as you want, it can be good to pad the variable, for example when you parse a table. E.g: $MONEY%%%%%%011d$ is a valid placeholder.

*encoder

There are predefined encoders in the module, which can be used to format the input data. These are:

- u    : url-encoder
- h    : HTML-encoder (converts > to &gt;, etc)
- uc   : convert the string to uppercase
- lc   : convert the string to lowercase

You can use zero or more of these:

$TITLE*uc*h$

Read more on encoders (and how to make new encoders) in the Encoders part.

Definition of a template

There are 3 ways to define a template.

$template = define dTemplate $filename

This reads the template from a file.

$template = text dTemplate $scalar

This creates a template from a scalar

$template = choose dTemplate $hash, "style1" => $template1, "style2" => ...

It is the definition of the template chooser. It is the way how you can create styled templates.

Parsing

Parsing means substituting the variables which are defined in the template. It can be done by simply calling the "parse" method of a dTemplate object.

The parameters of the "parse" method are the substitution definitions.

You can provide substitution parameters in two form:

- list of name => value pairs
- with a hash reference

You can mix them if you want:

$template->parse(
  name => $value,
  { name2 => $value2, name3 => $value3 },
  name4 => $value4,
  { name5 => $value5 },
  ...
)

The "value" can be:

scalar or scalar ref.

If a value is scalar, it will be substituted. Scalar refs can be used to save some memory if you use them more than one time.

code reference ( sub { }, or \&subroutine )

The sub will be evaluated at each occurence of the template variable.

hash

You can assign a hash to a template variable if you want. In this way, you can use structured data in the templates, e.g you assign a { name => "Greg", "zip" => 111 } to the template variable "person", and if you use "person.name" in the template, you will get "Greg" back. Nesting (more "."-s) will also work.

You can use %dTemplate::parse hash to assign global parse parameters.

The return value of the parse method is a dTemplate::Scalar object, which can be used as a simple scalar, but really it is a scalar reference to save some memory. It is useful if you use large templates.

Encoders

The global hash, %dTemplate::ENCODERS contains the defined encoders.

The hash keys are the names, the values are subroutine references. These subs get the encodable data as the first parameter and returns the encoded value.

HINTS

  • In the first parse of every template, the templates will be compiled. It is used to speed up parsing.

  • Don't forget that %dTemplate::parse can be localized. This means you can define local-only variable assignments in a subroutine:

    local %dTemplate::parse=( 
      %dTemplate::parse, 
      local_name => $value 
    );
  • You don't need to use text as the input value of an encoder, you can use any scalar, even referenes! If you want (for example) print a date by a date encoder, which expects the date to be an array ref of [ year, month, day ], then you can do this, e.g:

    $dTemplate::ENCODERS{date}=sub {
      return "" if ref($_[0]) ne 'ARRAY';
      return $_[0]->[0]."-".$_[0]->[1]."-".$_[0]->[2];
    }

    Then, when you put $START_DATE*date$ to a template, you can parse this template:

    $template->parse(
      START_DATE => [2000,11,13],
      ...
    );

ALL-IN-ONE EXAMPLE

It is an example, which contains most of the features this module has. It is not intended to be a real-world example, but it can show the usage of this module.

This example consists of one program, and some template modules.

The executable version of this program can be found in the example directory of the module distribution.

use dTemplate;

### definition of the standard templates

my @TEMPLATE_LIST=qw(page table_row table_cell);
my $templates={};
foreach my $template (@TEMPLATE_LIST) {
  $templates->{$template} = 
    define dTemplate("templates/$template.htm");
}

### definition of the styled templates (styles = languages)

my @STYLES=qw(eng hun);
my @STYLED_TEMPLATE_LIST=qw(table_title);

my $style_select={ lang => 'hun' }; 

foreach my $template (@STYLED_TEMPLATE_LIST) {
  my @array=();
  foreach my $style (@STYLES) {
    push @array, $style => 
      define dTemplate("text/$style/$template.txt");
  }
  $templates->{$template} = 
    choose dTemplate $style_select, @array;
}

### setting up input data

my $table_to_print=[
  [ "Buwam",   3, 6, 9 ],
  [ "Greg",    8, 4, 2 ],
  [ "You're",  8, 3, 4 ],
  [ "HTML chars: <>", 3],
];

### setting up the global parse hash with parse parameters;

$dTemplate::parse{PAGENO}=7;

### settings up a hash with personal data.

my $person_hash={
  name => { first_name => "Greg" },
  zip  => "9971",
};

### this hash is simply added to other parse parameters

my $parse_hash={
  "unknown.data" => 157,
};

### the main page parse routine

print $templates->{page}->parse(
  TABLE_TITLE =>             # name => value pair
    $templates->{table_title}->parse(),
  TABLE => sub {             # name => value pair. value is a sub
    my $ret="";
    foreach my $row (@$table_to_print) {
      $ret .= $templates->{table_row}->parse(
        BODY => sub {
          my $ret="";
          foreach my $cell (@$row) {
            $ret .= $templates->{table_cell}->parse(
              TEXT => $cell,
            )
          }
          return $ret;
        }
      )
    }
    return $ret;
  },
  "person" => $person_hash,  # name => value pair. value is a href
  $parse_hash,               # only a hash with parse parameters
);

And the templates:

templates/page.htm:
<html>
<body>

<h1>$TABLE_TITLE*h$</h1>

<table>
$TABLE$
</table>

<br>
Person name: $person.name*h$, zip code: $person.zip*h$
<br>

Unknown data: $unknown.data*h$
<br>

Page: $PAGENO%02d*h$

</body>
</html>
templates/table_row.htm:
<tr>$BODY$</tr>
templates/table_cell.htm:
<td>$TEXT*h$</td>
text/eng/table_title.txt:
Table 1
text/hun/table_title.txt:
1. táblázat

COPYRIGHT

Copyrigh (c) 2000-2001 Szabó, Balázs (dLux)

All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

AUTHOR

dLux (Szabó, Balázs) <dlux@kapu.hu>

SEE ALSO

perl(1).

1 POD Error

The following errors were encountered while parsing the POD:

Around line 383:

Non-ASCII character seen before =encoding in 'táblázat'. Assuming CP1252