Отображение HTML в теге Perl

#html #perl

Вопрос:

У меня есть скрипт 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 введите описание изображения здесь

Комментарии:

1. Похоже, вам нужно что-то вроде HTML::Escape или HTML::Сущности .

2. О, и всегда use strict; use warnings; в сценариях perl.

3. Это модуль, который необходимо установить? Увидел эту ошибку, когда попытался использовать ее Ошибка PerlScript: Не удается найти HTML/Escape.pm в @INC (@INC содержит: D:/Perl32/site/lib D:/Perl32/lib .)

4. Вот что я добавил. используйте HTML::Escape qw/escape_html/; escape_html(«<,>»)

5. Образец сгенерированного HTML , добавленный к вашему вопросу, может быть полезен. Я заметил несколько несоответствий: 1. переменные $host,$user,$pass,$driver содержат значения в одинарных кавычках, интерполяция не выполняется, 2. в цикле $Count , но никогда не используется, 3. $Output = "$Output$Temp"; лучше писать $Output .= $Temp; , Обратите внимание: есть лучшие способы формирования вывода HTML в переменной, что улучшает читаемость/упрощает обслуживание кода.

Ответ №1:

Следующий фрагмент кода демонстрирует слегка измененную версию опубликованного кода.

Пожалуйста, ознакомьтесь с разделом цикла для 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:Perl32scriptsUndeliveredRAW.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 .= "nt<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, заголовок, заголовок, текст

Ссылка:

Ответ №2:

HTML имеет хорошо понятный механизм включения символов, которые обычно интерпретируются как специальные символы. Например, если вы хотите включить a < в свой HTML, это обычно будет рассматриваться как начало нового HTML-элемента в вашем документе.

Решение состоит в том, чтобы заменить эти проблемные символы сущностями HTML, которые представляют эти символы. Например, < следует заменить на amp;< . Обратите внимание, что это означает, что амперсанд ( amp; ) необходимо добавить в набор символов, которые следует заменить (в данном случае amp;amp; ), если вы хотите включить его в свой HTML.

Perl имеет долгую историю использования в Интернете, поэтому неудивительно, что для выполнения этой замены доступно множество инструментов. HTML::Escape, вероятно, самый известный. Он предоставляет единственную функцию ( escape_html() ), которая принимает текстовую строку и возвращает ту же строку со всеми проблемными символами, замененными соответствующими сущностями.

 use HTML::Escape 'escape_html';

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

После запуска этого кода $escaped_html теперь содержит «$<некоторый текст$> $amp; $<некоторый другой текст$>». И если вы отправите этот текст в браузер, вы получите правильный вывод.

Поэтому самое простое решение-загрузить 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 на работе (что здорово), но очень жаль, что вы изучаете его в среде, которая, похоже, использует методы, которые устарели примерно на двадцать лет. Ваш вопрос-хороший пример того, почему попытка создать необработанные HTML-строки внутри вашего кода Perl-плохая идея. Гораздо лучше использовать какой-либо механизм создания шаблонов (стандартом defacto в мире Perl, по-видимому, является набор инструментов шаблонов).

Я также рекомендую взглянуть на каскадные таблицы стилей как на более современный подход к стилизации вывода HTML.

Комментарии:

1. Большое тебе спасибо, Дэйв, за твое подробное объяснение. У меня был последний вопрос. Мне нужно добавить еще один идентификатор столбца в вывод. Этот столбец не нуждается в какой-либо функции escape. Я добавляю идентификатор в цикл while, однако возникли проблемы. Можете ли вы сообщить мне, чего мне не хватает?

2. @SQLNovice: Не могли бы вы сообщить мне, чего мне не хватает? — Это невозможно, не зная гораздо больше об этой проблеме. Например, какие у вас проблемы? Честно говоря, это звучит как новая проблема, поэтому я рекомендую задать ее как новый вопрос.

3. Мне удалось найти проблему, и я обновил код. Большое вам спасибо за вашу помощь.