The CGI module provides HTML helper functions that, when passed array references, apply themselves to each element of the referenced array:
print ol( li([ qw(red blue green)]) );
<OL><LI>red</LI><LI>blue</LI><LI>green</LI></OL>
@names = qw(Larry Moe Curly);
print ul( li({ -TYPE => "disc" }, \@names) );
<UL><LI TYPE="disc">Larry</LI> <LI TYPE="disc">Moe</LI>
<LI TYPE="disc">Curly</LI></UL>
The HTML-generating functions in CGI.pm can make it easy to generate lists and tables. Passed a simple string, these functions produce HTML for that string. But passed an array reference, they work on all strings in that array.
print li("alpha");
<LI>alpha</LI>
print li( [ "alpha", "omega"] );
<LI>alpha</LI> <LI>omega</LI>
The shortcut functions for lists are loaded when you use the :standard import tag, but you need to ask for :html3 explicitly to get helper functions for tables. There's also a conflict between the <TR> tag, which would normally make a tr( ) function, and Perl's built-in tr/// operator. Therefore, to make a table row, use the Tr( ) function.
This example generates an HTML table starting with a hash of arrays. The keys will be the row headers, and the array of values are the columns.
use CGI qw(:standard :html3);
%hash = (
"Wisconsin" => [ "Superior", "Lake Geneva", "Madison" ],
"Colorado" => [ "Denver", "Fort Collins", "Boulder" ],
"Texas" => [ "Plano", "Austin", "Fort Stockton" ],
"California" => [ "Sebastopol", "Santa Rosa", "Berkeley" ],
);
$\ = "\n";
print "<TABLE><CAPTION>Cities I Have Known</CAPTION>";
print Tr(th [qw(State Cities)]);
for $k (sort keys %hash) {
print Tr(th($k), td( [ sort @{$hash{$k}} ] ));
}
print "</TABLE>";
That generates text like this:
<TABLE> <CAPTION>Cities I Have Known</CAPTION>
<TR><TH>State</TH> <TH>Cities</TH></TR>
<TR><TH>California</TH> <TD>Berkeley</TD> <TD>Santa Rosa</TD>
<TD>Sebastopol</TD> </TR>
<TR><TH>Colorado</TH> <TD>Boulder</TD> <TD>Denver</TD>
<TD>Fort Collins</TD> </TR>
<TR><TH>Texas</TH> <TD>Austin</TD> <TD>Fort Stockton</TD>
<TD>Plano</TD> </TR>
<TR><TH>Wisconsin</TH> <TD>Lake Geneva</TD> <TD>Madison</TD>
<TD>Superior</TD></TR>
</TABLE>
You can produce the same output using one print statement, although it is slightly trickier because you have to use a map to create the implicit loop. This print statement produces output identical to that displayed previously:
print table
caption('Cities I have Known'),
Tr(th [qw(State Cities)]),
map { Tr(th($_), td( [ sort @{$hash{$_}} ] )) } sort keys %hash;
This is especially useful for formatting the results of a database query, as in Example 19-3 (see Chapter 14 for more on databases).
#!/usr/bin/perl
# salcheck - check for salaries
use DBI;
use strict;
use CGI qw(:standard :html3);
my $limit = param("LIMIT");
print header( ), start_html("Salary Query"),
h1("Search"),
start_form( ),
p("Enter minimum salary", textfield("LIMIT")),
submit( ),
end_form( );
if (defined $limit) {
my $dbh = DBI->connect("dbi:mysql:somedb:server.host.dom:3306",
"username", "password")
or die "Connecting: $DBI::errstr";
my $sth = $dbh->prepare("SELECT name,salary FROM employees
WHERE salary > $limit")
or die "Preparing: ", $dbh->errstr;
$sth->execute
or die "Executing: ", $sth->errstr;
print h1("Results"), "<TABLE BORDER=1>";
while (my $row = $sth->fetchrow_arrayref( )) {
print Tr( td( $row ) );
}
print "</TABLE>\n";
$sth->finish;
$dbh->disconnect;
}
print end_html( );
The documentation for the standard CGI module; Recipe 14.9
Copyright © 2003 O'Reilly & Associates. All rights reserved.