Re: inserting HTML file in a PERL script
by Tortue (Scribe) on May 29, 2005 at 11:17 UTC
|
Here's the kind of thing you could do if this needs to be quick and dirty and you don't have time to learn Template::Toolkit:
my $variable = 'This is a value!';
my $variable_name = '$variable';
my $template = snarf('template.htm');
$template =~ s/\Q$variable_name\E/$variable/g;
print $template;
sub snarf {
local $/ = undef;
my $template_file = shift;
open F, $template_file or die "can't open $template_file";
my $template = <F>;
close F;
$template;
}
with the template.htm file containing:
<HTML>
<HEAD>
<TITLE>Title</TITLE>
</HEAD>
The variable is : $variable
<BR><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TR><TD>
<HR color=#99ffcc SIZE=4>
<FONT face=Arial color=#99ffcc><B>
Bottom text
</B></FONT>
</TD></TR></TABLE>
</BODY>
</HTML>
| [reply] [d/l] [select] |
|
Thank you for your help everyone, it is highly appreciated.
About this script, it seems to be applicable only if the variable is named
$variable
Could it be possible to give me the code for a script that would replace
anything starting with $xxx ?
The variables that i have got in my html code can be named A-Z and '_' like $EMAIL or $CONTACT_ADDRESS
| [reply] |
|
yes, you could match on the $ and lookup the variable name in a hash, and replace with the value. Expects the template variables to be uppercase (A-Z and _ only) and the hash keys to be lower case.
use strict;
use warnings;
my %data = (
first_name => 'Foo',
email => 'Bar',
);
$/ = undef;
my $s = <DATA>;
$s =~ s/\$([A-Z_]+)/exists $data{lc $1}?$data{lc $1}:$&/esg;
print $s;
__DATA__
First name is $FIRST_NAME and<br>
email is: $EMAIL.
junk is $JUNK
| [reply] [d/l] |
|
Just to generalize the script I gave you... This replaces any variable in the template with its value in the program.
It's a quick-and-dirty fix that may solve your problem if you're in a rush. Of course, as others have noted, it would be better if you used a proper templating system. Note also that this only works for simple scalar variables (e.g. $thing, $ZOWIE), not for more complicated variables such as array or hash elements (e.g., $var[$num] or $var{thing}).
my $template = snarf('template.htm');
while ($template =~ /(\$[:alpha:]\w*)/g) {
my $variable_name = $1;
my $value = eval $variable_name;
$template =~ s/\Q$variable_name\E/$value/g;
}
print $template;
| [reply] [d/l] [select] |
Re: inserting HTML file in a PERL script
by dimar (Curate) on May 29, 2005 at 09:26 UTC
|
Your question makes a little sense, but it is not exactly clear what is your underlying rationale and goals:
- do you intend to serve the html over the web or just open them locally on your own machine?
- do you intend to use msft FrontPage extensions in your pages or just using that because it is the only tool you have available?
- are you using this variable interpolation method because you do not want to use any of the myriad templating solutions already out there?
Absent a better understanding of why you are going this specific path, please take a look at Template Toolkit. It seems as though you are trying to re-invent it, or something similar.
http://www.template-toolkit.org/
=oQDlNWYsBHI5JXZ2VGIulGIlJXYgQkUPxEIlhGdgY2bgMXZ5VGIlhGV
| [reply] |
|
Hello and thanks for your answer.
- I will serve them on the web
- I use FrontPage, because it is indeed the only tool that I have in order to
design nice looking HTML pages.
- I inherited of these scripts that I now have to manage myself, and dont
feel like re-writing them all with new tools, as my knowledge of perl is very
limited.
These scripts have a myriad of embedded HTML codes with the print <<eof
method, and I have to re-edit and make them look better.
But for these .pl and .pm scripts, FrontPage is of little help for me, as the
mixture of perl script and HTML code makes it almost impossible to properly edit.
| [reply] |
|
To add to the advice from tchatzi.
The first time I came across Perl I was in a very similar situation to yourself. Perhaps the experiences I had maybe helpful.
Only make one small change at a time. You'll stand a better chance of having something that still works.
A point often made is that, as much as possible, keeping code and HTML separate makes maintaining both easier. A first step could be at least moving it all to the end of the script. Have a sub that returns the HTML.
my $name = 'John';
my $html = get_html(); # sub name corrected
# later...
sub get_html{
my $html = <<HTML;
<html>
<head>
<title>my html</title>
</head>
<body>
<p>Hi there $name</p>
</body>
</html>
HTML
return $html;
}
The next step I took was to replace the variable with an HTML comment.
<p>Hi there <!-- name --></p>
and then the code would look something like
my $html = get_html();
$html =~ s/<!-- name -->/$name/;
The advantage here is that Frontpage can happily use the HTML.
After that it wasn't long before the HTML ended up in a file.
my $html;
{
local $/;
my $file = 'template.html';
open my $fh, '<', $file
or die "can't open $file to read: $!";
$data = <$fh>;
close $fh
or die "cannot close $file: $!";
}
This way you can maintain the HTML in FrontPage.
Once you get to this stage you start to realise you have trod a well worn path! Many have gone before you. As scooterm pointed out above there are many template modules available. I now use HTML::Template and find it excellent.
There are many other aspects of cgi scripts you may want to consider (there is a very good module for that too).
Hope this is of help. If after looking through the docs you still hit some snags (I hit plenty) come back, show what you were trying to do, what you have tried, what you expected. If you do that I have always found the monks very helpful.
Good luck!
update:
Corrected name of sub in code snippet
| [reply] [d/l] [select] |
|
| [reply] |
Re: inserting HTML file in a PERL script
by dimar (Curate) on May 29, 2005 at 19:16 UTC
|
On a contrarian note, thetallblondguy, the time it has taken you to consider the partial solutions in this thread, and the different ways you could indicate variables, might have been better spent looking into a full-grown "real world" application like Template Toolkit (or any of the legion of its kin). Because if this is any kind of serious work, this is not the kind of wheel you want to re-invent.
Your clarification actually suggests your question is not really a perl or CGI question, but a question about how to *surgically* separate the Perl from HTML without breaking either one. That's exactly what templating systems are designed to do.
Sure, you could create perl subroutines that spit out HTML, or separate files with some (special syntax) in them, but the list of wheels you would have to re-invent to get it right are too numerous to list here. For example:
How to disambiguate 'true variables' from 'false variables'?
$19.95USD -> not a variable, a price
$e1p_zE@z -> not a variable, a suggested user-password
Micro$oft -> not a variable, a common company name
$$$CASH$$$ -> not a variable, a common spam subject line
How to handle common scenarios that always come up?
# A variable whose value is contingent on another variable
# A variable that appears inside of a loop
# A variable that should have some 'default' fill in value if the user
+-supplied value is left blank
# A sample code-snippet that should appear inside the HTML and not be
+messed with or interpolated AT ALL
There is a whole catalogue of issues to deal with, and each issue you resolve (on your own) means yet one more (undocumented) 're-invented wheel' that the person who comes after you will have to learn just to figure out what is going on.
If you *really* insist on creating your own system from scratch, you should at least try to use a totally unique syntax for indicating the presence of a 'true variable' ... something that is not likely to appear in any other context.
Hello @@@:username:@@@,
Please consider using @@@:existing_template_system:@@@
instead of creating your own from scratch; instead
of hand-rolling the @@@:huge_number:@@@th ad-hoc system
that no one understands except you.
=oQDlNWYsBHI5JXZ2VGIulGIlJXYgQkUPxEIlhGdgY2bgMXZ5VGIlhGV
| [reply] [d/l] [select] |
Re: inserting HTML file in a PERL script
by astroboy (Chaplain) on May 29, 2005 at 18:44 UTC
|
HTML::Template is a very light, simple solution. The Template Toolkit is nice, but it may be bigger than what you need. | [reply] |
Re: inserting HTML file in a PERL script
by TedPride (Priest) on May 29, 2005 at 18:32 UTC
|
davidrw's solution is the best imho, with some minor changes to the substitution line:
$s =~ s/\$([a-zA-Z]\w*)/exists $data{lc $1} ? $data{lc $1} : ''/esg;
There's no point allowing just uppercase letters and then lowercasing them. It's also not a good idea (at least in my opinion) to leave $vars that don't have a value defined as the original text. The intention was probably to keep things like $10.45 from being interpreted as '', but you can easily avoid this by defining your var names as starting with a letter. | [reply] [d/l] |
|
actually i hadn't thought of the $10.45 case, but that's a key point. The upper/lower casing I picked was pretty much just an arbitrary definition of this quick & dirty template system. My rationale was all upper for the template vars so that they stand out more in the template. And all lowercase for the keys since variable/key names are typically lowercase. Also, lc'ing it makes it tolerant of typos like $FIRSt_NAME in the template.
As for what to do with unknown vars, i figured that leaving '$FOO' in there was better to make it obvious that it didn't match, whereas doing '' might not be noticed..
But both ways are up to the template authoer on how they prefer it to work..
| [reply] |
Re: inserting HTML file in a PERL script
by kyoshu (Curate) on May 31, 2005 at 07:15 UTC
|
why don't you just create a html template and
use HTML::Template;
example of perl sciript:
#!/usr/bin/perl -wT
use strict;
use CGI;
use HTML::Template;
use CGI::Carp qw/fatalsToBrowser/;
my $default_puslapis = 'pradzia';
my $default_sritis = 'pagrindinis';
my $templ = 'data/pagrindinis/main.html';
my $q = new CGI;
if (grep { /application\/xhtml\+xml/ } $q->Accept ) {
print "Content-type: application/xhtml+xml\n\n";
} else {
print "Content-type: text/html;Charset=utf-8\n\n";
}
my $tmpl = HTML::Template->new(filename => $templ);
my $puslapis = $q->param('puslapis') || $default_puslapis;
$puslapis =~ /(\w+)/;
$puslapis = $1;
my $sritis = $q->param('sritis') || $default_sritis;
$sritis =~ /(\w+)/;
$sritis = $1;
if (-e "data/$sritis/$puslapis.html") {
undef local $/;
open my $f, "<data/$sritis/$puslapis.html";
my $content = <$f>;
close $f;
$tmpl->param('tekstas', $content);
} else {
$tmpl->param('tekstas', 'Klaida!');
...
and then you create 'data/pagrindinis/main.html'
where in html code you just add something like:
<TMPL_VAR NAME="tekstas">
in the place where you want $content to appear.
(all this code is from working example with some changes for you to see :-))
| [reply] |
Re: inserting HTML file in a PERL script
by Ctrl-z (Friar) on May 30, 2005 at 12:16 UTC
|
I would second scooterm's comment. In addition, the answers above dont really solve your problem:
- You dont want to be cutting and pasting between an HTML editor and Perl editor
- You dont want to be heavily modifying the HTML (adding special variable tags or whatever)
- You do not want to be heavily modifying the existing Perl code (rewriting to a module API or adding half-assed templating subroutines)
To sum up, by the time perl starts executing you want it to run exactly as your program does now. But for you (while developing) you want the html fragments in their own file, to edit with Frontpage and use Perl's existing $variable syntax.
Consider using a source filter.
package Insert;
use Filter::Simple;
sub slurp
{
my $file = shift;
my ($str, $in);
open($in, $file) or die $!;
local $/ = undef;
$str = <$in>;
close $in;
return $str;
}
FILTER
{
1 while $_ =~ s/INSERT\(\s*?["']?([^"']*?)["']?\s*?\)/slurp($1)/e;
+
}
1;
This will paste the contents of files into your script before perl begins executing.
- Save the above code with the rest of your program as Insert.pm
- add use Insert; to the top of your script
- Cut the contents of each heredoc and paste into a new file
- Replace the heredoc contents with INSERT("/path/to/that/file")
So this
my $variable = "World!";
print <<EOT;
Hello $variable
EOT
would become this
use Insert;
my $variable = "World!";
print <<EOT;
INSERT("includeme.txt")
EOT
With the file includeme.txt being
Hello $variable
This will do what you want - but be careful what you wish for.
At least you can concentrate on hacking the HTML rather than adapting existing code to an API or debugging a broken wheel.
Once you get the HTML the way you want it, you can simply paste it back into the code to get better performance.
time was, I could move my arms like a bird and...
| [reply] [d/l] [select] |