use strict; use warnings; my $tab = " "; my %refs_seen; my %dispatch = ( # scalar '' => sub { my ( $element, $level ) = @_; print $tab x $level, $element // "UNDEF", "\n"; }, 'HASH' => sub { my ( $element, $level ) = @_; print $tab x $level++, "\n"; for my $key (keys %{$element}) { print $tab x $level, "\n"; structure_to_xml( $element->{$key}, $level+1 ); print $tab x $level, "\n" } print $tab x --$level, "\n"; }, 'ARRAY' => sub { my ( $element, $level ) = @_; print $tab x $level, "\n"; structure_to_xml( $_, $level+1 ) for @{$element}; print $tab x $level, "\n"; }, 'default' => sub { my ( $element, $level ) = @_; print $tab x $level, "\n" }, ); # operates on references sub structure_to_xml { my ( $element, $level ) = @_; if( ref $element ) { if( exists $refs_seen{$element} ) { print $tab x $level, "\n"; return; } else { $refs_seen{$element} = 1; } } &{ $dispatch{ ref($_[0]) } // $dispatch{'default'} }(@_); } # here comes an example for using it use XML::Simple; # enable looking into XML::Simple objects $dispatch{'XML::Simple'} = $dispatch{HASH}; # comment out if you do not want to see internals my $xml = XML::Simple->new(); sub somesub { } my $hashref; $hashref->{self} = $hashref; my $var = { "0x55555555" => { "0x55555555" => [ ["0xAAAAAAAA", "0x9"], ], "0xAAAAAAAA" => [ ["0xAAAAAAAA", "0x8"], ], }, "0xAAAAAAAA" => { "0x55555555" => [ ["0xFFFFFFFF", "0x8"], ], "0xAAAAAAAA" => [ ["0x55555554", "0x3"], ], }, "self" => $hashref, "code" => \&somesub, "xmlparser" => $xml, }; structure_to_xml( $var, 0 );