Using HTML::Template to add a tag

163 Views Asked by At

I'm using CGI and HTML::Template. I need to add below tag in all the templates which contain <form> tag (tag should be added inside <form> tag).

<input type="hidden" value="TO_BE_PARSED_FROM_CGI">

I don't want to edit all the template files manually. Is there any method available in HTML::Template to do this? Some type of hook which I can pass while creating constructor of HTML::Template?

2

There are 2 best solutions below

0
On BEST ANSWER

You don't have to modify all the template files manually. Perl has HTML parsers that can help you locate where the changes need to be made. Go ahead and fix the templates once as opposed to modifying your code to do it each and every time it runs. Below, I use \*DATA for illustrative purposes, but, clearly, the list of template files could come from anywhere.

Back the files up first (better still, make sure you do this in a branch in your version control system).

#!/usr/bin/env perl

use utf8;
use strict;
use warnings;
use open qw[ :std :encoding(UTF-8) ];

use HTML::TokeParser::Simple;

run(\@ARGV);

sub run {
    my $argv = shift;
    my $parser = HTML::TokeParser::Simple->new(handle => \*DATA);

    while (my $token = $parser->get_token) {
        print $token->as_is;
        if ($token->is_start_tag('form')) {
            print qq{\n<input type="hidden" name="sid" value="<TMPL_VAR NAME=SID>">\n};
        }
    }
}

__DATA__
<h3>Here is a form:</h3>

<form
    method="POST"
    action="https://example.com/action-action-action.pl"
    id="action"
    name="actionable_form">

<label for="date">Date:</label>
<input type="date" name="date" id="date">

<input type="submit">

</form>
3
On

Is there any method available in HTML::Template to do this?

This again? ;) No, you need to read and manipulate the DOM to do what you want. HTML::Template only works with it's specific tags/markers. Store $template->output() into a variable. Read the variable with a parser such as Mojo::DOM to find the instances of forms and append your content. This example illustrates a solution:

#!/usr/bin/perl
use strict;
use warnings;
use Mojo::DOM;

# fake output of $template->output;

my $html = << 'HTML';
  <html>
    <head>
      <title>test</title>
    </head>
    <body>
      <form method="post">
        <input type="text" id="name">
      </form>
    </body>
  </html>
HTML

# you say you want to parse this from CGI
my $value ='foo'; 

# what you want to add
my $addme = "<input type='hidden' value='$value'>";

my $dom = Mojo::DOM->new();

$dom->parse( $html )->at('form')->child_nodes->first->append( $addme )->root;
print $dom;

prints:

  <html>
    <head>
          <title>test</title>
        </head>
        <body>
          <form method="post">
            <input type="hidden" value="foo"><input id="name" type="text">
          </form>
        </body>
  </html>

Edit.

Since we don't know what you're doing within your templates the sanest method is to base any changes on the output of your existing code. Meaning that you can safely add the method illustrated to the above before the point were you currently print the output of your template. You could use the code given as a one off update to actually write the change back to your templates, and the value rather than foo could be an HTML::Template param.