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.
Related
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
I am attempting to display some info from an infoblox device. When I run this code in a browser using an html post, the table that displays MAC address entries does not display the values from the api. When I run this code in the unix command-line, the variables show up appropriately. Any Advice?
#!/usr/bin/perl
use strict;
use Infoblox;
use CGI;
my $cgi = new CGI;
print
$cgi->header() .
$cgi->start_html( -title => 'Form Results') .
$cgi->h1('Form Results') . "\n";
my #params = $cgi->param();
my $username = $cgi->param('username');
print '<table border="1" cellspacing="0" cellpadding="0">' . "\n";
foreach my $parameter (sort #params) {
print "<tr><th>$parameter</th><td>" . $cgi->param($parameter) . "</td></tr>\n";
}
print "</table>\n";
print "<p>$username</p>";
print $cgi->end_html . "\n";
#Create a session to the Infoblox appliance
my $session = Infoblox::Session->new(
master => "server", #appliance host ip
username => "username", #appliance user login
password => "password" #appliance password
);
unless ($session) {
die("Construct session failed: ",
Infoblox::status_code() . ":" . Infoblox::status_detail());
}
print "Session created successfully\n<br>";
my #list = $session->get(
object => "Infoblox::DHCP::MAC",
filter => "macfilter",
);
my $nextobject = $list[0];
print <<EOF;
<br>
<table>
<tr>
<th>MAC</th>
<th>Description</th>
<th>UserID</th>
<th>Expiration</th>
</tr>
EOF
foreach my $test ( #list ) {
print "<tr>";
print "<td> $test->mac()</td>";
print "<td>" . scalar($test->comment()) . "</td>\n";
print "<td>" . scalar($test->username()) . "</td>\n";
print "<td>" . scalar(localtime(scalar($test->expiration_time()))) . "</td>\n";
print "</tr>";
}
exit (0);
I had incorrect permissions. The script was running as user nobody and would not display the items correctly on the web page.
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";
}
}
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)
input text file contain the following:
....
ponies B-pro
were I-pro
used I-pro
A O
report O
of O
indirect B-cd
were O
. O
...
output XML file
<sen>
<base id="pro">
<w id="1">ponies</w>
<w id="2">were</w>
<w id="3">were</w>
</base>A report of
<base id="cd">indirect</base> were
</sen>
i want to make an XML file by reading the text file, B- means the begining of my tag and I- means an include words inside the tag while "O" means outside the base tag which means it only exist in the tag.
i try the following codes:
#!/usr/local/bin/perl -w
open(my $f, "input.txt") or die "Can't";
open(my $o, ">output.xml") or die "Can't";
my $c;
sub read_line {
my $fh = shift;
if ($fh and my $line = <$fh>) {
chomp($line);
my #words = split(/\t/, $line);
my $word = $words[0];
my $group = $words[1];
if($word eq "."){
return;
}
else{
if($group ne 'O'){
my #b = split(/\-/, $group);
if($b[0] eq 'B'){
my $e = "<e id=\"";
$e .= " . $b[1] . "\">";
$e .= $word . "</e>";
return $e;
}
if($b[0] eq 'I'){
my $w = "<w id=\"";
$w .= $c . "\">";
$w .= $word . "</w>";
$c++;
return $w;
}
}
else{
$c = 2;
return $word;
}
}
}
return;
}
sub get_text(){
my $txt = "";
my $r = read_line($f);
while($r){
if($r =~ m/[[:punct:]]/){
chop($txt);
$txt .= " " . $r . " ";
}
else{
$txt .= $r . " ";
}
$r = read_line($f);
}
chop($txt);
return "<sen>" . $txt . ".</sen>";
}
instead im getting as output:
<sen>
<base id="pro"> ponies </base>
<w id="2">were</w>
<w id="3">were</w>
A report of
<base id="cd">indirect</base> were
</sen>
i really need help.
Thanks
Writing XML "by hand" will only get you in trouble. Use a module from CPAN.
In your case, I would first put the data in a proper Perl data structure (maybe a hash containing some arrays, or something similar) and then using a module (i.e. XML::Simple for starters) to output to a file.
As Javs said, you want to use a module rather than do this by hand. For your purposes, since you have mixed content, I recommend XML::LibXML. Here is an example I made to test that you can indeed to mixed content like you've got:
use XML::LibXML;
my $doc = XML::LibXML::Document->new();
my $root = $doc->createElement('html');
$doc->setDocumentElement($root);
my $body = $doc->createElement('body');
$root->appendChild($body);
my $link = $doc->createElement('a');
$link->setAttribute('href', 'http://google.com');
$link->appendText('Google');
$body->appendChild($link);
$body->appendText('Inline Text');
print $doc->toString;