How can I extract and save values from an XML file in Perl?
Here is what I am trying to do in a Perl script:
开发者_StackOverflow$data=""; sub loadXMLConfig() { $filename="somexml.xml" $data = $xml->XMLin($filename); } sub GetVariable() { ($FriendlyName) = @_; switch($FriendlyName) { case "My Friendly Name" {print $data->{my_xml_tag_name}} .... .... .... } }
The problem is I am using Perl just because I am reading from an XML file, but I need to get these variables by a shell script. So, here is what I am using:
$ perl -e 'require "scrpt.pl"; loadConfigFile(); GetVariable("My Variable")'
This works exactly as expected, but I need to read the XML file every time I am getting a variable. Is there a way I could "preserve" $data
across shell calls? The idea is that I read the XML file only once. If no, is there is a more simple way I could do this? These are the things I can't change:
- Config File is an XML
- Need the variables in a shell script
When I need some information, retrieved by Perl, in a shell script, I generate shell script by Perl and set environment variables via eval
:
myscript
#!/bin/bash
BINDIR=`dirname $0`
CONFIG=$BINDIR/config.xml
eval `$BINDIR/readcfg $CONFIG`
echo Running on the $planet near the $star.
readcfg
#!/usr/bin/perl
use XML::Simple;
my $xml = XMLin('config.xml', VarAttr => 'name', ContentKey => '-content');
while (my ($k, $v) = each %{$xml->{param}}) {
$v =~ s/'/'"'"'/g;
$v = "'$v'";
print "export $k=$v\n";
}
config.xml
<config>
<param name="star">Sun</param>
<param name="planet">Earth</param>
</config>
You can do this in two steps. You want to create a stored Perl data structure if you haven't done so already, and when you have, you the stored version so you don't have to parse it again.
There are may ways to accomplish this, but here's a version using Storable:
use Storable qw(nstore retrieve);
my $stored_data_structure = 'some_file_name';
my $data = do {
# from the stored data structure if it is there
if( -e $stored_data_structure ) {
retrieve( $stored_data_structure );
}
# otherwise parse the xml and store it
else {
my $data = $xml->XMLin( $xml_filename );
nstore( $data, $stored_data_structure );
$data;
}
};
You might also consider inverting your concept. Instead of a shell script that calls your Perl script, have your Perl script call your shell script:
# load the data, as before
# set some environment variables
$ENV{SomeThing} = $data->{SomeThing};
# now that the environment is set up
# turn into the shell script
exec '/bin/bash', 'script_name'
You can simply store the values in shell-executable file. assuming bourne shell (sh) script and that you know beforehand a list of variable names that interest you:
$data="";
sub loadXMLConfig()
{
$filename="somexml.xml"
$data = $xml->XMLin($filename);
}
sub GetVariable()
{
($FriendlyName) = @_;
switch($FriendlyName)
{
case "My Friendly Name" {
print "$FriendlyName='$data->{my_xml_tag_name}'; export $FriendlyName\n"
} # Use "export var=value" form for bash
....
....
....
}
}
sub storeVariables {
# @variables list defined elsewhere - this is just a sketch
foreach my $variable (@variables) {
GetVariable($variable);
}
}
And then call as follows:
$ perl -e 'require "scrpt.pl"; loadConfigFile(); storeVariables();' > my_vars.sh
$ source my_vars.sh
And the my_vars.sh can be sourced many many times
精彩评论