The following calls a user supplied routine with a list of ancestors of a node when it encounters a node with the right name in the XML tree.
use feature ":5.14";
use warnings FATAL => qw(all);
use strict;
use Data::Dump qw(dump pp);
use XML::Simple;
my $x = XMLin(<<'END');
<files name="Common.h">
<enums>
<members kind="enum" name="PermissionLevel" protection="public"
+static="no" virtualness="non_virtual">
<values initializer=" 99" name="PERMISSION_PUBLIC"></values>
<values initializer=" 98" name="PERMISSION_NDA"></values>
</members>
<members kind="enum" name="RegisterType" protection="public" sta
+tic="no" virtualness="non_virtual">
<values initializer=" 4" name="REGISTER_PCI"></values>
</members>
</enums>
<functions>
<members const="no" kind="function" name="Compare" protection="p
+ublic" static="no" type="bool" virtualness="non_virtual" volatile="no
+">
<parameters declaration_name="first" type="T"/>
<parameters declaration_name="second" type="T"/>
</members>
</functions>
</files>
END
pp($x);
sub r($$$;$);
sub r($$$;$)
{my ($r, $l, $e, $a) = @_;
$a = [] unless $a;
return unless $l and ref($l);
if (ref($l) =~ /HASH/)
{for(sort keys %$l)
{unless (/$e/)
{push @$a, $_;
r($r, $l->{$_}, $e, $a);
pop @$a;
}
else
{&$r(@$a);
}
}
}
elsif (ref($l) =~ /ARRAY/)
{for(1..@$l)
{unless ($l->[$_-1] =~ /$e/)
{push @$a, $_;
r($r, $l->[$_-1], $e, $a);
pop @$a;
}
else
{&$r(@$a);
}
}
}
}
r sub {say "@_"}, $x, "values";
Produces
enums members PermissionLevel
enums members RegisterType
|