BC0148 BC0148 - 6 months ago 10
Perl Question

How to render an HTML table properly in a perl CGI file

So i am using perl CGI to create a table from arrays in my perl code. i also have HTML implemented in my perl file. I have the content printing out on the browser, but its printing on top of the HTML part of the web page. I want it to be lower so it will display in the actual HTML part of the .pl file. For a better understanding i will post a screenshot of how it loads on the browser.

enter image description here

Here is my perl code which prints out this data..

#!/usr/bin/perl -w

use CGI qw/:standard/;
use strict;
use warnings;
use JSON qw( decode_json );
use LWP::Simple 'get';
use Data::Dumper;

print "content-type:text/html; charset=utf-8\n\n";

my @sessionArr;
my @classArr;
my @timeArr;
my @adminArr;
my @profArr;
my @descArr;

my $i = 0;

my $myURL = "leaving URL out";

my $json = get($myURL);
die "Could not get $myURL!" unless defined $json;

my $decoded_json = decode_json ($json);

my @sessionID = @{ $decoded_json->{'items'} };
foreach my $d ( @sessionID ) {
$sessionArr[$i] = $d->{"sessionID"};
$i = $i + 1;
}

$i = 0;

my @class = @{ $decoded_json->{'items'} };
foreach my $d ( @class ) {
$classArr[$i] = $d->{"classField"};
$i = $i + 1;
}

$i = 0;


my @time = @{ $decoded_json->{'items'} };
foreach my $d ( @time ) {
$timeArr[$i] = $d->{"startTimeField"};
$i = $i + 1;
}

$i = 0;

my @usrcreater = @{ $decoded_json->{'items'} };
foreach my $d ( @usrcreater ) {
$adminArr[$i] = $d->{"leader"};
$i = $i + 1;
}

$i = 0;

my @professor = @{ $decoded_json->{'items'} };
foreach my $d ( @professor ) {
$profArr[$i] = $d->{"professorField"};
$i = $i + 1;
}

$i = 0;




my @description = @{ $decoded_json->{'items'} };
foreach my $d ( @description ) {
$descArr[$i] = $d->{"descriptionField"};
$i = $i + 1;
}

$i = 0;

foreach my $p ( @description ) {
$i = $i +1;
}

foreach my $i (0..$#sessionArr) {
print "<tr>\n";
print " ";
foreach my $ra (\@sessionArr, \@classArr, \@timeArr, \@adminArr, \@profArr, \@descArr) {
print "<td>$ra->[$i]</td>\n"
}
print "<h2></tr></h2>\n";
}


