Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Anyway I can avoid putting "print" in from of all my cgi html data? There must be a way to use print just once and still get the html to work?
print "Content-type: text/html\n\n"; print "<html><head><title>Page title</title></head>\n"; print "<body bgcolor=\"white\">\n"; more print statements.....

Replies are listed 'Best First'.
Re: print content in cgi and html
by ColtsFoot (Chaplain) on Sep 26, 2003 at 13:07 UTC
    If you want to output a lot of HTML but not use CGI.pm
    (which you really should). You can use what is known as a
    HERE document.
    print <<KEEP_PRINTING_UNTIL_REACHING_THIS_STRING; <TABLE> <TR> <TD> </TD> </TR> <TABLE> KEEP_PRINTING_UNTIL_REACHING_THIS_STRING
    Whatever string you use for "KEEP_PRINTING_UNTIL_REACHING_THIS_STRING"
    must not appear in the output to be printed

    Hope this helps
Re: print content in cgi and html
by LAI (Hermit) on Sep 26, 2003 at 12:49 UTC

    The Best way to do what you're trying to would be to look into the CGI module from CPAN. There are all sorts of nifty subs in that module that make any CGIer's life way easier. For instance (from the docs), here's a "Hello World" page done with the functions from CGI.pm:

    #!/usr/local/bin/perl use CGI qw/:standard/; # load standard CGI routines print header, # create the HTTP header start_html('hello world'), # start the HTML h1('hello world'), # level 1 header end_html; # end the HTML

    And the icing on the cake is that CGI should be already installed in your existing distribution of Perl!

    LAI

    __END__
      I personally find that using CGI's named subroutines almost always is the wrong way to factor code for all but very short CGI scripts for personal use.

      Just because someone respected found a piece of code worth writing does not mean that you should be using it whenever you can.

      For some generalities on the design factors that go into choosing how to integrate HTML and your Perl code together, you can read Re (tilly) 6: Code Critique. For lots more on why templating is generally a better solution when you have a large problem, see Building and Managing Web Sites with the Template Toolkit. Before choosing the templating system for you, I strongly suggest reading perrin's Choosing a Templating System.

Re: print content in cgi and html
by barrd (Canon) on Sep 26, 2003 at 13:20 UTC
    Hi Anonymous Monk,

    TIMTOWTDI

    You can also use "HERE documents", e.g:

    print <<_EOF; <html><head> <title>My page title</title> </head> <body> ... blah blah </body></html> _EOF

    The line containing _EOF must not contain any white space at the beginning or end or it will not work!

    However I would highly recommend looking at a templating system such as the excellent HTML::Template module which will allow you to extract your HTML code from your perl code. This makes both far easier to maintain.

    HTH ~ barrd

      HERE documents are good advice even if you do use CGI.pm, for those situations where the nested function structure that CGI.pm imposes proves to be too unwieldly (for example, constructing a table where you might need a foreach loop to enumerate the elements). Yes, it can always be done with CGI.pm, but sometimes it is easier to look at and manipulate with a simple HERE document.

      If you want your HERE documents to be indented you assign the document to a scalar, and then perform a substitution on leading whitespace for each line.

      The Perl Cookbook provides a couple of good solutions. Here's an adaptation of one version.

      ($html = <<HERE_DOC) =~ s/^[^\S\n]//gm; your text goes here. Notice how indentation doesn't matter because the regexp bound to the HERE doc strips leading whitespace. HERE_DOC print $html;

      This works by substituting any amount of whitespace (space, tab, form feed) at the beginning of the line with "nothing" unless the "whitespace" is a newline character (ie, it preserves newlines). Cool huh?

      Enjoy!

      Dave

      "If I had my life to do over again, I'd be a plumber." -- Albert Einstein

      The line containing _EOF must not contain any white space at the beginning or end or it will not work!

      This isn't true, you can have all the white space you want, as long as it's the same on both ends:

      print <<" _ EOF"; Blah _ EOF

      We're not surrounded, we're in a target-rich environment!
        Hiya jasonk,
        This isn't true, you can have all the white space you want...
        OK, hands up, you're right using the technique you supplied with double quotes, but the example I gave wouldn't have accepted spaces as it wasn't quoted... so it is true.

        Thanks for the poke though. ;)

Re: print content in cgi and html
by svsingh (Priest) on Sep 26, 2003 at 13:09 UTC
    Try HERE documents. I haven't used them to print the Content-type line in my scripts, but I would expect them to work for that as well. They're great for short blocks of HTML code.
    print <<HEAD; <html><head><title>Page title</title></head> <body bgcolor="white"> HEAD # create the page print <<FOOT; </body></html> FOOT
Re: print content in cgi and html
by Roger (Parson) on Sep 26, 2003 at 13:21 UTC
    I agree that the best way is to use the CGI module from CPAN. However if you only want your code to look tidy quickly, there are many ways -

    Method 1 - Using qq{ ... }
    print qq{Content-type: text/html <html><head>.....</head> <body bgcolor="white"> ..... </body> ..... </html> };
    Method 2 - Using HEREDOC
    print <<HTML Content-type: text/html <html><head>.....</head> <body bgcolor="white"> ..... </body> ..... $variable_text </html> HTML
    Note that you can get rid of the \n from the end of every line, and you can embed variables in them too.

      I have conditions in my html cgi output. How would I handle that?
      if($condition) { print <<HTML Content-type: text/html <html><head>.....</head> <body bgcolor="white"> if($variable == 1) { print $anotherVariable; } </body> </html> HTML }
        Use multi HERE Documents like:

        if ($condition) { print <<HTML Content-type: text/html <html><head>.....</head> <body bgcolor="white"> ... blah blah HTML if ($variable == 1) { print $anotherVariable; } print <<HTML ... blah blah </body></html> HTML }

        Or as I mentioned before use HTML::Template, it can handle all that for you too... go on try it, you know you want to. ;)