在 Perl 标记中显示 HTML

Displaying HTML in Perl Tag

我有一个 Perl 脚本,它建立数据库连接并以 HTML 格式显示输出。它试图显示的数据中嵌入了标签 (<>),因此 HTML 不会显示。如果我打开脚本使用记事本生成的实际 HTML 文件,我会看到数据。但是由于标签,我无法显示它。知道如何解决这个问题吗?

#!/usr/bin/perl
use DBI;
use HTML::Escape '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.ID
  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>ID</TH><TH>MESSAGE</TH></TR>";

while (my $ref = $sthslam->fetchrow_hashref()) {
       $Count++;
    $Output .= '<TR><TD align=center rowspan=1 valign=top width=1000 height=1000>'
            . $ref->{'ID'}.'</TD>'
            .  '<TD align=center rowspan=1 valign=top width=1000 height=1000>'
            .  escape_html($ref->{'MESSAGE'}).'</TD></TR>';
}

$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";

期望的输出

已生成 HTML 的内容

以下代码片段演示了已发布代码的略微修改版本。

有关escape_html(...)数据库获取数据的用法,请参阅循环部分。

#!/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";
}

注意:为避免使用 HTML 样式 属性污染代码,花些时间学习 CSS,您生成的 HTML 不包括必需的部分 DOCTYPEhtmlhead, 标题, body

参考:

HTML 有一个易于理解的机制来包含通常被解释为特殊字符的字符。例如,如果您想在 HTML 中包含一个 <,这通常会被视为在您的文档中开始一个新的 HTML 元素。

解决方案是用 HTML 代表这些字符的实体替换那些有问题的字符。例如,< 应替换为 &lt;。请注意,这意味着如果您想在 HTML 中包含符号 (&),则需要将其添加到应该替换的字符集中(在本例中为 &amp;) .

Perl 在网络上的使用由来已久,因此有许多工具可用于执行此替换也就不足为奇了。 HTML::Escape 可能是最著名的。它提供了一个函数 (escape_html()),它接受一个文本字符串和 returns 相同的字符串,所有有问题的字符都被适当的实体替换。

use HTML::Escape 'escape_html';

my $html = '<some text> & <some other text>'
my $escaped_html = escape_html($html);

在 运行 这段代码之后,$escaped_html 现在包含“$lt;some text$gt; $amp; $lt;some other text$gt;”。如果将该文本发送到浏览器,则会显示正确的输出。

因此,最简单的解决方案是在程序顶部加载 HTML::Escape,然后在向输出添加可能有问题的字符串时调用 escape_html()。这意味着您的 while 循环看起来像这样:

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>';
}

请注意,我已经删除了 $Temp 变量(它似乎没有做任何有用的事情)并切换到使用 .= 来构建输出字符串。 =. 是“赋值串联”运算符 - 它将其右侧的新字符串添加到其左侧变量中当前存在的任何内容的末尾。

您似乎是在工作中学习 Perl(这很棒),但是您在一个似乎使用已经过时了大约 20 年的技术的环境中学习它真是一种耻辱。您的问题很好地说明了为什么尝试在 Perl 代码中构建原始 HTML 字符串是个坏主意。使用某种模板引擎是一个更好的主意(Perl 世界中的实际标准似乎是 the Template Toolkit)。

我还建议查看级联样式表,将其作为一种更现代的方法来设置 HTML 输出的样式。