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

Hello, I have an XML file and a Perl script that uses XML::Simple. I am trying to grab a command line parameter, and use it to select a certain section of the XML file for configuration options...


The XML, saved as script.xml:
<config> <profile name="Test"> <dat_file_location>e:\</dat_file_location> <logdir>Test</logdir> <drop_script>n_a</drop_script> <database_type>MSSQL</database_type> <scripts_sql_dlt>blah</scripts_sql_dlt> <TNS-DSN_name>SwissTest</TNS-DSN_name> <db_user>db_builder</db_user> <password>pass</password> <log_file>Test.log</log_file> <single_sql_file>create_db.sql</single_sql_file> <single_dlt_file>blah</single_dlt_file> </profile> <profile name="Live"> <dat_file_location>e:\</dat_file_location> <logdir>Live</logdir> <drop_script>n_a</drop_script> <database_type>MSSQL</database_type> <scripts_sql_dlt>blah</scripts_sql_dlt> <TNS-DSN_name>Live</TNS-DSN_name> <db_user>db_builder</db_user> <password>pass</password> <log_file>Live.log</log_file> <single_sql_file>create_db.sql</single_sql_file> <single_dlt_file>blah</single_dlt_file> </profile> </config>
The code, saved as script.pl:
# Load XML Config file... use XML::Simple; my $config = XMLin(); # Find the right config... # This should be the only commandline argument my $desired_config = $ARGV[0]; # Dump the config file.... use Data::Dumper; print Dumper($config); print $config->{$desired_config}->{database_type};
And calling it as "script.pl Test" I am not able to get it to work...

I have tried all of the following:
print $config->{profile}->{$desired_config}->{database_type}; print "\nTest1\n"; print $config->{profile}->{config}=>$desired_config->{database_type}; print "\nTest2\n"; print $config->{profile}->{config => $desired_config}->{database_type} +; print "\nTest3\n"; # Below is the only one that works.... # It is hardcoded... print $config->{profile}->{Test}->{database_type}; print "\nTest4\n"; print $config->{$desired_config}->{database_type}; print "\nTest5\n"; print $config->{profile}->{$desired_config}->{database_type}; print "\nTest6\n"; print $config->{profile}=>{$desired_config}->{database_type}; print "\nTest7\n";
I need to be able to specify the config from the command line...

Thanks,
amonotod

Replies are listed 'Best First'.
Re: XML::Simple and variable interpolation
by pzbagel (Chaplain) on Oct 17, 2003 at 17:23 UTC

    You almost have it, look at the Dumper output closer, there is another level to your HoHs.

    print $config->{'profile'}{$desired_config}{database_type};

    HTH

    P.S. Your first test should have worked. I cut and pasted it and it worked for me:

    print $config->{profile}->{$desired_config}->{database_type}; print "\nTest1\n";
      No freakin way...! I saved the posted code and data into seperate files, ran them, and they worked. What a bunch of crap.

      So, I renamed the old files, moved the new files into the same place, and they ran.

      Comparing the original with the new, I see no code differences. At all. Line by line, char by char, nothing different. (Not counting comment lines...)

      So, thank you, pzbagel. I appreciate the input...

      amonotod

        Are you by any chance working between a Windows box and a *nix machine? Perhaps you have some nasty \r characters in your original script or XML file. Those tend to cause weirdness especially with parsing and regexes. Try:

        cat -vET <file>

        The \r will show up as ^M at the end of lines before the $ characters(those command-line options cause cat to mark the end of each line with a $).

        HTH

Re: XML::Simple and variable interpolation
by grantm (Parson) on Oct 17, 2003 at 19:52 UTC

    I understand you've got your script working but I just wanted to point out a potential problem with this line:

    my $config = XMLin();

    Calling XMLin() with absolutely no parameters is a bit of a 'red flag'. In your case, you want the XML file to be found automatically, so leaving the first parameter undefined is OK; but you're expecting the <profile> elements to be 'folded' into a hash keyed on the contents of the 'name' attribute. Unfortunately, if config file is edited and there's only one <profile> element in it, things will go horribly wrong. I'd recommend:

    my $config = XMLin(undef, keyattr => { profile => 'name'}, forcearray => [ 'profile' ], );

    Read more here.

      Hi Grant!

      With you being the author of the module, I'm most happy to take your advice. Even though there will be far more than two profiles in the config file, I see your point.

      Now, I have one more question for you: What is the datatype for the $config variable? It was kicking my ass till I figured out how to apply your example from the XML-mail list on Activestate about UUIDs..

      Thanks!
      amonotod

        What is the datatype for the $config variable?

        $config is a scalar (obviously) and contains a reference to a hash*. Hence when you dereference it, you use the arrow notation with curly braces around the hash key, eg: $config->{profile}->{Live}->{dat_file_location}

        Unlike the DOM modules, XML::Simple sticks to the basic Perl data structures so the individual nodes are not objects and therefore have no methods.

        _____
        *There is an obscure condition in which XMLin() would return an array reference, but you're unlikely to happen across that by accident unless you generate your XML by passing XMLout an arrayref.