Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing Objects into Template::Toolkit

I'm writing a script to pull my Stackoverflow activity feed into a webpage, it looks something like this:

#!/usr/bin/perl

use strict;
use warnings;

use XML::Feed;
use Template;

my $stackoverflow_id = 1691146;
my $stackoverflow_url = "http://stackoverflow.com/feeds/user/$stackoverflow_id";

my $template = <<'TEMPLATE';
[% FOREACH item = items %]
[% item.title %]
[% END %]
TEMPLATE

my $tt = Template->new( 'STRICT' => 1 )
  or die "Failed to load template: $Template::ERROR\n";

my $feed = XML::Feed->parse(URI->new($stackoverflow_url));

$tt->process( \$template, $feed )
  or die $tt->error();

The template should iterate my activity feed (from XML::Feed->items()) and print the title of each. When I run this code I get:

var.undef error - undefined variable: items

To get it to work I had to change the process line to:

$tt->process( \$template, { 'items' => [ $feed->items ] } )

Can anyone explain why Template::Toolkit appears unable to use the XML::Feed->items() method?

I've had something similar working with XML::RSS:

my $rss = XML::RSS->new();
$rss->parse($feed);
$tt->process ( \$template, $rss )
    or die $tt->error();
like image 950
RobEarl Avatar asked Sep 13 '26 14:09

RobEarl


1 Answers

Just a couple of tweaks.

#!/usr/bin/perl -Tw

use strict;
use warnings;

use XML::Feed;
use Template;
use Data::Dumper;

my $stackoverflow_id = 1691146;
my $stackoverflow_url = "http://stackoverflow.com/feeds/user/$stackoverflow_id";

my $template = <<'TEMPLATE';
[% FOREACH item = feed.items() %]
[% item.title %]
[% END %]
TEMPLATE

my $tt = Template->new( 'STRICT' => 1 )
  or die "Failed to load template: $Template::ERROR\n";

my $feed = XML::Feed->parse(URI->new($stackoverflow_url));



$tt->process( \$template, { feed => $feed } )
  or die $tt->error();

The template compiler expects a plain hash ref, the keys and values of which are stored internally. Giving it an XML::RSS object works as it has an items element. An XML::Feed object doesn't have an items element as it is just a wrapper for several implementations (including XML::RSS). The template wouldn't get an XML::Feed object, it'd get a plain hash ref, something like:

{ 'rss' => XML::RSS Object }

Wrapping your feed in a hash ref makes the compiler retain the XML::Feed object, allowing the processing engine to perform the 'magic' required when feed.items is found in the template.

like image 141
ddoxey Avatar answered Sep 16 '26 04:09

ddoxey



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!