print qq(<!DOCTYPE html><head></head><body>


<head>

<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<title>AU Study Sessions</title>

<link href="../css/bootstrap.css" rel="stylesheet">

<link href="../css/main.css" rel="stylesheet">

<!--[if lt IE 9]>
<script src="js/html5shiv.js"></script>
<script src="js/respond.min.js"></script>
<![endif]-->

<link rel="shortcut icon" href="../images/favicon.png">
<script src="../js/pace.js"></script>

<link href='http://fonts.googleapis.com/css?family=Open+Sans:300,600' rel='stylesheet' type='text/css'>
</head>

<body>
<div class="preloader"></div>

<! -- ******************** MASTHEAD SECTION ******************** -->
<main id="top" class="masthead" role="main">
<div class="container">
<div class="logo"> <a href="http://a3jjddh.com/"><img src="../images/aulogo2.png" alt="logo"></a>
</div>

<h1>View Study Sessions</h1>

<table>
<-- *****This is where i want my table to be displayed -->


</table>


<br>
<br>
<a href="http://website.com"> Add a Study Session</a>

<!--<a href="index.html#explore" class="scrollto">
<p>SCROLL DOWN TO EXPLORE</p>
<p class="scrollto--arrow"><img src="../images/scroll_down.png" alt="scroll down arrow"></p>
</a> -->
</div><! --/container -->
</main><! --/main -->


<! -- ******************** FOOTER SECTION ******************** -->
<div class="container" id="explore">



<div class="section-title">
<h2>With Adelphi Study Sessions Website</h2>
<h4>You will be able to do the following</h4>
</div>

<section class="row features">
<div class="col-sm-6 col-md-3">
<div class="thumbnail">
<img src="../images/service_01.png" alt="analytics-icon">
<div class="caption">
<h3>View Study Groups</h3>
<p>See the most up to date study sessions taking place on our garden city campus.</p>
</div>
</div><! --/thumbnail -->
</div><! --/col-sm-6-->

<div class="col-sm-6 col-md-3">
<div class="thumbnail">
<img src="../images/service_02.png" alt="analytics-icon">
<div class="caption">
<h3>Add and create new study sessions</h3>
<p>If you or some classmates want to create a new study session you will be able to add a new group along with course information, sudy topics, and time and location taking place.</p>
</div>
</div><! --/thumbnail -->
</div><! --/col-sm-6-->

<div class="col-sm-6 col-md-3">
<div class="thumbnail">
<img src="../images/service_03.png" alt="analytics-icon">
<div class="caption">
<h3>See description of session</h3>
<p>The student who creates the study session will give a short description about what the study session will cover.</p>
</div>
</div><! --/thumbnail -->
</div><! --/col-sm-6-->

<div class="col-sm-6 col-md-3">
<div class="thumbnail">
<img src="../images/service_04.png" alt="analytics-icon">
<div class="caption">
<h3>Available on campus</h3>
<p>All study sessions will take place on our Garden City campus therefore are available to all students who commute or live on campus.</p>
</div>
</div><! --/thumbnail -->
</div><! --/col-sm-6-->
</section><! --/section -->







<script src="../js/jquery.js"></script>
<script src="../js/bootstrap.js"></script>
<script src="../js/easing.js"></script>
<script src="../js/nicescroll.js"></script>


</body>);

Answer

Here's a rewrite that uses Template Toolkit ("TT") to build the HTML page and include the data from your JSON

There are many problems with your original HTML. Tags are unbalanced, and you have head-only elements within the body. I can't guarantee that this fixes everything but I can't spot any more errors. You should be careful to keep your HTML indented so that you can more easily spot unbalanced tags. It also obviates the need to comment the closing tags

I've included a block of code that shows you how to more easily extract arrays of the same field from each of a list of hashes. The variables aren't used, so please delete that code once you've understood the lesson

The templates for Template Toolkit are normally held in separate .tt files. In this case I've used the DATA file handle as it's more in keeping with the way you wrote your original code. But bear in mind that a TT template may contain include statements that refer to other separate files. For instance you could put your footer section in an external file and then [% INCLUDE footer.tt %] in your main template. But that is for the future

Note that Template Toolkit allows you to access Perl data structures directly. Anything that the template needs to use must be passed in the second parameter of the process methods call. In this case I have passed { json => $decoded_json } so that TT can now use the json identifier to refer to the hash that you have downloaded. Within the template, json.items is now the array of data (accessible as json.items.0, json.items.1 etc.) and here I have written [% FOREACH item IN json.items %] which declares a new TT variable item and assigns it to each element of the items array in turn

I hope all of that is clear

#!/usr/bin/perl

use utf8;
use strict;
use warnings qw/ all FATAL /;

use CGI qw/:standard/;
use JSON qw( decode_json );
use LWP;
use Template;

use Data::Dumper; 

use constant JSON_URL => 'http://example.com/json';

### This code uses a literal JSON data item. The live code should
### fetch the real data from the JSON_URL. The code to do this
### is here but has been commented out

=comment
my $json = do {
    my $ua = LWP::UserAgent->new;
    my $resp = $ua->get(JSON_URL);
    unless ( $resp->is_success ) {
        die sprintf "Could not retrieve JSON data: %s", $resp->status_line;
    }
    $resp->decoded_content;
};
=cut

my $json = <<END;
{
    "items": [
        {
            "sessionID":        "session1",
            "classField":       "class1",
            "startTimeField":   "start1",
            "leader":           "leader1",
            "professorField":   "prof1",
            "descriptionField": "desc1"
        },
        {
            "sessionID":        "session2",
            "classField":       "class2",
            "startTimeField":   "start2",
            "leader":           "leader2",
            "professorField":   "prof2",
            "descriptionField": "desc2"
        }
    ]
}
END

my $decoded_json = decode_json($json);


