Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Parse template into data structure

by Anonymous Monk
on Nov 07, 2006 at 08:45 UTC ( [id://582589]=perlquestion: print w/replies, xml ) Need Help??

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

This is likely a trivial question, but I am a novice and the answer eludes me. I am using Template Toolkit to process some ... err, templates. Nothing fancy, just passing a reference to a one dimensional hash, the keys match the template variable names, and it spits out exactly what I expect. So on to some more templates, these provided by a 3rd party. I want to use the templates for my output, but the template variable names no longer match my hash keys.

Basically I'm going to be mapping (perhaps not the best word) my hash keys to the 3rd party template variables that are their equivalent. (last_name vs. lname for instance) My question at this time is not related to that particular task, however. My question is....

Does Template Toolkit provide access to the data structure of a parsed template? I already know the names of the keys in my hash, what I want is to be able to fetch out all of the variable names in a simple template and create some logic that can translate my keys to the appropriate template variable.

A nudge in the right direction would suffice. I'm quite sure I am overlooking something obvious.

Replies are listed 'Best First'.
Re: Parse template into data structure
by Hofmator (Curate) on Nov 07, 2006 at 09:33 UTC
    I don't know much about Template::Toolkit and its innards, so I can't tell you if there is a (un)documented way to get at the information you want.

    But a simple template basically comes down to some text ... [% variable_name %]... some more text. If this is the case with your templates you can easily parse them directly with something like the following:

    local $/; my $text = <DATA>; while ($text =~ /\[%(.*?)%\]/g) { print "$1\n"; } __DATA__ some text ... [% variable_name %] ... some more text [% variable_name2 %] [% variable_name3 %] ... some more text some text ... [% variable_name4 %]

    -- Hofmator

    Code written by Hofmator and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: Parse template into data structure
by fenLisesi (Priest) on Nov 07, 2006 at 12:35 UTC
    The following might help. Cheers.
    use warnings; use strict; use Template; my $tt = Template->new(); my %data_href = ( fname => 'William', lname => 'Shakespeare', ); my %data_map = ( first_name => 'fname', last_name => 'lname', ); $tt->process( \*DATA, { data_href => { map { $_ => $data_href{ $data_map{$_} } } keys %data_map }, } ) or die $tt->error(), "\n"; __END__ New third party template ======================== First name : [% data_href.first_name %] Last name : [% data_href.last_name %]
    Update: The following could actually be closer to your situation. HTH.
Re: Parse template into data structure
by jbert (Priest) on Nov 07, 2006 at 12:51 UTC
    Hmmm...I think the solution might not be that obvious. (especially once you start to worry about more complex constructs within the template, such as IFs etc).

    Here's a sneaky thought - run the template, but give it a tied hash which traps and output the key on each attempted access to a hash value. You'll still miss any hash keys which are conditionally accessed, but it should do as a good first run.

    Looks like Tie::Trace might do the job nicely.

Re: Parse template into data structure
by Rhandom (Curate) on Nov 07, 2006 at 15:56 UTC
    Without getting too complicated - here are the basics.

    use Template; { package MyStash; use base qw(Template::Stash); sub undefined { my $self = shift; my @ident = shift; print "(".join("|",@ident).")\n"; if (@ident > 1) { return ''; } elsif ($ident[0] eq 'adjective') { return 'red'; } elsif ($ident[0] eq 'noun') { return 'fox'; } elsif ($ident[0] eq 'verb') { return 'jumped'; } else { return ''; } } } my $stash = MyStash->new; my $string = "The [% adjective %] [% noun %] [% verb %] over the river +.\n"; Template->new(STASH => $stash)->process(\$string);


    my @a=qw(random brilliant braindead); print $a[rand(@a)];
      And if you'd rather use CGI::Ex::Template (which is Template::Toolkit compatible template wise) you could use the following code (I'd use CGI::Ex::Template personally - but that might be because I'm intimately familiar with it :)).

      use CGI::Ex::Template; my $cet = CGI::Ex::Template->new( UNDEFINED_GET => sub { my $self = shift; my $ident = shift; print "(".join("|",@$ident).")\n"; if (@$ident > 2) { return ''; } elsif ($ident->[0] eq 'adjective') { return 'red'; } elsif ($ident->[0] eq 'noun') { return 'fox'; } elsif ($ident->[0] eq 'verb') { return 'jumped'; } else { return ''; } }, ); my $string = "The [% adjective %] [% noun %] [% verb %] over the river +.\n"; $cet->process(\$string);


      my @a=qw(random brilliant braindead); print $a[rand(@a)];
        UNDEFINED_GET in this package appears to be able to do what I had in mind. I will have to take some time to play with it a bit. Thank you.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://582589]
Approved by Hofmator
Front-paged by andyford
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (2)
As of 2024-04-19 20:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found