Solved

syntax for array push and HTML::Template

Posted on 2004-08-16
11
413 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 5
11 Comments
 
LVL 18

Expert Comment

by:kandura
ID: 11809539
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
ID: 11809889
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
ID: 11810373
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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:GessWurker
ID: 11811305
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
ID: 11811341
oops, that last my $attend   is just  $attend. Makes no difference though; I get no attendees back.
0
 
LVL 18

Expert Comment

by:kandura
ID: 11811447
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
ID: 11811655
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
ID: 11811686
yay!
0
 

Author Comment

by:GessWurker
ID: 11812378
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
ID: 11813294
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
ID: 11814992
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

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

There are many situations when we need to display the data in sorted order. For example: Student details by name or by rank or by total marks etc. If you are working on data driven based projects then you will use sorting techniques very frequently.…
Checking the Alert Log in AWS RDS Oracle can be a pain through their user interface.  I made a script to download the Alert Log, look for errors, and email me the trace files.  In this article I'll describe what I did and share my script.
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…
Six Sigma Control Plans

717 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