Extract Contents from HTML Table [duplicate] - perl

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Extract Table Contents using Perl
I am trying to extract table content from a html file using HTML::TableExtract. My problem is my html file is structured in the following way:
!DOCTYPE html>
<html>
<body>
<h4>One row and three columns:</h4>
<table border="1">
<tr>
<td>
<p> 100 </p></td>
<td>
<p> 200 </p></td>
<td>
<p> 300 </p></td>
</tr>
<tr>
<td>
<p> 100 </p></td>
<td>
<p> 200 </p></td>
<td>
<p> 300 </p></td>
</tr>
</table>
</body>
Because of this structure, my output looks like:
100|
200|
300|
400|
500|
600|
Instead of what I want:
100|200|300|
400|500|600|
Can you please help? Here is my perl code
use strict;
use warnings;
use HTML::TableExtract;
my $te = HTML::TableExtract->new();
$te->parse_file('Table_One.html');
open (DATA2, ">TableOutput.txt")
or die "Can't open file";
foreach my $ts ($te->tables()) {
foreach my $row ($ts->rows()) {
my $Final = join('|', #$row );
print DATA2 "$Final";
}
}
close (DATA2);

sub trim(_) { my ($s) = #_; $s =~ s/^\s+//; $s =~ s/\s+\z//; $s }
foreach my $ts ($te->tables()) {
foreach my $row ($ts->rows()) {
print DATA2 join('|', map trim, #$row), "\n";
}
} ^
|
|
Or if you really want the trailing "|",
sub trim(_) { my ($s) = #_; $s =~ s/^\s+//; $s =~ s/\s+\z//; $s }
foreach my $ts ($te->tables()) {
foreach my $row ($ts->rows()) {
print DATA2 (map { trim($_).'|' } #$row), "\n";
}
}

Related

How to create HTML tables dynamically using Perl?

I am working on a project where I need to access CSV file form a web URL. I am able access the file and print the content from CSV file in the terminal, but I'm unable to produce HTML table (then I'll later send email using MIME).
Here is my code - I need complete CSV file as HTML table delivered to my email.
#!/usr/bin/perl
use strict;
use warnings;
use LWP::Simple;
use POSIX qw(strftime);
use MIME::Lite;
use Getopt::Long;
my $to="pankajdustbin\#gmail.com";
my $from="pankajdustbin\#gmail.com";
$subject="CSV File";
my $content = `curl -s "https:csvfile.com"`;
#output = split(/\n/,$content);
foreach my $line (#output) {
my ($col1, $col2, $col3, $col4, $col5, $col6) = split(/,/, $line);
#print "\n$col1, $col2, $col3, $col4, $col5, $col6\n";
$message = "<tr> <td>$col1</td> <td>$col2</td> <td>$col3</td> <td>$col4</td> <td>$col5</td> <td>$col6</td></tr>";
}
my $msg=MIME::Lite->new(
From => $from,
To => $to,
Subject => $subject,
Data => $message
);
$msg->attr('content-type' => 'text/html');
#MIME::Lite->send("smtp");
$msg->send;
With this code, the HTML table contains only the last row of the CSV. Can someone help me how I should do?
CSV has around 100 rows, and the sample output that I see in terminal as below:
1.2.3.4 03-04-2022. 03-08-2022. Red. 1%. Positive
5.2.3.4 03-05-2022. 04-08-2022. Blue. 1%. Neutral
and so on...
The problem is that you overwrite the contents of the $message variable each time through the foreach loop. This means that $message will only have the last value that you assign to it.
You could append to the contents of the variable using the .= operator:
my $message;
foreach my $line (#output) {
my ($col1, $col2, $col3, $col4, $col5, $col6) = split(/,/, $line);
$message .= "<tr> <td>$col1</td> <td>$col2</td> <td>$col3</td> <td>$col4</td> <td>$col5</td> <td>$col6</td></tr>";
}
Previous answer covered that you overwrite $message in the loop what is not you have intended.
Following snippet code demonstrates slightly different approach to build html table utilizing split and for loop.
Then table can be utilized anyway you desire -- send it by mail or generate html page. In this demo code complete html page generated.
Note #1: \n and \t optional and added for html readability only
Note #2: as no sample input CVS file was provided the content was assumed based on provided output in terminal
use strict;
use warnings;
use feature 'say';
my $table = '<table border=1>';
while( my $line = <DATA>) {
chomp $line;
$table .= "\n\t\t\t<tr>";
$table .= "\n\t\t\t\t<td>" . $_ . '</td>' for split(/,/,$line);
$table .= "\n\t\t\t</tr>";
}
$table .= "\n\t\t</table>";
my $html =
"<html lang='en'>
<head>
<meta charset='utf8' />
<link rel='stylesheet' href='css/styles.css'>
<title>
CVS table
</title>
</head>
<body>
$table
</body>
</html>
";
say $html;
__DATA__
1.2.3.4,03-04-2022,03-08-2022,Red,1%,Positive
5.2.3.4,03-05-2022,04-08-2022,Blue,1%,Neutral
1.2.3.4,03-04-2022,03-08-2022,Red,1%,Positive
5.2.3.4,03-05-2022,04-08-2022,Blue,1%,Neutral
1.2.3.4,03-04-2022,03-08-2022,Red,1%,Positive
5.2.3.4,03-05-2022,04-08-2022,Blue,1%,Neutral

Send action links with buttons in Mail using YII2

I want to put action button in this mail format Using Yii2 ..
So that releveant person can take a certain actions (Accept or Reject) through mail itself.
Is there any way to send encrypted key or anything else so that particular usr can perform their operation using mail it self.?
As of now i am able to send only mail with normal text body , i want to send particular action link with button along with this mail.
How can i achieve this ?
Any help will be highly appriciated.
Thanks in Advance.
My Controller Code.
/* Sending Mail Function */
public function Sendemail($request, $receiver, $subject, $email_body) {
$empmodel = Employee::find()->where('EmployeeNo = "' . $request->createdby . '" ')->all();
$data = ServreqItems::find()->where('srno=' . $request->srno)->all();
$content = "<html><body>";
$content .= "<table align='center' width='70%' bgcolor='#e0e0e0' cellpadding='0' cellspacing='0' border='0'>";
$content .= "<tr><td>";
$content .= "<table align='center' width='100%' cellpadding='0' cellspacing='0' style='border:dashed #FFA500 2px; max-width:650px; background-color:#fff; font-family:Verdana, Geneva, sans-serif;'>";
$content .= "<thead>
<tr height='80'>
<th colspan='4' style='background-color:#f5f5f5; border-bottom:solid 1px #bdbdbd; font-family:Verdana, Geneva, sans-serif; color:#333; font-size:24px;' >" . $request->FormsName . " Details</th>
</tr>
</thead>";
$content .= "<tbody>
<tr align='center' height='10' style='background-color:#FFA500; font-family:Verdana, Geneva, sans-serif;'></tr>";
$empmdl = Employee::find()->where('EmployeeNo = "' . Yii::$app->session['username'] . '" ')->all();
for ($e = 0; $e < count($empmdl); $e++) {
$content.= "<tr>
<td colspan='4' style='padding:15px;'>
<p style='font-size:20px;'>Hi' " . $empmdl[$e]->EmployeeName . " !!! " . $email_body . "</p>
<hr />";
}
for ($i = 0; $i < count($data); $i++) {
$content.= '<tr><td style="padding-left:15px;padding-bottom:15px;">' . $data[$i]->fid->filable . '</td> <td style="padding-right:255px;"> : ' . $data[$i]->fivalue . '</td></tr>';
}
$content .= "<tr height='25'>
<td colspan='4' align='center' style='background-color:#f5f5f5; border-top:dashed #FFA500 2px; font-size:12px; '>
</td>
</tr>
</tbody>";
$content .= "</table>";
$content .= "</td></tr>";
$content .= "</table>";
$content .= "</body></html>";
$sender = 'test#abc.in';
$message = Yii::$app
->mail
->compose()
->setFrom($sender)
->setTo($receiver)
->setSubject($subject)
->setHtmlBody($content, ' text/html')
;
Yii::$app->mail->getTransport()->start();
Yii::$app->mail->send($message);
Yii::$app->mail->getTransport()->stop();
echo '<script>alert("Email Sent Successfuly")</script>';
}
encrypt url like as #kumar Rakesh explained
$id = $emp_id;
$static_key = "afvsdsdjkldfoiuy4uiskahkhsajbjksasdasdgf43gdsddsf";
$ids = $id . "_" . $static_key;
$b_id = base64_encode($ids);
Then you can make two links for Accept and Decline.
$url1 = base_url('Class_name/action_name/') . "/?id=" . $b_id."&action=accept";
$url2 = base_url('Class_name/action_name/') . "/?id=" . $b_id."&action=reject";
And in your Sendemail function do this:
$content .= "<p><a target='_blank' href='" . $url1 . "'>Accept</a></p>";
$content .= "<p><a target='_blank' href='" . $url2 . "'>Reject</a></p>";
As like your question , I have sent a link in my email for forget password.. This link Work for different functionality for different users. I am working it with codeigniter but it also work fine for all php frameworks.
e.g.
$id = $emp_id;
$static_key = "afvsdsdjkldfoiuy4uiskahkhsajbjksasdasdgf43gdsddsf";
$ids = $id . "_" . $static_key;
$b_id = base64_encode($ids);
$url = base_url('Access/newpassword/') . "/?id=" . $b_id;
Now $url is secure encrypted link. And this url send in body part of message e.g.
echo "<p><a target='_blank' href='" . $url . "'>Change Password</a></p>";
Send it in email . After click of user at this link in his/her email.. you can achive this reverse process of all thing eg..
$ids = $this->input->get('id');
$urlData = array('ids'=>$ids);
$iddecoded = base64_decode($ids);
$idsalt = explode('_', $iddecoded);
$id = $idsalt[0];
$salt = $idsalt[1];
Now $id is employe Id.. Try this php code. It will be working Fine for everyone.

spliting the html files using perl

I am new to Perl but I have tried to write a program to split a single HTML file into multiple HTML files.
#!/usr/bin/env perl
use strict;
#use warnings;
my #file_names;
## Read the list of file names
open( my $fh, "$ARGV[0]" );
while ( <$fh> ) {
chomp; #remove new line character from the end of the line
push #file_names, $_;
}
my $counter = 0;
my ( $file_name, $fn );
## Read the input file
open( $fh, "$ARGV[1]" );
while ( <$fh> ) {
## If this is an opening class, open the next output file,
## and set $counter to 1.
if ( / class="bch_ha"/ ) {
$counter = 1;
$file_name = shift(#file_names);
open( $fn, ">", "$file_name" );
#print "<html>\n<body>";
}
## If this is a closing class, print the line and set $counter back to 0
if ( /\n<p sourcepage="(\d+)" class="bch_ha"/ ) {
$counter = 0;
print $fn $_;
close($fn);
}
if ( / class="bcesu_tt"/ ) {
$counter = 1;
$file_name = shift(#file_names);
open( $fn, ">", "$file_name" );
#print "<html>\n<body>";
}
if ( /\n<p sourcepage="(\d+)" class="bcekt_tt"/ ) {
$counter = 0;
print $fn $_;
close($fn);
}
if (/ class="bcekt_tt"/ ) {
$counter = 1;
$file_name = shift(#file_names);
open( $fn, ">", "$file_name" );
#print "<html>\n<body>";
}
if ( /\n<p sourcepage="(\d+)" class="bcepq_tt"/ ) {
$counter = 0;
print $fn $_;
close($fn);
}
if ( / class="bcepq_tt"/ ) {
$counter = 1;
$file_name = shift(#file_names);
open( $fn, ">", "$file_name" );
#print "<html>\n<body>";
}
if ( /\n<p sourcepage="(\d+)" class="bcecs_tt"/ ) {
$counter = 0;
print $fn $_;
close($fn);
}
if ( / class="bcecs_tt"/ ) {
$counter = 1;
$file_name = shift(#file_names);
open( $fn, ">", "$file_name" );
#print "<html>\n<body>";
}
if ( /\n<p sourcepage="(\d+)" class="bceex_tt"/ ) {
$counter = 0;
print $fn $_;
close($fn);
}
if ( / class="bceex_tt"/ ) {
$counter = 1;
$file_name = shift(#file_names);
open( $fn, ">", "$file_name" );
#print "<html>\n<body>";
}
if ( /\n<\/body>\n<\/html>/ ) {
$counter = 0;
print $fn $_;
close($fn);
}
## Print into the corresponding file handle if $counter is 1
print $fn $_ if $counter == 1
}
I need to add some more options. The code should ask for manual input for the delimiters and the split files should go to folder name chapterxx. Please help me on this
Yeah Please find the below HTML sample.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8" />
</head>
<body>
<p sourcepage="27" `class="bch_ha"`></p>
<p sourcepage="26" class="bopob_ct">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</p>
<p sourcepage="26" class="bopob_cr">Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx% <i>Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</i></p>
<p sourcepage="26" class="bch_nmword">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</b></p>
<p sourcepage="26" class="bch_nm">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</b></p>
<p sourcepage="26" class="bch_tt">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</p>
<p sourcepage="26" class="bopob_tt">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx% <b>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX% </b>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</p>
<p sourcepage="26" class="bopob_tx">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</i></p>
<p sourcepage="26" class="bopob_lbfirst">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</b></p>
<p sourcepage="26" class="bopob_lb">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</b></p>
<p sourcepage="26" class="bopob_lb">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</b></p>
<p sourcepage="26" class="bopob_lb">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</b></p>
<p sourcepage="26" class="bch_ha">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</b></p>
<p sourcepage="26" class="bopob_lblast">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</b> </p>
<p sourcepage="26" class="bopcs_txfirst">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</p>
<p sourcepage="26" class="bopcs_tx">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</p>
<p sourcepage="26" class="bopcs_tx">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</p>
<p sourcepage="27" class="bopcs_tx">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</p>
<p sourcepage="27" class="bopcs_tx">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%<span class="sup">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</sup>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</p>
<p sourcepage="27" class="bch_txfirst">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</p>
</body>
</html>
I just need to split the html based on the class class="bch_ha" to next class="bch_ha" and write the content in new html named reader_0.html. the file name will be incremental like reader_1.html.
Maybe this example will give you an idea on how to be able to complete your program.
In this example the focus is on how to split files based on the delimiter.
Note: Only the html body is saved.
#!/usr/bin/env perl
# test.pl
use strict;
use warnings;
my $file = './htmlInput.html'; # input file
my $delim = 'class="bch_ha"'; # delimiter
my $dir = 'chapter' . time; # folder with unix timestamp
# mkdir returns 1 if success
if ( mkdir($dir, 0755) ) {
print "INFO: Created folder $dir to collect files.\n";
} else {
die "Can't make folder $dir\n";
}
# reader_x.html, x = [0..]
my $reader = 'reader_0.html';
my $fh2;
my $cnt = 0;
my $delim_first_time = 1;
open(my $fh, "<", $file) or die "Can't open and read $file: $!"; # read file
while (my $li = <$fh>) {
last if ( $li =~ /<\/body>/ ); # quit the while loop
if ( $delim_first_time && $li =~ /$delim/ ) {
open($fh2, ">", "./$dir/$reader") or die "Can't write to $reader : $!"; # write
$delim_first_time = 0;
} elsif ( $li =~ /$delim/ ) {
close($fh2);
$cnt++;
$reader =~ s/[0-9]+/$cnt/; # reader_0.html -> reader_1.html
open($fh2, ">", "./$dir/$reader") or die "Can't write to $reader : $!"; # write
}
print $fh2 $li if !$delim_first_time;
}
close($fh);
close($fh2);
# output:
# [~]$ ./test.pl
# INFO: Created folder chapter1465642603 to collect files.
# [~]$ ls chapter1465642603
# reader_0.html reader_1.html
# [~]$ cat chapter1465642603/reader_0.html
# <p sourcepage="27" `class="bch_ha"`></p>
# <p sourcepage="26" class="bopob_ct">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</p>
# <p sourcepage="26" class="bopob_cr">Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx% <i>Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</i></p>
# <p sourcepage="26" class="bch_nmword">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</b></p>
# <p sourcepage="26" class="bch_nm">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</b></p>
# <p sourcepage="26" class="bch_tt">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</p>
# <p sourcepage="26" class="bopob_tt">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx% <b>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX% </b>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</p>
# <p sourcepage="26" class="bopob_tx">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</i></p>
# <p sourcepage="26" class="bopob_lbfirst">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</b></p>
# <p sourcepage="26" class="bopob_lb">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</b></p>
# <p sourcepage="26" class="bopob_lb">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</b></p>
# <p sourcepage="26" class="bopob_lb">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</b></p>
# [~]$
# [~]$ cat chapter1465642603/reader_1.html
# <p sourcepage="26" class="bch_ha">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</b></p>
# <p sourcepage="26" class="bopob_lblast">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</b> </p>
# <p sourcepage="26" class="bopcs_txfirst">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</p>
# <p sourcepage="26" class="bopcs_tx">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</p>
# <p sourcepage="26" class="bopcs_tx">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</p>
# <p sourcepage="27" class="bopcs_tx">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</p>
# <p sourcepage="27" class="bopcs_tx">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%<span class="sup">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</sup>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</p>
# <p sourcepage="27" class="bch_txfirst">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%</p>
# [~]$

download url content of the cgi web page

I have cgi search engine for local flat database search and I would like to add option the user able to export/download the search result. is that possible with cgi?
this is the code.
#!/usr/bin/perl
read(STDIN, $buffer,$ENV{'CONTENT_LENGTH'});
# Split the name-value pairs
#pairs = split(/&/, $buffer);
foreach $pair (#pairs) {
($key, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$formdata{$key}.= "$value";
}
$search = $formdata{'search'};
open(INFO, "/test.txt");
#array=<INFO>;
close (INFO);
print "Content-type:text/html\n\n";
print "<html>\n";
print "<head><title>Search result</title></head>\n";
print "<body>\n";
print "<h4><font color=#990000>This is your search result!</h4>\n";
$search_url = 'https://test.php';
foreach $line (#array) {
if ($line =~ /$search/){
($host,$ip)=split(/\|/,$line);
$records= ++$counter;
#result =($host,$ip);
print "<font color=#7a378b><b><p>";
print "<table border=0 cellpadding=0 cellspacing=0 style=border-collapse: collapse
bordercolor=#111111 width=20% bgcolor=#C0C0C0>";
print "</tr>";
foreach (#result) {
#words = split ;
print "<tr><td width=33% bgcolor=#DCDCDC><b><font color=#000080 size=1 face=Courier New>$words[0]</font></b></td>";
print "<td width=36% bgcolor=#DCDCDC><b><font color=#000080 size=1 face=Courier
New>$words[1]</font></b></td>";
print "</table>";
}
}
}
if ($records== 0) {
print " Sorry! No records found\n";
}
Yes. The conventional way is to output the appropriate content type header, e.g.
Content-type: text/csv
Content-type: text/xml
and optionally to specify a "content disposition" as well. In conforming browsers, this will give the client the option to save the server's output to a local file:
Content-disposition: attachment;filename="myfilename.csv"
(Edit to use friedo's wise suggestion)

How can I change a rowspan attribute within my CGI program?

I am writing a CGI script that will process form data, and it should print the name of the input, along with its value, in a table. When I have one or more values with the same name, the name should span rows to accommodate all values that correspond to that name. For example, if I have a name "color" with its values at "red", "green", "blue", then color should span 3 rows in my table. My question is, how would i change the rowspan attribute in my script to accommodate this:
#!/usr/bin/perl --
use strict;
use CGI;
print <<HTTP;
Status: 200 OK
Content-Type: text/html
HTTP
print <<HTML;
<html>
<head>
<title>Parameters<title>
<head>
<body>
<table border="1" cellpadding="5" cellspacing="1">
<tr>
<th>Name</th>
<th>Value</th>
</tr>
HTML
my $query = new CGI;
my($name, $value);
foreach $name ( $query->param)
{
print "<tr>";
print "<td>$name</td>";
foreach $value($query->param($name))
{
print "<td>$value</td>";
print "</tr>";
}
}
Try this:
my $query = new CGI;
my($name, $value);
foreach $name ($query->param) {
my #values = $query->param($name);
my $count = #values;
print "<tr>";
print "<td rowspan='$count'>$name</td>";
print "<td>".shift(#values)."</td>";
print "</tr>";
foreach $value (#values) {
print "<tr>";
print "<td>$value</td>";
print "</tr>";
}
}
BTW, I would suggest you to consider using some template processing system, e.g. Template Toolkit.