syntax for array push and HTML::Template

I'm trying to use HTML::Template to format some query results, but I don't have the correct (HTML::Template-friendly) syntax for displaying a list. How do I alter the code snippet below so that HTML::Template can handle it properly? I know I could use an HTML wrapper instead, but would like to try using HTML::Template.

snippet:

    ...
    $attend = $LastName_txt . $FirstName_txt . $Email_txt . $CorpDiv_txt . $BusUnit_txt;
    push @attendees, $attend;

     $_[0]->purge;

#    print $attend;
    }

foreach my $atts(@attendees) {
   $newAtts .= $atts."<BR>";  # yes, "<BR>" only makes sense if I use a wrapper instead of html template
#       print  $newAtts."<BR>"
}

# fill in some parameters in the template
$template->param(ConfInfo => $conf);
$template->param(ConfAttendees => $newAtts);   #doesn't work. I need to use an html tempalte loop, but how exactly?
# send the obligatory Content-Type
#print "Content-Type: text/html\n\n";

# print the template
print $template->output;

And in the template, something like this?

   <TMPL_LOOP NAME="ConfAttendees">
      <TMPL_VAR NAME="attend"><BR>
   </TMPL_LOOP>

Can somebody show me what to do?

Thanks!

GessWurker

GessWurkerAsked:
Who is Participating?
 
kanduraConnect With a Mentor Commented:
I think it appears sluggish because you first have to walk through the two xml documents, and you can only start display at the very end.
This may be a situation where using html::template is not the most efficient, and you might want to consider generating your output as the results from the Twig come in.
0
 
kanduraCommented:
Hi GessWurker,

Your template snippet looks good: you have a named loop, and a var within it.
The data you need to supply to the template is an arrayref of hashrefs: the arrayref will be looped over, and the hashrefs will supply the data for each loop.

A rough description with some of your fields would be this:

for( some loop where you get attendee info ) {
   
    # note the use of curly braces here: they make this into a reference to a hash
    my $attend = {
        lastname    => $LastName_txt,
        firstname   => $FirstName_txt,
        email       => $Email_txt,
        # and so on for the other fields ...
    };
    push @attendees, $attend;
}

$template->param( ConfAttendees => \@attendees );


You can now reference each field of the hashref inside the tmpl_loop:

<tmpl_loop name="ConfAttendees">
    First name: <tmpl_var name="firstname"> <br>
    Email:      <tmpl_var name="email"> <br>
</tmpl_loop>

HTH,
Kandura
0
 
GessWurkerAuthor Commented:
Thanks kandura!

I'm not getting any errors, but I'm not getting the attendees either. I get the attendee info as you see below using xml twig and other code that you might remember  :)   ). I need to add the loop to the process_recordA sub?

$queryA = new CGI;
%dataA = $queryA->Vars;
$numberIDA=$dataA{'ConfID'};
$sServerNameA = $ENV{'SERVER_NAME'} || 'localhost';
$queryStrA='http://'.$sServerNameA.'/ics-wpd/exec/icspcgi.exe?TN=Attendees&XM=1&AC=QBE_QUERY&QY=find+ConfUniqueID+ct+'.$numberIDA;

$|++;

sub process_recordA
    {
    local $" = '; ';

    $recA = $_;

    $FirstName = $recA->first_child('inm:FirstName') ? $recA->first_child('inm:FirstName') : undef;
    $FirstName_txt = ($FirstName && $FirstName->text) ? $FirstName->text : undef;

    $LastName = $recA->first_child('inm:LastName') ? $recA->first_child('inm:LastName') : undef;
    $LastName_txt = ($LastName && $LastName->text) ? $LastName->text . ", ": undef;

    $Email = $recA->first_child('inm:Email') ? $recA->first_child('inm:Email') : undef;
    $Email_txt = ($Email && $Email->text) ?  " (" . $Email->text . "), " : undef;

    $CorpDiv = $recA->first_child('inm:CorpDiv') ? $recA->first_child('inm:CorpDiv') : undef;
    $CorpDiv_txt = ($CorpDiv && $CorpDiv->text) ? $CorpDiv->text.", " : undef;

    $BusUnit = $recA->first_child('inm:BusUnit') ? $recA->first_child('inm:BusUnit') : undef;
    $BusUnit_txt = ($BusUnit && $BusUnit->text) ? $BusUnit->text."" : undef;

    $attend = {
        lastname    => $LastName_txt,
        firstname   => $FirstName_txt,
        email       => $Email_txt,
        corpdiv     => $CorpDiv_txt,
        busunit     => $BusUnit_txt,
    };
    push @attendees, $attend;
#     $_[0]->purge;
}