### Note that these variables are unused. This is just an example
### of a better way to extract a list of values from an array of hashes
### Please remove this code before deploying

my $items = $decoded_json->{items};

my @sessionArr = map { $_->{sessionID} } @$items;
my @classArr   = map { $_->{classField} } @$items;
my @timeArr    = map { $_->{startTimeField} } @$items;
my @adminArr   = map { $_->{leader} } @$items;
my @profArr    = map { $_->{professorField} } @$items;
my @descArr    = map { $_->{descriptionField} } @$items;

### All that needs to be done its to use CGI to print the HTTP
### header and invoke Template Toolkit to build an HTML page that
### includes the data from the JSON hash

print CGI->header(
    -type    => 'text/html',
    -charset => 'utf-8',
);

my $tt = Template->new;

$tt->process(\*DATA, { json => $decoded_json } );

__DATA__
<!DOCTYPE html>
<head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="">
    <title>AU Study Sessions</title>

    <link href="../css/bootstrap.css" rel="stylesheet">

    <link href="../css/main.css" rel="stylesheet">

    <!--[if lt IE 9]>
      <script src="js/html5shiv.js"></script>
      <script src="js/respond.min.js"></script>
    <![endif]-->

    <link rel="shortcut icon" href="../images/favicon.png">
    <script src="../js/pace.js"></script>

    <link href='http://fonts.googleapis.com/css?family=Open+Sans:300,600' rel='stylesheet' type='text/css'>

</head>

<body>

    <div class="preloader"></div>

    <!-- ******************** MASTHEAD SECTION ******************* -->

    <main id="top" class="masthead" role="main">
        <div class="container">
            <div class="logo">
                <a href=""><img src="../images/aulogo2.png" alt="logo"></a>
            </div>

            <h1>View Study Sessions</h1>);

            <table>

            [% FOREACH item IN json.items %]
            <tr>
                <td>[% item.sessionID %]</td>
                <td>[% item.classField %]</td>
                <td>[% item.startTimeField %]</td>
                <td>[% item.leader %]</td>
                <td>[% item.professorField %]</td>
                <td>[% item.descriptionField %]</td>
            </tr>
            [% END %]

            <br/>
            <br/>

            <a href=""> Add a Study Session</a>

            <!--
            <a href="index.html#explore" class="scrollto">
                <p>SCROLL DOWN TO EXPLORE</p>
                <p class="scrollto--arrow"><img src="../images/scroll_down.png" alt="scroll down arrow"></p>
            </a>
            -->

        </div> <!-- class="container" -->
    </main>

    <!-- ******************** FOOTER SECTION ******************** -->  

    <div class="container" id="explore">

        <div class="section-title">
            <h2>With Adelphi Study Sessions Website</h2>
            <h4>You will be able to do the following</h4>
        </div>

        <section class="row features">

            <div class="col-sm-6 col-md-3">
                <div class="thumbnail"> 
                    <img src="../images/service_01.png" alt="analytics-icon">
                    <div class="caption">
                        <h3>View Study Groups</h3>
                        <p>See the most up to date study sessions taking place on our garden city campus.</p>
                    </div>
                </div>
            </div>

            <div class="col-sm-6 col-md-3">
                <div class="thumbnail"> 
                    <img src="../images/service_02.png" alt="analytics-icon">
                    <div class="caption">
                        <h3>Add and create new study sessions</h3>
                        <p>If you or some classmates want to create a new study session you will be able to add a new group along with course information, sudy topics, and time and location taking place.</p>
                    </div>
                </div>
            </div>

            <div class="col-sm-6 col-md-3">
                <div class="thumbnail"> 
                    <img src="../images/service_03.png" alt="analytics-icon">
                    <div class="caption">
                        <h3>See description of session</h3>
                        <p>The student who creates the study session will give a short description about what the study session will cover.</p>
                    </div>
                </div>
            </div>

            <div class="col-sm-6 col-md-3">
                <div class="thumbnail"> 
                    <img src="../images/service_04.png" alt="analytics-icon">
                    <div class="caption">
                        <h3>Available on campus</h3>
                        <p>All study sessions will take place on our Garden City campus therefore are available to all students who commute or live on campus.</p>
                    </div>
                </div>
            </div>

        </section>

        <script src="../js/jquery.js"></script>
        <script src="../js/bootstrap.js"></script>
        <script src="../js/easing.js"></script>
        <script src="../js/nicescroll.js"></script>

    </div> <!-- class="container" id="explore" -->

