ColonelPanic has asked for the wisdom of the Perl Monks concerning the following question:

I have an HTML template that looks something like this:
<h1>Some beginning HTML up here</h1> <update> interpolate [vars] when they are<p> between brackets like [this].<p> <a href="[doink]">[dink]</a> </update> <small>The ending HTML down here</small>
What I want to do is loop through the code between the update tags, interpolating variables each time.

I know I could search and replace with the data each time, however, this would obviously be inefficient, because it has to search through everything multiple times. I wonder if there is a different way to do it. Thanks in advance for your help.

By the way, I realize I am duplicating the functionality of HTML::Template, but this is a project I started a long time ago, when I was just beginning perl and not very module-aware. And I have my reasons now for not changing it, besides having to rewrite a lot of code.

When's the last time you used duct tape on a duct? --Larry Wall

Replies are listed 'Best First'.
Re: search and variable interpolation in templates
by eg (Friar) on Jan 30, 2001 at 22:15 UTC

    Standard practice is to put your key/values into a hash and loop through your text once.

    my %hash = ( vars => 'vars', this => 'this', doink => 'doink', dink => 'dink', ); while(<DATA>) { s/\[([^]]+)\]/$hash{$1}/g; print; } __END__ <h1>Some beginning HTML up here</h1> <update> interpolate [vars] when they are<p> between brackets like [this]. <p> <a href="[doink]">[dink]</a> </update> <small>The ending HTML down here</small>

    If you want, you can use HTML::Parser or something so it only looks at whatever's between the <update> tags (or, if as gryphon surmised, you want to run through <update> many times.)

Re: search and variable interpolation in templates
by AgentM (Curate) on Jan 30, 2001 at 23:44 UTC
    Legacy code, eh? You do realize that you could prep these files for use with the all-powerful HTML::Template (as you rightfully mention) using a simple regex, right?
    s/\[([^]]+)\]/<TMPL_VAR NAME=$1>/g;
    Then, in your code, nuke all of the opening, reading, parsing, and closing and replace it with three lines of kiss-HTML::Template's-feet code:
    my $t=HTML::Template->new(filename=>'file.html'); $t->param(var=>'AgentM\'s Print-o-Matic'); $CGIquery->print $t->output;
    I can only strongly recommend that you do so. As it is, your regex will return strange-looking HTML or invalid HTML altogether if some HTML guy forgets a bracket. HTML::Template catches this. HTML::Template also provides a handy looping mechanism useful for generating tables and forms. In short, you're right, you should've used HTML::Template. But you have the chance now- so take it!

    Here's another tip: If you encapsulated your parser (the HTML::Template clone) in the first place in a package, you should easily be able to use your existing code to construct a wrapper class around HTML::Template so that you don't have to change ANY code (just throw in a use HTMLTemplateWrapper; at the start)!

    AgentM Systems nor Nasca Enterprises nor Bone::Easy nor Macperl is responsible for the comments made by AgentM. Remember, you can build any logical system with NOR.
Re: search and variable interpolation in templates
by gryphon (Abbot) on Jan 30, 2001 at 22:13 UTC

    Greetings. I'm assuming that the variables you want to place in the "update" sections are stored in arrays, and that all arrays are the same length...

    # @vars, @this, @doing, @dink are predefined. print "<h1>Some beginning HTML up here</h1>\n\n"; for ($x=0; $x<$#vars; $x++) { print "interpolate $vars[$x] when they are<p>\n"; print "between brackets like $this[$x].<p>\n"; print "<a href="$doink[$x]">$dink[$x]</a>\n"; } print "<small>The ending HTML down here</small>\n";

    Is this what you're looking for? This will change significantly if you want to hold your data in something other than these arrays like a hash or something (which would be recommended). Anyway, let me know if this doesn't help; I'll expand my answer or add something. I do this sort of thing all the time with CGIs.

    --Gryphon.

      Personally I would think this method would be best the best because then it doesn't have to replace variables in a string by searching, but just printing them when called for. Of course I could be wrong and just amde an ass of myself.

      I'm not saying I'm the best at Perl, but I'm saying that I am the best.

      Sorry if I wasn't clear in my original question. I have an HTML template in an external file. Hard-coding it in like that would defeat the purpose of having a template. I want non Perlers to be able to edit the HTML without (gasp!) seeing any code.

      When's the last time you used duct tape on a duct? --Larry Wall
Re: search and variable interpolation in templates
by chipmunk (Parson) on Jan 31, 2001 at 00:19 UTC
Re: search and variable interpolation in templates
by ColonelPanic (Friar) on Jan 31, 2001 at 03:00 UTC
    Much thanks to everyone for your help. I have a good idea of where to go from here.

    When's the last time you used duct tape on a duct? --Larry Wall