2

I was wondering if you could shed some lights regarding the code I've been doing for a couple of days.

I've been trying to convert a Perl-parsed hash back to XML using the XMLout() and XMLin() method and it has been quite successful with this format.

#!/usr/bin/perl -w
use strict;

# use module
use IO::File;
use XML::Simple;
use XML::Dumper;
use Data::Dumper;
my $dump = new XML::Dumper;

my ( $data, $VAR1 );

Topology:$VAR1 = {  
   'device' => {  
    'FOC1047Z2SZ' => {  
      'ChassisID' => '2009-09',  
      'Error' => undef,  
      'Group' => {  
        'ID' => 'A1',  
        'Type' => 'Base'  
      },  
      'Model' => 'CATALYST',  
      'Name' => 'CISCO-SW1',  
      'Neighbor' => {},  
      'ProbedIP' => 'TEST',  
      'isDerived' => 0  
    }  
  },  
  'issues' => [  
    'TEST'  
  ]  
};  

# create object  
my $xml = new XML::Simple (NoAttr=>1,  
                           RootName=>'data',     
                           SuppressEmpty => 'true');  

# convert Perl array ref into XML document  
$data = $xml->XMLout($VAR1);  

#reads an XML file  
my $X_out = $xml->XMLin($data);  

# access XML data  
print Dumper($data);  
print "STATUS: $X_out->{issues}\n";  
print "CHASSIS ID: $X_out->{device}{ChassisID}\n";  
print "GROUP ID: $X_out->{device}{Group}{ID}\n";  
print "DEVICE NAME: $X_out->{device}{Name}\n";  
print "DEVICE NAME: $X_out->{device}{name}\n";  
print "ERROR: $X_out->{device}{error}\n";  

I can access all the element in the XML with no problem.

But when I try to create a file that will house the parsed hash, problem arises because I can't seem to access all the XML elements. I guess, I wasn't able to unparse the file with the following code.

#!/usr/bin/perl -w
use strict;
#!/usr/bin/perl

# use module
use IO::File;  
use XML::Simple;  
use XML::Dumper;  
use Data::Dumper;  
my $dump = new XML::Dumper;  

my ( $data, $VAR1, $line_Holder );

#this is the file that contains the parsed hash  
my $saveOut = "C:/parsed_hash.txt";  
my $result_Holder = IO::File->new($saveOut, 'r');  
while ($line_Holder = $result_Holder->getline){  
    print $line_Holder;  
}  

# create object  
my $xml = new XML::Simple (NoAttr=>1, RootName=>'data', SuppressEmpty => 'true');  
# convert Perl array ref into XML document  
$data = $xml->XMLout($line_Holder);  
#reads an XML file  
my $X_out = $xml->XMLin($data);  

# access XML data  
print Dumper($data);  
print "STATUS: $X_out->{issues}\n";  
print "CHASSIS ID: $X_out->{device}{ChassisID}\n";  
print "GROUP ID: $X_out->{device}{Group}{ID}\n";  
print "DEVICE NAME: $X_out->{device}{Name}\n";  
print "DEVICE NAME: $X_out->{device}{name}\n";  
print "ERROR: $X_out->{device}{error}\n";  

Do you have any idea how I could access the $VAR1 inside the text file?

Regards,
newbee_me

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
newbee_me
  • 31
  • 1
  • 1
  • 3
  • Please edit you post and put all code section as such for better readability – Dror Jun 17 '09 at 07:29
  • Your initial code (the one that's supposed to work) has at least a couple of typos in it: $X_out->{device}{name} should be $X_out->{device}{Name} (upper case N, actually the line above has the proper field name), same with the line below, where 'error' should be 'Error' – mirod Jun 17 '09 at 07:52
  • Hi Manni, Yup you are right on this but when i try to pass $VARS1 on the XMLout(), it is giving me the element ... and the though basing from the parsed perl equivalent it is not the same. Thanks for your help! – newbee_me Jun 17 '09 at 09:25

6 Answers6

5
$data = $xml->XMLout($line_Holder); 

$line_Holder has only the last line of your file, not the whole file, and not the perl hashref that would result from evaling the file. Try something like this:

my $ref = do $saveOut;

The do function loads and evals a file for you. You may want to do it in separate steps, like:

use File::Slurp "read_file";
my $fileContents = read_file( $saveOut );
my $ref = eval( $fileContents );
ysth
  • 96,171
  • 6
  • 121
  • 214
  • Thanks for your help ysth, i understand that the $line_Holder only holds the the last line of the file and i was doing some script that will hold all the data from the text file but i can't find a suitable code that has its objective. Glad you gave me that idea on this Slurp. It can now see the parsed perl equivalent, and i can access all of its data using that code. Thank you very much! – newbee_me Jun 17 '09 at 09:21
5

You might want to look at the Data::Dump module as a replacement for Data::Dumper; its output is already ready to re-eval back.

Ricky Morse
  • 458
  • 4
  • 8
  • 2
    +1. Data::Dump is basically Data::Dumper done right. It avoids assignments to $VAR1 etc. and fixes several tricky edge cases at the same time. – j_random_hacker Jun 18 '09 at 11:40
4

Basically to load Dumper data you eval() it:

use strict;
use Data::Dumper;
my $x = {"a" => "b", "c"=>[1,2,3],};
my $q = Dumper($x);
$q =~ s{\A\$VAR\d+\s*=\s*}{};
my $w = eval $q;
print $w->{"a"}, "\n";

The regexp (s{\A\$VAR\d+\s*=\s*}{}) is used to remove $VAR1= from the beginning of string.

On the other hand - if you need a way to store complex data structure, and load it again, it's much better to use Storable module, and it's store() and retrieve() functions.

  • 1
    The regex isn't necessary—the value of the assignment statement is the same as the right-hand side of the assignment. – nohat Jun 17 '09 at 18:24
1

You can configure the variable name used in Data::Dumper's output with $Data::Dumper::Varname.

Example

use Data::Dumper
$Data::Dumper::Varname = "foo";
my $string = Dumper($object);
eval($string);

...will create the variable $foo, and should contain the same data as $object. If your data structure is complicated and you have strange results, you may want to consider Storable's freeze() and thaw() methods.

Ωmega
  • 42,614
  • 34
  • 134
  • 203
Ether
  • 53,118
  • 13
  • 86
  • 159
1

This has worked for me, for hashes of hashes. Perhaps won't work so well with structures which contain references other structures. But works well enough for simple structures, like arrays, hashes, or hashes of hashes.

 open(DATA,">",$file);
 print DATA Dumper(\%g_write_hash);
 close(DATA);

 my %g_read_hash = %{ do $file };
billg
  • 11
  • 1
1

Please use dump module as a replacement for Data::Dumper