# fill in some parameters in the template
$template->param(ConfInfo => $conf);
$template->param(ConfAttendees => \@attendees);
# send the obligatory Content-Type
#print "Content-Type: text/html\n\n";

# print the template
print $template->output;

0
Cloud Class® Course: Microsoft Windows 7 Basic

This introductory course to Windows 7 environment will teach you about working with the Windows operating system. You will learn about basic functions including start menu; the desktop; managing files, folders, and libraries.

 
kanduraCommented:
make sure you localize all variables in the process_recordA sub, especially $attend:

    my $attend = ...;

Can you do a dump of the @attendees array to see if it contains the records?
Do something like this after processing your xml:

use Data::Dumper;
print Dumper(\@attendees);
0
 
GessWurkerAuthor Commented:
See the complete code below. I declare all the variables at top. Is that the problem?

$template->param(ConfInfo => $conf);   #this works fine
$template->param(ConfAttendees => \@attendees);  #this returns nothing

When I tried
use Data::Dumper;
print Dumper(\@attendees);

all I got back was:
$VAR1 = [];


The complete code:

#!/usr/bin/perl -w

use strict;
use CGI;
use XML::Twig;
use HTML::Template;

$ENV{'HTML_TEMPLATE_ROOT'} = "/docs";

# open the HTML template
my $template = HTML::Template->new(filename => '/conferences/attendees.tmpl');

my ($query, $numberID, %data, $sServerName, $queryStr, $twig, $rec, $conference, $conference_txt, $conf_link_text, $conf_link_text_txt, $location, $location_txt,
    $date_held, $date_held_txt, $year, $year_txt, $conf);
my ($queryA, $numberIDA, %dataA, $sServerNameA, $queryStrA, $twigA, $recA, $FirstName, $FirstName_txt,
    $LastName, $LastName_txt, $Email, $Email_txt, $CorpDiv, $CorpDiv_txt, $BusUnit, $BusUnit_txt, @attendees, $attend);

 $query = new CGI;
 %data = $query->Vars;
 $numberID=$data{'ConfID'};
 $sServerName = $ENV{'SERVER_NAME'} || 'localhost';
 $queryStr='http://'.$sServerName.'/ics-wpd/exec/icspcgi.exe?TN=Conferences&XM=1&AC=QBE_QUERY&QY=find+unique_id+ct+'.$numberID;

$|++;

my $twig = new XML::Twig(
            TwigHandlers =>
             {
                      '/inm:Results/inm:Recordset/inm:Record' => \&process_record,
             },
           );

$twig->parseurl( $queryStr );
sub process_record
    {
    local $" = '; ';

    $rec = $_;

    $conference = $rec->first_child('inm:Conference') ? $rec->first_child('inm:Conference') : undef;
    $conference_txt = ($conference && $conference->text) ? $conference->text.", " : undef;

    $conf_link_text = $rec->first_child('inm:Conf_Link_Text') ? $rec->first_child('inm:Conf_Link_Text') : undef;
    $conf_link_text_txt = ($conf_link_text && $conf_link_text->text) ? $conf_link_text->text.", " : undef;

    $location = $rec->first_child('inm:Location') ? $rec->first_child('inm:Location') : undef;
    $location_txt = ($location && $location->text) ?  $location->text . ", " : undef;

    $date_held = $rec->first_child('inm:Date_Held') ? $rec->first_child('inm:Date_Held') : undef;
    $date_held_txt = ($date_held && $date_held->text) ? $date_held->text.", " : undef;

    $year = $rec->first_child('inm:Year') ? $rec->first_child('inm:Year') : undef;
    $year_txt = ($year && $year->text) ? $year->text ."<BR>" : undef;
    $conf = $conference_txt . $conf_link_text_txt . $location_txt . $date_held_txt . $year_txt;
    }
$queryA = new CGI;
%dataA = $queryA->Vars;
$numberIDA=$dataA{'ConfID'};
$sServerNameA = $ENV{'SERVER_NAME'} || 'localhost';
$queryStrA='http://'.$sServerNameA.'/ics-wpd/exec/icspcgi.exe?TN=Attendees&XM=1&AC=QBE_QUERY&QY=find+ConfUniqueID+ct+'.$numberIDA;

$|++;

sub process_recordA
    {
    local $" = '; ';

    $recA = $_;

    $FirstName = $recA->first_child('inm:FirstName') ? $recA->first_child('inm:FirstName') : undef;
    $FirstName_txt = ($FirstName && $FirstName->text) ? $FirstName->text : undef;

    $LastName = $recA->first_child('inm:LastName') ? $recA->first_child('inm:LastName') : undef;
    $LastName_txt = ($LastName && $LastName->text) ? $LastName->text . ", ": undef;

    $Email = $recA->first_child('inm:Email') ? $recA->first_child('inm:Email') : undef;
    $Email_txt = ($Email && $Email->text) ?  " (" . $Email->text . "), " : undef;

    $CorpDiv = $recA->first_child('inm:CorpDiv') ? $recA->first_child('inm:CorpDiv') : undef;
    $CorpDiv_txt = ($CorpDiv && $CorpDiv->text) ? $CorpDiv->text.", " : undef;

    $BusUnit = $recA->first_child('inm:BusUnit') ? $recA->first_child('inm:BusUnit') : undef;
    $BusUnit_txt = ($BusUnit && $BusUnit->text) ? $BusUnit->text."" : undef;

    my $attend = {
        lastname    => $LastName_txt,
        firstname   => $FirstName_txt,
        email       => $Email_txt,
        corpdiv     => $CorpDiv_txt,
        busunit     => $BusUnit_txt,
    };
    push @attendees, $attend;
}

# fill in some parameters in the template
$template->param(ConfInfo => $conf);
$template->param(ConfAttendees => \@attendees);
# send the obligatory Content-Type
print "Content-Type: text/html\n\n";
# print the template
print $template->output;






0
 
GessWurkerAuthor Commented:
oops, that last my $attend   is just  $attend. Makes no difference though; I get no attendees back.
0
 
kanduraCommented:
It looks like you're not actually calling process_recordA() anywhere. Do you parse that second queryStrA?

The reason it's important to make $attend a local variable is that you need to allocate a new hashref for every new record. Otherwise you'll be changing the same hashref over and over again, and you end up with an array with identical records.
0
 
GessWurkerAuthor Commented:
Aaargh! Yes, in the process of all my cutting and pasting I left out this rather important bit:
$twigA = new XML::Twig(
            TwigHandlers =>
             {
                      '/inm:Results/inm:Recordset/inm:Record' => \&process_recordA,
             },
           );

$twigA->parseurl( $queryStrA );

Works remarkably better when process_recordA is called and $queryStrA is parsed!

(i.e., it works)
0
 
kanduraCommented:
yay!
0
 
GessWurkerAuthor Commented:
kandura:

One last thing before I leave you in peace...  (well...for a little while anyway).

Do you see any ways to improve the efficiency of the code below? The data display seems a trifle sluggish to me, but I think it might just be the time it takes for the xml to fully display (prior to parsing). However, maybe you see some way to quicken the code below? If not, we'll call it a day.

Here's the code:

#!/usr/bin/perl -w

use strict;
use CGI;
use XML::Twig;
use HTML::Template;

$ENV{'HTML_TEMPLATE_ROOT'} = "/docs";

# open the HTML template
my $template = HTML::Template->new(filename => '/conferences/attendees.tmpl');

my ($query, $numberID, %data, $sServerName, $queryStr, $twig, $rec, $conference, $conference_txt, $conf_link_text, $conf_link_text_txt, $location, $location_txt,
    $date_held, $date_held_txt, $year, $year_txt, $conf);
my ($queryA, $numberIDA, %dataA, $sServerNameA, $queryStrA, $twigA, $recA, $FirstName, $FirstName_txt,
    $LastName, $LastName_txt, $Email, $Email_txt, $CorpDiv, $CorpDiv_txt, $BusUnit, $BusUnit_txt, @attendees, $attend);

 $query = new CGI;
 %data = $query->Vars;
 $numberID=$data{'ConfID'};
 $sServerName = "nycweb04.pfizer.com";
 #$ENV{'SERVER_NAME'} || 'localhost';
 $queryStr='http://'.$sServerName.'/ics-wpd/exec/icspcgi.exe?TN=Conferences&RF=ConfXML&XM=1&AC=QBE_QUERY&QY=find+unique_id+ct+'.$numberID;

$|++;

my $twig = new XML::Twig(
            TwigHandlers =>
             {
                      '/inm:Results/inm:Recordset/inm:Record' => \&process_record,
             },
           );