</body>

</html>

output

Content-Type: text/html; charset=utf-8

<!DOCTYPE html>
<head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="">
    <title>AU Study Sessions</title>

    <link href="../css/bootstrap.css" rel="stylesheet">

    <link href="../css/main.css" rel="stylesheet">

    <!--[if lt IE 9]>
      <script src="js/html5shiv.js"></script>
      <script src="js/respond.min.js"></script>
    <![endif]-->

    <link rel="shortcut icon" href="../images/favicon.png">
    <script src="../js/pace.js"></script>

    <link href='http://fonts.googleapis.com/css?family=Open+Sans:300,600' rel='stylesheet' type='text/css'>

</head>
<body>

    <div class="preloader"></div>

    <!-- ******************** MASTHEAD SECTION ******************* -->

    <main id="top" class="masthead" role="main">
        <div class="container">
            <div class="logo">
                <a href=""><img src="../images/aulogo2.png" alt="logo"></a>
            </div>

            <h1>View Study Sessions</h1>);

            <table>


            <tr>
                <td>session1</td>
                <td>class1</td>
                <td>start1</td>
                <td>leader1</td>
                <td>prof1</td>
                <td>desc1</td>
            </tr>

            <tr>
                <td>session2</td>
                <td>class2</td>
                <td>start2</td>
                <td>leader2</td>
                <td>prof2</td>
                <td>desc2</td>
            </tr>


            <br/>
            <br/>

            <a href=""> Add a Study Session</a>

            <!--<a href="index.html#explore" class="scrollto">
            <p>SCROLL DOWN TO EXPLORE</p>
            <p class="scrollto--arrow"><img src="../images/scroll_down.png" alt="scroll down arrow"></p>
            </a> -->

        </div>
    </main>


    <!-- ******************** FOOTER SECTION ******************** -->  
    <div class="container" id="explore">
        <div class="section-title">
            <h2>With Adelphi Study Sessions Website</h2>
            <h4>You will be able to do the following</h4>
        </div>

        <section class="row features">
            <div class="col-sm-6 col-md-3">
                <div class="thumbnail"> 
                    <img src="../images/service_01.png" alt="analytics-icon">
                    <div class="caption">
                        <h3>View Study Groups</h3>
                        <p>See the most up to date study sessions taking place on our garden city campus.</p>
                    </div>
                </div><! --/thumbnail -->
            </div><! --/col-sm-6-->

            <div class="col-sm-6 col-md-3">
                <div class="thumbnail"> 
                    <img src="../images/service_02.png" alt="analytics-icon">
                    <div class="caption">
                        <h3>Add and create new study sessions</h3>
                        <p>If you or some classmates want to create a new study session you will be able to add a new group along with course information, sudy topics, and time and location taking place.</p>
                    </div>
                </div><! --/thumbnail -->
            </div><! --/col-sm-6-->

            <div class="col-sm-6 col-md-3">
                <div class="thumbnail"> 
                    <img src="../images/service_03.png" alt="analytics-icon">
                    <div class="caption">
                        <h3>See description of session</h3>
                        <p>The student who creates the study session will give a short description about what the study session will cover.</p>
                    </div>
                </div><! --/thumbnail -->
            </div><! --/col-sm-6-->

            <div class="col-sm-6 col-md-3">
                <div class="thumbnail"> 
                    <img src="../images/service_04.png" alt="analytics-icon">
                    <div class="caption">
                        <h3>Available on campus</h3>
                        <p>All study sessions will take place on our Garden City campus therefore are available to all students who commute or live on campus.</p>
                    </div>
                </div><! --/thumbnail -->
            </div><! --/col-sm-6-->
        </section><! --/section -->

        <script src="../js/jquery.js"></script>
        <script src="../js/bootstrap.js"></script>
        <script src="../js/easing.js"></script>
        <script src="../js/nicescroll.js"></script> 

    </body>

</html>
Comments