1

I am struggling with the following declaration of a hash in Perl:

my %xmlStructure = {
            hostname    =>  $dbHost,
            username    =>  $dbUsername,
            password    =>  $dbPassword,
            dev_table   =>  $dbTable,
            octopus     =>  {
                                alert_dir       =>  $alert_dir,
                                broadcast_id    =>  $broadcast_id,
                                system_id       =>  $system_id,
                                subkey          =>  $subkey
                            }
 };

I've been googling, but I haven't been able to come up with a solution, and every modification I make ends up in another warning or in results that I do not want.

Perl complaints with the following text:

Reference found where even-sized list expected at ./configurator.pl line X.

I am doing it that way, since I want to use the module:

XML::Simple

In order to generate a XML file with the following structure:

 <settings>
  <username></username>
  <password></password>
  <database></database>
  <hostname></hostname>

  <dev_table></dev_table>

  <octopus>
      <alert_dir></alert_dir>
      <broadcast_id></broadcast_id>
      <subkey></subkey>
  </octopus>
 </settings>

so sometthing like:

my $data = $xmlFile->XMLout(%xmlStructure);
warn Dumper($data);

would display the latter xml sample structure.

Update:

I forgot to mention that I also tried using parenthesis instead of curly braces for the hash reference, and eventhough it seems to work, the XML file is not written properly: I end up with the following structure:

<settings>

 <dev_table>5L3IQWmNOw==</dev_table>
 <hostname>gQMgO3/hvMjc</hostname>

 <octopus>
  <alert_dir>l</alert_dir>
  <broadcast_id>l</broadcast_id>
  <subkey>l</subkey>
  <system_id>l</system_id>
 </octopus>

 <password>dZJomteHXg==</password>
 <username>sjfPIQ==</username>

</settings>

Which is not exactly wrong, but I'm not sure if I'm going to have problems latter on as the XML file grows bigger. The credentials are encrypted using RC4 algorith, but I am encoding in base 64 to avoid any misbehavior with special characters. Thanks

ILikeTacos
  • 17,464
  • 20
  • 58
  • 88

3 Answers3

13

{} are used for hash references. To declare a hash use normal parentheses ():

my %xmlStructure = (
            hostname    =>  $dbHost,
            username    =>  $dbUsername,
            password    =>  $dbPassword,
            dev_table   =>  $dbTable,
            octopus     =>  {
                                alert_dir       =>  $alert_dir,
                                broadcast_id    =>  $broadcast_id,
                                system_id       =>  $system_id,
                                subkey          =>  $subkey
                            }
 );

See also perldoc perldsc - Perl Data Structures Cookbook.

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
dgw
  • 13,418
  • 11
  • 56
  • 54
4

You're using the curly braces { ... } to construct a reference to an anonymous hash. You should either assign that to a scalar, or change the { ... } to standard parentheses ( ... ).

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
Aquatoad
  • 778
  • 8
  • 21
4

For your second issue, you should keep in mind that XML::Simple is indeed too simple for most applications. If you need a specific layout, you're better off with a different way of producing the XML, say, using HTML::Template. For example (I quoted variable names for illustrative purposes):

#!/usr/bin/env perl

use strict; use warnings;
use HTML::Template;

my $tmpl = HTML::Template->new(filehandle => \*DATA);
$tmpl->param(
    hostname    =>  '$dbHost',
    username    =>  '$dbUsername',
    password    =>  '$dbPassword',
    dev_table   =>  '$dbTable',
    octopus     =>  [
        {
            alert_dir       =>  '$alert_dir',
            broadcast_id    =>  '$broadcast_id',
            system_id       =>  '$system_id',
            subkey          =>  '$subkey',
        }
    ]
);

print $tmpl->output;

__DATA__
<settings>
  <username><TMPL_VAR username></username>
  <password><TMPL_VAR password></password>
  <database><TMPL_VAR database></database>
  <hostname><TMPL_VAR hostname></hostname>

  <dev_table><TMPL_VAR dev_table></dev_table>

  <octopus><TMPL_LOOP octopus>
    <alert_dir><TMPL_VAR alert_dir></alert_dir>
    <broadcast_id><TMPL_VAR broadcast_id></broadcast_id>
    <subkey><TMPL_VAR subkey></subkey>
    <system_id><TMPL_VAR system_id></system_id>
  </TMPL_LOOP></octopus>
</settings>

Output:

<settings>
  <username>$dbUsername</username>
  <password>$dbPassword</password>
  <database></database>
  <hostname>$dbHost</hostname>

  <dev_table>$dbTable</dev_table>

  <octopus>
    <alert_dir>$alert_dir</alert_dir>
    <broadcast_id>$broadcast_id</broadcast_id>
    <subkey>$subkey</subkey>
    <system_id>$system_id</system_id>
  </octopus>
</settings>
Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
  • Thank you! I am quite new to Perl, and I am not aware of this kind of libraries. This one did the job exactly the way I wanted. – ILikeTacos May 03 '12 at 21:10