There's more going on than what's in the code. An inconsequential alteration (removing the HTML templates, so I can be lazy and not install HTML::Template) works.
Code:
#!/usr/bin/perl -w
#use HTML::Template;
use CGI;
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
use XML::Simple;
use Data::Dumper;
########################
# MUST EDIT FOLOWING #
########################
# path to the data directory
my $dataDir = $ENV{'DOCUMENT_ROOT'} . "/survey/";
########################
# DO NOT EDIT #
########################
my $query = new CGI;
#my $template = HTML::Template->new(filename => 'survey.tmpl', path => $dataDir);
my $XML = new XML::Simple;
my $survey = $query->param('survey') || 'foo';
my $list = $XML->XMLin($dataDir . "/list.xml", KeyAttr => "id");
print <<EOS ;
Content-Type: text/html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title></title>
<style type="text/css">
pre {
padding: 0.5em;
border: 1px solid black;
}
</style>
</head>
<body>
EOS
if (exists $list->{survey}->{$survey}) {
my $surveyMetaData = $list->{survey}->{$survey};
my $surveyData = $XML->XMLin($dataDir . "/" . $surveyMetaData->{file} . ".xml", KeyAttr => "id");
print 'survey.xml:<pre>', Dumper($list), '</pre>';
print 'survey meta data:<pre>', Dumper($surveyMetaData), '</pre>';
print "survey data (from <a href='/survey/$surveyMetaData->{file}.xml'>$surveyMetaData->{file}.xml</a>):<pre>", Dumper($surveyData), '</pre>';
} else {
#$template->param(TITLE => 'ERROR', CONTENT => 'ERROR (0x0): Undefined survey ID.');
#print "Content-Type: text/html\n\n", $template->output;
print "<p>Error: undefined survey '$survey'.</p>";
}
print <<EOS ;
</body>
</html>
EOS
Check that the elusive <survey> element in list.xml isn't missing any child elements or attributes.