简体   繁体   中英

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:

$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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM