Solved

syntax for array push and HTML::Template

Posted on 2004-08-16
11
408 Views
Last Modified: 2012-06-21
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

0
Comment
Question by:GessWurker
  • 6
  • 5
11 Comments
 
LVL 18

Expert Comment

by:kandura
Comment Utility
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
 

Author Comment

by:GessWurker
Comment Utility
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
 
LVL 18

Expert Comment

by:kandura
Comment Utility
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
 

Author Comment

by:GessWurker
Comment Utility
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
 

Author Comment

by:GessWurker
Comment Utility
oops, that last my $attend   is just  $attend. Makes no difference though; I get no attendees back.
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 18

Expert Comment

by:kandura
Comment Utility
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
 

Author Comment

by:GessWurker
Comment Utility
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
 
LVL 18

Expert Comment

by:kandura
Comment Utility
yay!
0
 

Author Comment

by:GessWurker
Comment Utility
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
 
LVL 18

Accepted Solution

by:
kandura earned 500 total points
Comment Utility
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
 

Author Comment

by:GessWurker
Comment Utility
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

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

I've just discovered very important differences between Windows an Unix formats in Perl,at least 5.xx.. MOST IMPORTANT: Use Unix file format while saving Your script. otherwise it will have ^M s or smth likely weird in the EOL, Then DO NOT use m…
I have been pestered over the years to produce and distribute regular data extracts, and often the request have explicitly requested the data be emailed as an Excel attachement; specifically Excel, as it appears: CSV files confuse (no Red or Green h…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now