I have a Perl Script which makes a DB connection and displays the output in HTML format. The data which it's trying to display has tags embedded (<>) in it, hence the html does not get displayed. . If I open the actual html file which the script generates using notepad, I see the data, however I am unable to display it due to the tags. Any idea how this can be fixed?
#!/usr/bin/perl
use DBI;
use HTML::Escape qw/escape_html/;
escape_html("<^<^>");
unlink("D:\\Perl32\\scripts\\UndeliveredRAW.html");
my $host = '${Node.Caption}';
my $user = '${USER}';
my $pwd = '${PASSWORD}';
my $driver = "SQL Server";
$dbhslam = DBI->connect("dbi:ODBC:Driver=$driver;Server=$host;UID=$user;PWD=$pwd") || die "connect failed:";
$sthslam = $dbhslam->prepare("SELECT
DBA_Reports.dbo.undelivered_raw_host_msgs.MESSAGE
FROM
DBA_Reports.dbo.undelivered_raw_host_msgs");
$sthslam->execute;
$msg = "Up";
$Count = 0;
$Output = "";
$Temp = "";
$tbl = "<TABLE border=1 bordercolor=orange cellspacing=0 cellpadding=1>";
$tblhd = "<TR><TH>MESSAGE</TH></TR>";
while (my $ref = $sthslam->fetchrow_hashref()) {
$Count ;
$Temp = "$Temp<TR><TD align=center rowspan=1 valign=top width=5000 height=5000>$ref->{'MESSAGE'}</TD></TR>";
$Output = "$Output$Temp";
$Temp = "";
}
$dbhslam->disconnect;
$Output = "$tbl$tblhd$Output</TABLE>";
my $filename1 = 'D:\\Perl32\\Scripts\\UndeliveredRAW.html';
open(my $fh1, '>', $filename1) or die "Could not open file '$filename1' $!";
print $fh1 "$Output";
close $fh1;
if ($Count > 0) {
$msg = $Output;
}
print "\nMessage: $msg";
print "\nStatistic: $Count";
Desired Output
CodePudding user response:
Following code snippet demonstrates slightly modified version of posted code.
Please see the loop section for escape_html(...)
usage on database obtained data.
#!/usr/bin/env perl
#
# vim: ai ts=4 sw=4
use strict;
use warnings;
use feature 'say';
use DBI;
use HTML::Escape qw/escape_html/;
my $filename = 'D:\Perl32\scripts\UndeliveredRAW.html';
unlink($filename) if -e $filename;
my $host = ${Node.Caption};
my $user = ${USER};
my $pwd = ${PASSWORD};
my $driver = 'SQL Server';
my $dbh = DBI->connect("dbi:ODBC:Driver=$driver;Server=$host;UID=$user;PWD=$pwd")
or die 'DB connect failed:';
my $query = '
SELECT
DBA_Reports.dbo.undelivered_raw_host_msgs.MESSAGE
FROM
DBA_Reports.dbo.undelivered_raw_host_msgs
';
my $rv = $dbh->do($query) or die $dbh->errstr;
my $msg = 'Up';
my $Count = 0;
my $tbl = '
<TABLE border=1 bordercolor=orange cellspacing=0 cellpadding=1>
<TR><TH>MESSAGE</TH></TR>
';
while (my $ref = $sth->fetchrow_hashref()) {
$Count ;
$tbl .= "\n\t<TR><TD align=center rowspan=1 valign=top width=5000 height=5000>"
. escape_html($ref->{'MESSAGE'})
. '</TD></TR>';
}
$tbl .= '
</TABLE>
';
my $html =
'<!DOCTYPE html>
<html>
<head>
<title>Undelivered RAW</title>
</head>
<body>
<h1>DB table data</h1>
' . $tbl . '
</body>
</html>
';
open my $fh, '>', $filename
or die "Could not open file '$filename1' $!";
print $fh $html;
close $fh;
if ($Count > 0) {
say 'Message: ' . $msg;
say 'Statistic: ' . $Count";
}
Note: to avoid polluting code with HTML style attributes find some time to learn CSS, your generated HTML does not include required sections DOCTYPE, html, head, title, body
Reference:
CodePudding user response:
HTML has a well-understood mechanism to include characters that would normally be interpreted as special characters. For example, if you want to include a <
in your HTML, that would normally be seen as starting a new HTML element in your document.
The solution is to replace those problematic characters with HTML entities that represent those characters. For example, <
should be replaced with <
. Note that this means the ampersand (&
) needs to be added to the set of characters that should be replaced (in this case by &
) if you want to include it in your HTML.
Perl has a long history of being used on the web, so it's no surprise that there are many tools available to carry out this replacement. HTML::Escape is probably the best known. It supplies a single function (escape_html()
) which takes a text string and returns that same string with all of the problematic characters replaced by the appropriate entities.
use HTML::Escape 'escape_html';
my $html = '<some text> & <some other text>'
my $escaped_html = escape_html($html);
After running this code, $escaped_html
now contains "$lt;some text$gt; $amp; $lt;some other text$gt;". And if you send that text to a browser, you will get the correct output displayed.
So the easiest solution is to load HTML::Escape at the top of your program and then call escape_html()
whenever you're adding potentially problematic strings to your output. That means your while
loop would look something like this:
while (my $ref = $sthslam->fetchrow_hashref()) {
$Count ;
$Output .= '<TR><TD align=center rowspan=1 valign=top width=5000 height=5000>'
. escape_html($ref->{'MESSAGE'})
. '</TD></TR>';
}
Note that I've removed the $Temp
variable (which didn't seem to be doing anything useful) and switched to using .=
to build up your output string. =.
is the "assignment concatenation" operator - it adds the new string on its right to the end of whatever currently exists in the variable on its left.
You seem to be learning Perl on the job (which is great) but it's a real shame that you're learning it in an environment that seems to use techniques that have been outdated for about twenty years. Your question is a good example of why trying to build up raw HTML strings inside your Perl code is a bad idea. It's a far better idea to use a templating engine of some kind (the defacto standard in the Perl world seems to be the Template Toolkit).
I also recommend looking at Cascading Style Sheets as a more modern approach to styling your HTML output.