http://www.perlmonks.org?node_id=336857

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

Esteemed Monks,

I am using HTML::Template in an application where I would like pass it a hash of hashes. Sadly, it doesnt support this type of structure.

Has anyone out there a module, or even a subroutine, that will parse a hash of hashes into a set of heirarchical template variables?

The alternative is to write something that "flattens" out the data, but this would be rather "not general purpose" which is what I would prefer.

My structure looks like this (it is only a part of a much larger structure):

$VAR1 = { 'apptimeupdated' => '20040315145142', 'appdate' => '2004-03-15', 'personellid' => '0', 'appscref' => '', 'apptime' => '16:45:00', 'appdesc' => '', 'appid' => '270', 'apptype' => { 'taxlc' => '0', 'apt_requ_qual' => '', 'apt_abbr_desc' => '001', 'taxst' => '0', 'apt_defstatus' => { 'name' => 'Pending', 'css_class' => 'pending' +, 'id' => '1', 'graphic' => '/images/te +nt.jpg' }, 'taxfed' => '0', 'value' => '50', 'apt_full_desc' => 'Round, regular - 18 holes +', 'apt_requ_prepay' => '1', 'apt_requ_option' => '', 'providerid' => '4', 'id' => '1' }, 'appamountpaid' => '0', }
jdtoronto

Replies are listed 'Best First'.
Re: HTML::Template and hashes of hashes
by jeffa (Bishop) on Mar 15, 2004 at 22:19 UTC
    Treat them as Lists of Hashes, even if it's only one hash in the list:
    my $VAR1 = { 'apptimeupdated' => '20040315145142', 'apptype' => [{ 'apt_defstatus' => [{ 'name' => 'Pending', }], 'value' => '50', }], }; my $tmpl = HTML::Template->new(filehandle => \*DATA); $tmpl->param($VAR1); print $tmpl->output; __DATA__ <tmpl_var apptimeupdated> <tmpl_loop apptype> <tmpl_var value> <tmpl_loop apt_defstatus> <tmpl_var name> </tmpl_loop> </tmpl_loop>
    I hate to say it ... but i would use TT here instead, since it works better with your existing data structure:
    my $VAR1 = { 'apptimeupdated' => '20040315145142', 'apptype' => { 'apt_defstatus' => { 'name' => 'Pending', }, 'value' => '50', }, }; my $tt = Template->new; $tt->process(\*DATA, $VAR1) || die $tt->error(); __DATA__ [% apptimeupdated %] [% apptype.value %] [% apptype.apt_defstatus.name %]
    OK ... so i don't hate to say it. TT rocks. ;)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
      Thanks jeffa you are right about TT. But this app is 5-6000 lines in and is all based on H::T. I have the TT Book and will be learning it before I start on another project.

      jdtoronto

Re: HTML::Template and hashes of hashes
by blokhead (Monsignor) on Mar 16, 2004 at 02:17 UTC
    This recursively flattens multilevel hashes so you can get to them with a TT-ish syntax from HTML::Template. It should be straight-forward to modify if you also want arrayrefs to be recursively flattened too.
    sub flatten { my $hr = shift; my %result; while (my ($k, $v) = each %$hr) { if (ref $v eq 'HASH') { my $r = flatten($v); $result{"$k.$_"} = $r->{$_} for keys %$r; } else { $result{$k} = $v; } } \%result; } print Dumper flatten { foo => { in_foo => 1, bar => 1, baz => { in_baz => 1 } }, blah => 1 }; __END__ $VAR1 = { 'foo.bar' => 1, 'blah' => 1, 'foo.baz.in_baz' => 1, 'foo.in_foo' => 1 };

    blokhead

      Thanks blokhead,

      Thats just the trick. I was pondering the same answer when I saw your response and I took your code and used it. Thank you so much, it did just what I need.

      jdtoronto