<?xml version="1.0" encoding="windows-1252"?>
<node id="729003" title="almut's scratchpad" created="2008-12-08 12:27:55" updated="2008-12-08 12:27:55">
<type id="182711">
scratchpad</type>
<author id="580097">
almut</author>
<data>
<field name="doctext">
&lt;p&gt; (follow-up to [id://834482] to handle identical keys at different nesting levels) &lt;/p&gt;
&lt;p&gt; In case the two hashes are always structurally equivalent, you could use a "traversal-ID" (&lt;c&gt;$id&lt;/c&gt; here) to make the keys unique by adding the ID to the keys. It's a bit of a hack because it relies on a number of assumptions, but hopefully, it helps... &lt;/p&gt;
&lt;p&gt; For example, with a duplicate key &lt;c&gt;'a'&lt;/c&gt;: &lt;/p&gt;
&lt;c&gt;
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;

my %xhash = ('a' =&gt; {
                 'b' =&gt; {
                        'e' =&gt; 'E',
                        'c' =&gt; 'C',
                        'content' =&gt; 'B
'
                      },
                 'content' =&gt; 'A
',
                 'd' =&gt; 'D',
                 'a' =&gt; 'Foo'
               });

my %c_hash=('a' =&gt; {
                   'addval' =&gt; {
                                 'b' =&gt; {
                                          'addval' =&gt; {
                                                        'e' =&gt; {
                                                                 'addval' =&gt; {},
                                                                 'repval' =&gt; '5'
                                                               },
                                                        'c' =&gt; {
                                                                 'addval' =&gt; {},
                                                                 'repval' =&gt; '3'
                                                               }
                                                      },
                                          'repval' =&gt; '2'
                                        },
                                 'd' =&gt; {
                                          'addval' =&gt; {},
                                          'repval' =&gt; '4'
                                        },
                                 'a' =&gt; {
                                          'addval' =&gt; {},
                                          'repval' =&gt; '99'
                                        },
                               },
                   'repval' =&gt; '1'
                 });


my $id;
sub traverse {
    my ($hash, $callback, $mode, $start_id) = @_;
    return unless ref($hash) eq "HASH";
    $id = $start_id if defined $start_id;
    for my $key (sort keys %$hash) {
        my $val = $hash-&gt;{$key};
        if (ref($val) eq "HASH") {
            traverse($val, $callback, $mode);
            if ($mode eq "collect") {
                if (exists $val-&gt;{repval}) {
                    $id++;
                    $callback-&gt;("$key-$id", $val-&gt;{repval});
                }
            }
        }
        if ($mode eq "replace") {
            $id++ unless $key eq "content";
            $callback-&gt;("$key-$id", $val, $hash);
        }
    }
}

my %repl;  # lookup table: a =&gt; 1, etc.
traverse(\%c_hash,
         sub {
             my ($key, $val) = @_;
             $repl{$key} = $val;
         },
         "collect", 0
);
# print Dumper \%repl;  # debug

traverse(\%xhash,
         sub {
             my ($key, $val, $href) = @_;
             if (exists $repl{$key}) {
                 my $newkey = $repl{$key};
                 my ($oldkey) = split /-/, $key;
                 $href-&gt;{$newkey} = $val;
                 delete $href-&gt;{$oldkey};
             }
         },
         "replace", 0
);
print Dumper \%xhash;

__END__
$VAR1 = {
          '1' =&gt; {
                   '4' =&gt; 'D',
                   '99' =&gt; 'Foo',
                   'content' =&gt; 'A
',
                   '2' =&gt; {
                            '3' =&gt; 'C',
                            'content' =&gt; 'B
',
                            '5' =&gt; 'E'
                          }
                 }
        };

&lt;/c&gt;</field>
</data>
</node>
