Link to home
Start Free TrialLog in
Avatar of Anu2117
Anu2117

asked on

Convert xml to hash in perl

This is the continuation of
https://www.experts-exchange.com/questions/23837595/XML-generation-with-XML-Simple-XMLout.html

I was wondering if its possible to build a hash back from the xml that got generated. Will this hash match the original hash?

Basically,  I wanted to build a hash from a string and convert the hash to xml format. This is working so far with the code below. Now I want to see if it's possible to build a hash(hash of hash) back from this xml and will it look same as the original hash.

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
 
my @str = (";&EVENT[__nmi_0](nmi, THREAD => 0, TRIGGER => &TRIGGER[__nmi_0.trigger](eom, LIP => 0x2020, SELF_CHECK => 'MUST_COMPLETE', THREAD => 0));",
          ";&EVENT[__psmi_1](psmi, THREAD => 0, TRIGGER => &TRIGGER[__retire_1](retire, LIP => 0x203f, TRIGGER => &EVENT[__smi_1](smi, THREAD => 1, TRIGGER => &TRIGGER[__eom_1](eom, LIP => 0x203f, THREAD => 0))));",
          ";&EVENT[__psmi_0](psmi, THREAD => 0, TRIGGER => &TRIGGER[__psmi_0.trigger](eom, LIP => 0x2000, SELF_CHECK => 'MUST_COMPLETE', THREAD => 0));" );


 
my %Event;
my %Pieces;
foreach (@str) {
      %Pieces = ();
      my $Cnt;
     
      1 while s/\&(\w+)\[__([^\]]+)\]\((\w+),\s+([^\(\)]+)\)/$Cnt++;$Pieces{$Cnt}=MakeHash($1,$2,$3,$4);"$2:SubHash{$Cnt}"/ge;
      for my $piece (sort {$b <=> $a} keys %Pieces) {
            while(my ($k, $v) = each %{$Pieces{$piece}}) {
                  if($v =~ /^(.*):SubHash{(\d+)}$/) {
                        $Pieces{$piece}->{$k}=$1;
                        $Pieces{$piece}->{$1}=$Pieces{$2};
                  }
            }
      }
      if(/^;(.*):SubHash{(\d+)};$/) {
            $Event{$1}=$Pieces{$2};
      }
}
 
print XMLout(\%Event);
 
sub MakeHash {
      return {lc($_[0])=> $_[2], split(/[,=>\s]+/, $_[3])};
}
 
sub XMLout {
      my ($ref, $pre) = @_;
      $pre='' unless defined($pre);
      
      my $str='';
      if(ref($ref) eq 'HASH') {
            foreach my $k (sort keys %$ref) {
                  $str .= "$pre<param name=$k>\n";
                  if(ref($ref->{$k})) { $str .= XMLout($ref->{$k},"$pre\t"); }
                  else { $str .= "$pre\t<value val=$ref->{$k} />\n"; }
                  $str .= "$pre</param>\n";
            }
      }
      else {
            die "Unsupported reference: " . ref($ref) . "\n";
      }
      return $str;
}

ASKER CERTIFIED SOLUTION
Avatar of Adam314
Adam314

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of wilcoxon
I would suggest changing your script to use XML::Simple for both writing the XML and reading it back.  XML::Simple converts perl hash to XML (XMLout) and XML to perl hash (XMLin).

As Adam314 said, getting the perl hash from the XML is just:

my $hash = XMLin($filename);  # $filename can also be a string

I would suggest looking at the XML::Simple documentation as there are quite a few useful options to both XMLin and XMLout.