I'm trying to output some data into an html table with this code:
print "\n";
for my $array ( @sorted ) {
print "<tr>";
for my $element ( @$array ) {
print "<td>" . $element . "</td>";
}
print "</tr>";
print "\n";
}
However after successfully outputting several rows it sometimes
randomly throws in a row like this:
<tr><td>CY</td><td>2.4321</td><td>16.79</td><td!>+0.04</td></tr>
where one of the <td> tags is instead <td!> which is clearly wrong.
It is also clearly impossible unless the "<td!>" is included in the
data. For example, if
@sorted = (
[ 'CY', 2.4321, '16.79</td><td!>+0.04' ],
);
your code will print the line above.
First, wenn producing HTML, always escape any data. Instead of
print "<td>" . $element . "</td>";
use
print "<td>" . html_escape($element) . "</td>";
...
sub html_escape {
my $s = @_;
$s =~ s/&/&/;
$s =~ s/</</;
$s =~ s/>/>/; # only for symmetry
$s =~ s/"/&dquot;/; # only needed in attributes
$s =~ s/'/'/; # only needed in attributes
return $s;
}
For the same data in @sorted this would produce:
<tr><td>CY</td><td>2.4321</td><td>16.79</td><td!>+0.04</td></tr>
which makes it easy to spot the error. It also makes
cross-site-scripting attacks a lot harder.
Second, I've found it helpful to insert debug output in comments, for
example, something like:
my $row = 0;
for my $array ( @sorted ) {
print "<!-- row $row -->";
print "<tr>";
my $col = 0;
for my $element ( @$array ) {
print "<!-- col $col: $element -->";
print "<td>" . $element . "</td>";
$col++;
}
print "</tr>";
print "\n";
$row++;
}
makes it easier so see where the error occurs. This helps you to collect
data for a test case.
Finally, try to make the error reproducable. If something happens
"randomly", it often only means that you haven't found the cause yet.
Trim down your code to the minimal code which still exhibits the
behaviour. Don't get your data from sources which may change from one
run of your program to the next (e.g., websites, log files, etc.). Get
it from sample files or enter it directly into your program.
hp