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

In the context of rendering a directory tree in HTML, where the data structure is an array of hashes containing keys "name" (string) and "depth" (integer)...

Is there some way to get HTML::Template to repeat a character N times, say  , without resorting to HTML::Template::Expr?

(I did have a nested data structure before, but from tinkering and other postings I've read, I don't believe that HTML::Template allows for recursion.)

  • Comment on can you repeat a character N times using HTML::Template?

Replies are listed 'Best First'.
Re: can you repeat a character N times using HTML::Template?
by barrd (Canon) on Nov 01, 2003 at 12:20 UTC
    Hiya spditner,
    Is there some way to get HTML::Template to repeat a character N times, say  , without resorting to HTML::Template::Expr?
    Nope. :)

    But... using Zaxo's advice above you could get the script to prepare a HTML::Template param for inclusion into your .tmpl template like so:

    # Original code by Zaxo my $repeated = '&nbsp;' x $foo->{'depth'}; my $line = $repeated . $foo->{'name'} . "<br />"; my $template = HTML::Template->new(filename => 'foo.tmpl'); $template->param(html_out => $line);
    Then in foo.tmpl you would call the result by using something like:
    <TMPL_VAR NAME="html_out">
    Not sure if that's the kind of answer you were looking for, but its one way of achieving your desired result.
Re: can you repeat a character N times using HTML::Template?
by BUU (Prior) on Nov 01, 2003 at 12:23 UTC
    HTML::Template in and of it's self does not allow for recursion. However, recently when I was attempting solve a problem similar to this, what I did was write a template that *allowed* for recursion and then used the perl code to actually recurse. In other words, my template looked something like this:
    <div> <tmpl_var one> <tmpl_var two> <tmpl_var recursion_data> </div>
    Then in my perl code I did something similar to:
    my $ht=new HTML::Template(filename=>recurse.tmpl); my $data; while($foo=recurse()) { $ht->param(one=>foo,two=>bar, recursion_data=>$data); $data=$ht->output; $ht->clear_params(); }
    Thus the total output is constantly updated with all the data you have generated so far, then you stick that data inside the template and do it again. Seemed rather elegant to me at the time, but this may not at all be what you are considering.

    (Btw, if in fact you are doing something similar to what I think you, some sort of nested tree structure and your trying to indent each layer, appropiate, what I did was make each <div></div> in my recursion template have a padding of 5 pixels left or whatever. That way when I nest all of the divs, each one inherits the padding value of all of it's parents, so the first layer had 5 px, the second layer had 10 and so on and so forth. Thus combining the beauty of HTML::Template with the simplicity that is CSS. There are several benefits to doing it this way, such as it's incredibly easy to change the padding for each layer, just change one value in the style sheet, instead of mucking about with perl code.)
Re: can you repeat a character N times using HTML::Template?
by Zaxo (Archbishop) on Nov 01, 2003 at 07:21 UTC

    Without HTML::Template specifics, you can use the x operator to get repeated strings,

    my $repeated = '&nbsp;' x $foo->{'depth'}; my $line = $repeated . $foo->{'name'} . "<br/>\n";

    After Compline,
    Zaxo

Re: can you repeat a character N times using HTML::Template?
by cees (Curate) on Nov 01, 2003 at 23:03 UTC

    As others have mentioned, HTML::Template does not support recursion. However, with a very simple change in the HTML::Template source code you can get it to support recursion to a fixed depth!

    You can use TMPL_INCLUDE to recursively include itself. When you do this, HTML::Template will die with the following error:

    HTML::Template->new() : likely recursive includes - parsed 10 files deep and giving up (set max_includes higher to allow deeper recursion).

    So it will only allow 10 levels of include files. But it is configurable with the 'max_includes' parameter that is passed to the constructor.

    So all you really need to do to get recursion to work to a given depth is to edit HTML::Template so that is doesn't die when it reaches the 'max_includes' limit. Then when you create the HTML::Template opbject, tell it how many levels deep you want your recursion to go (using max_includes), and then use a template file that uses TMPL_INCLUDE to call itself.

    I won't vouch for the efficiency of this method, as each included file is most likely duplicated in memory (ie if you recurse a max of 20 times, you will have 20 parsed copies of the template in memory).

    Another way to handle recursion in HTML::Template is to handle it in the code by recursively creating new HTML::Template objects and including the results in other HTML::Template objects using TMPL_VARs.

    sub recurse_template { my $template_name = shift; my $template = new HTML::Template(filename => $template_name); my $value = recurse_template('template.tmpl'); $template->params(param => $value); return $template->output(); }

    Of course that is an incomplete example, as you would need to stop the recursion at some point, and you probably want to add some parameters at some point... Also, this isn't very efficient either since you are creating and destroying many objects.