【问题标题】:Displaying HTML in Perl Tag在 Perl 标签中显示 HTML
【发布时间】:2021-11-16 04:19:09
【问题描述】:

我有一个 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 内容

【问题讨论】:

  • 听起来你需要HTML::EscapeHTML::Entities 之类的东西。
  • 哦,在 perl 脚本中总是use strict; use warnings;
  • 是需要安装的模块吗?当我尝试使用它时看到这个错误 PerlScript Error: Can't locate HTML/Escape.pm in @INC (@INC contains: D:/Perl32/site/lib D:/Perl32/lib .)
  • 这是我添加的。使用 HTML::Escape qw/escape_html/; escape_html("")
  • 添加到您的问题中的生成 HTML 示例可能很有用。我注意到一些不一致之处:1.变量$host,$user,$pass,$driver将值保存在单引号中,没有发生插值,2.在循环中$Count++但从未使用过,3.$Output = "$Output$Temp";最好写$Output .= $Temp;,注意:有更好的方法可以在变量中形成 HTML 输出,从而提高可读性/简化代码维护。

标签: html perl


【解决方案1】:

以下代码 sn-p 演示了已发布代码的略微修改版本。

请参阅循环部分了解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 不包含必需的部分 DOCTYPE , html, head, title, body

参考:

【讨论】:

    【解决方案2】:

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

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

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

    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,真是太可惜了。您的问题是一个很好的例子,说明为什么尝试在 Perl 代码中构建原始 HTML 字符串是一个坏主意。使用某种模板引擎是一个更好的主意(Perl 世界中的事实标准似乎是the Template Toolkit)。

    我还建议将级联样式表视为一种更现代的 HTML 输出样式设置方法。

    【讨论】:

    • 非常感谢 Dave 的详细解释。有最后一个问题。我需要在输出中添加另一个列 ID。此列不需要任何转义函数。我将 ID 添加到 while 循环中,但遇到了问题。你能告诉我我错过了什么吗?
    • @SQLNovice:你能告诉我我错过了什么吗? - 如果不了解更多有关问题的信息,这是不可能的。例如,您遇到的问题是什么?老实说,这听起来像是一个新问题,所以我建议将其作为一个新问题提出。
    • 我能够找到问题并且我已经更新了代码。非常感谢您的帮助。
    猜你喜欢
    • 2015-03-03
    • 1970-01-01
    • 2023-01-24
    • 2018-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-01
    • 1970-01-01
    相关资源
    最近更新 更多