$twig->parseurl( $queryStr );
sub process_record
    {
    local $" = '; ';

    $rec = $_;

    $conference = $rec->first_child('inm:Conference') ? $rec->first_child('inm:Conference') : undef;
    $conference_txt = ($conference && $conference->text) ? $conference->text.", " : undef;

    $conf_link_text = $rec->first_child('inm:Conf_Link_Text') ? $rec->first_child('inm:Conf_Link_Text') : undef;
    $conf_link_text_txt = ($conf_link_text && $conf_link_text->text) ? $conf_link_text->text.", " : undef;

    $location = $rec->first_child('inm:Location') ? $rec->first_child('inm:Location') : undef;
    $location_txt = ($location && $location->text) ?  $location->text . ", " : undef;

    $date_held = $rec->first_child('inm:Date_Held') ? $rec->first_child('inm:Date_Held') : undef;
    $date_held_txt = ($date_held && $date_held->text) ? $date_held->text.", " : undef;

    $year = $rec->first_child('inm:Year') ? $rec->first_child('inm:Year') : undef;
    $year_txt = ($year && $year->text) ? $year->text : undef;
    $conf = $conference_txt . $conf_link_text_txt . $location_txt . $date_held_txt . $year_txt;
    }

$queryA = new CGI;
%dataA = $queryA->Vars;
$numberIDA=$dataA{'ConfID'};
$sServerNameA = $ENV{'SERVER_NAME'} || 'localhost';
$queryStrA='http://'.$sServerNameA.'/ics-wpd/exec/icspcgi.exe?TN=Attendees&XM=1&AC=QBE_QUERY&QY=find+ConfUniqueID+ct+'.$numberIDA;

$|++;

$twigA = new XML::Twig(
            TwigHandlers =>
             {
                      '/inm:Results/inm:Recordset/inm:Record' => \&process_recordA,
             },
           );

$twigA->parseurl( $queryStrA );
sub process_recordA
    {
    local $" = '; ';

    $recA = $_;

    $FirstName = $recA->first_child('inm:FirstName') ? $recA->first_child('inm:FirstName') : undef;
    $FirstName_txt = ($FirstName && $FirstName->text) ? $FirstName->text : undef;

    $LastName = $recA->first_child('inm:LastName') ? $recA->first_child('inm:LastName') : undef;
    $LastName_txt = ($LastName && $LastName->text) ? $LastName->text : undef;

    $Email = $recA->first_child('inm:Email') ? $recA->first_child('inm:Email') : undef;
    $Email_txt = ($Email && $Email->text) ?  $Email->text : undef;

    $CorpDiv = $recA->first_child('inm:CorpDiv') ? $recA->first_child('inm:CorpDiv') : undef;
    $CorpDiv_txt = ($CorpDiv && $CorpDiv->text) ? $CorpDiv->text : undef;

    $BusUnit = $recA->first_child('inm:BusUnit') ? $recA->first_child('inm:BusUnit') : undef;
    $BusUnit_txt = ($BusUnit && $BusUnit->text) ? $BusUnit->text : undef;

    $attend = {
        lastname    => $LastName_txt,
        firstname   => $FirstName_txt,
        email       => $Email_txt,
        corpdiv     => $CorpDiv_txt,
        busunit     => $BusUnit_txt,
    };
    push @attendees, $attend;
}

# fill in some parameters in the template
$template->param(ConfInfo => $conf);
$template->param(ConfAttendees => \@attendees);

# send the obligatory Content-Type
print "Content-Type: text/html\n\n";

# print the template
print $template->output;

0
 
GessWurkerAuthor Commented:
kandura:

You're absolutedly right. This non-HTML::Template version runs much faster:

#!/usr/bin/perl -w
$ContentType   = "Content-type:  text/html\n\n";
print $ContentType;

use strict;
use CGI;
use XML::Twig;

my ($query, $numberID, %data, $sServerName, $queryStr, $twig, $rec, $conference, $conference_txt, $conf_link_text, $conf_link_text_txt, $location, $location_txt,
    $date_held, $date_held_txt, $year, $year_txt, $conf, $twig);
my ($queryA, $numberIDA, %dataA, $sServerNameA, $queryStrA, $twigA, $recA, $FirstName, $FirstName_txt,
    $LastName, $LastName_txt, $Email, $Email_txt, $CorpDiv, $CorpDiv_txt, $BusUnit,
    $BusUnit_txt, $count, $record_counter, @attendees, $attend, $atts, $twigA);

