I don't see how your example is more simple than the
following:
use strict;
use warnings;
use CGI qw(header);
use HTML::Template;
my $tmpl = HTML::Template->new(filehandle => \*DATA);
$tmpl->param(
title => 'HTML Sample',
toc => 'Table of Contents',
body => 'Sample text',
);
print header, $tmpl->output;
__DATA__
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title><tmpl_var title></title>
</head>
<body>
<b><tmpl_var toc></b><br/>
<i><tmpl_var body></i>
</body>
</html>
Barring looking under the hood of
HTML::Template,
of course (hairy stuff - but it works, it's tested,
it's ready to go, and it handles loops and includes).