my $HTMLstart = <<START;
<HEAD>
<TITLE>Conference Attendees</TITLE>
<STYLE type="text/css">
<!--
body {  font-family: Arial, Helvetica, sans-serif; color: #000000}
.meeting {  font-size: 12px; font-weight: normal; color: #000099}
.attendees {  font-size: 12px; font-weight: normal; color: #000000}
-->
</STYLE>
</HEAD>
<BODY  bgcolor="#FFFFFF" text="#000000">
<SPAN class="meeting">
START

my $TBLstart = <<tblSTART;
<TABLE width="100%" cellspacing="0" cellpadding="0">
  <TR>
    <TD height="8"></TD>
    <TD></TD>
  </TR>
  <TR>
    <TD valign="top" width="115" class="attendees" nowrap>Pfizer attendees
tblSTART

$query = new CGI;
%data = $query->Vars;
$numberID=$data{'ConfID'};
$sServerName = $ENV{'SERVER_NAME'} || 'localhost';
$queryStr='http://nycweb04.pfizer.com/ics-wpd/exec/icspcgi.exe?TN=Conferences&XM=1&AC=QBE_QUERY&QY=find+unique_id+ct+'.$numberID;

$|++;

$twig = new XML::Twig(
            TwigHandlers =>
             {
                      '/inm:Results/inm:Recordset/inm:Record' => \&process_record,
             },
           );

$twig->parseurl( $queryStr );
sub process_record
    {
    local $" = '; ';

    $rec = $_;

    $conference = $rec->first_child('inm:Conference') ? $rec->first_child('inm:Conference') : undef;
    $conference_txt = ($conference && $conference->text) ? $conference->text.", " : undef;

    $conf_link_text = $rec->first_child('inm:Conf_Link_Text') ? $rec->first_child('inm:Conf_Link_Text') : undef;
    $conf_link_text_txt = ($conf_link_text && $conf_link_text->text) ? $conf_link_text->text.", " : undef;

    $location = $rec->first_child('inm:Location') ? $rec->first_child('inm:Location') : undef;
    $location_txt = ($location && $location->text) ?  $location->text . ", " : undef;

    $date_held = $rec->first_child('inm:Date_Held') ? $rec->first_child('inm:Date_Held') : undef;
    $date_held_txt = ($date_held && $date_held->text) ? $date_held->text.", " : undef;

    $year = $rec->first_child('inm:Year') ? $rec->first_child('inm:Year') : undef;
    $year_txt = ($year && $year->text) ? $year->text ."<BR>" : undef;
    $conf = $conference_txt . $conf_link_text_txt . $location_txt . $date_held_txt . $year_txt;
    print $HTMLstart,$conf ."</span>
    ";
    }

$queryA = new CGI;
%dataA = $queryA->Vars;
$numberIDA=$dataA{'ConfID'};
$sServerNameA = $ENV{'SERVER_NAME'} || 'localhost';
$queryStrA='http://nycweb04.pfizer.com/ics-wpd/exec/icspcgi.exe?TN=Attendees&XM=1&AC=QBE_QUERY&QY=find+ConfUniqueID+ct+'.$numberIDA;


$|++;

$twigA = new XML::Twig(
            TwigHandlers =>
             {
                      '/inm:Results/inm:Recordset/inm:Record' => \&process_recordA,
             },
                           StartTagHandlers =>
                 {
                      '/inm:Results/inm:Recordset' => sub
                    {
                      $count = $_[1]->{'att'}->{'setCount'};
                      $record_counter = 0;
                    },
                 }

           );

$twigA->parseurl( $queryStrA );
sub process_recordA
    {
    local $" = '; ';

    $recA = $_;

    $FirstName = $recA->first_child('inm:FirstName') ? $recA->first_child('inm:FirstName') : undef;
    $FirstName_txt = ($FirstName && $FirstName->text) ? $FirstName->text : undef;

    $LastName = $recA->first_child('inm:LastName') ? $recA->first_child('inm:LastName') : undef;
    $LastName_txt = ($LastName && $LastName->text) ? $LastName->text . ", ": undef;

    $Email = $recA->first_child('inm:Email') ? $recA->first_child('inm:Email') : undef;
    $Email_txt = ($Email && $Email->text) ?  " (" . $Email->text . "), " : undef;

    $CorpDiv = $recA->first_child('inm:CorpDiv') ? $recA->first_child('inm:CorpDiv') : undef;
    $CorpDiv_txt = ($CorpDiv && $CorpDiv->text) ? $CorpDiv->text.", " : undef;

    $BusUnit = $recA->first_child('inm:BusUnit') ? $recA->first_child('inm:BusUnit') : undef;
    $BusUnit_txt = ($BusUnit && $BusUnit->text) ? $BusUnit->text."" : undef;
    $attend = "<A href=\"mailto:" . $Email_txt . "\">" . $LastName_txt . $FirstName_txt ."</A> (" . $CorpDiv_txt . $BusUnit_txt . ")";

    push @attendees, $attend;
     $_[0]->purge;
     }
print "\n" . $TBLstart ."(".$count."):</TD>
    <TD class=\"attendees\">";

foreach $atts(@attendees) {
       print  $atts . "<BR>";
}
print "
    </TD>
  </TR>
</TABLE>
</BODY>";
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.