use strict; use warnings; no warnings 'uninitialized'; use XML::Rules; my %written; my %depends; my $parser = XML::Rules->new( style => 'filter', rules => { _default => 'raw', 'name,members' => 'raw extended', 'Group' => 'raw extended array', record => sub { my @I_depend; if (exists $_[1]->{':members'} and exists $_[1]->{':members'}{':Group'}) { @I_depend = grep !exists $written{$_}, map $_->{_content}, @{$_[1]->{':members'}{':Group'}}; } if (@I_depend) { $_[1]->{':I_depend'} = {map {$_ => 1} @I_depend}; foreach (@I_depend) { push @{$depends{$_}}, $_[1] } return; } else { my $name = $_[1]->{':name'}{_content}; $written{$name} = 1; my @to_write = $_[1]; if (exists $depends{$name}) { push @to_write, find_dependent($name); } return 'record' => \@to_write; } } } ); sub find_dependent { my $name = shift; my @to_write; foreach my $parent (@{$depends{$name}}) { delete $parent->{':I_depend'}{$name}; if (! %{$parent->{':I_depend'}}) { # if it doesn't depend on anything more, write it after this one push @to_write, $parent; $written{$parent->{':name'}{_content}} = 1; push @to_write, find_dependent($parent->{':name'}{_content}); } } delete $depends{$name}; return @to_write; } #$parser->filter(\*DATA); $parser->filterfile('c:\temp\groups.xml'); #if (%depends) { # print STDERR "Unsatisfied dependencies! Some records depend on these unknown groups: ", # join ", ", keys %depends; #} if (%depends) { print STDERR "\nUnsatisfied dependencies!\n"; foreach my $missing (keys %depends) { print STDERR"Missing group '$missing' is a member of:\n"; print STDERR "BUT IT WAS WRITTEN!!\n" if (exists $written{$missing}); foreach my $failed (@{$depends{$missing}}) { print STDERR" $failed->{':name'}{_content}\n"; } } } __DATA__ <SystemXchange version="1.0"> <summary> <tool version="2.8 build: [070207]">Enterprise Migration Tool</tool> <source></source> <comments> </comments> <timestamp>May 30, 2008 @ 10:00:00 CDT</timestamp> </summary> <!--Begin Group Records--> <records type="group" operation="insert"> <record> <name>GOLF</name> <comments> </comments> <departments> <department>Default</department> </departments> <members> <Group>ECHO</Group> <Group>BETA</Group> <Group>DELTAx</Group> <Group>FOXTROT</Group> <Destination>bj1234</Destination> </members> <ta_properties> <FullName> </FullName> </ta_properties> </record> <record> <name>ECHO</name> <comments> </comments> <departments> <department>Default</department> </departments> <members> <Group>CHARLIE</Group> <Group>DELTA</Group> <Destination>cn1234</Destination> <Destination>mc1234</Destination> </members> <ta_properties> <FullName> </FullName> </ta_properties> </record> <record> <name>CHARLIE</name> <comments> </comments> <departments> <department>Default</department> </departments> <members> <Group>ALPHA</Group> <Group>DELTA</Group> <Destination>zt1234</Destination> <Destination>rx1234</Destination> </members> <ta_properties> <FullName> </FullName> </ta_properties> </record> <record> <name>BETA</name> <comments> </comments> <departments> <department>Default</department> </departments> <members> <Destination>bp1234</Destination> <Destination>cm1234</Destination> <Group>FOXTROT</Group> <Group>CHARLIE</Group> </members> <ta_properties> <FullName> </FullName> </ta_properties> </record> <record> <name>FOXTROT</name> <comments> </comments> <departments> <department>Default</department> </departments> <members> <Group>ALPHA</Group> <Destination>cn1234</Destination> <Destination>sc1234</Destination> <Destination>sp1234</Destination> </members> <ta_properties> <FullName> </FullName> </ta_properties> </record> <record> <name>DELTA</name> <comments> </comments> <departments> <department>Default</department> </departments> <members> <Group>ALPHA</Group> <Group>FOXTROT</Group> </members> <ta_properties> <FullName> </FullName> </ta_properties> </record> <record> <name>ALPHA</name> <comments> </comments> <departments> <department>Default</department> </departments> <members> <Destination>sm1234</Destination> </members> <ta_properties> <FullName> </FullName> </ta_properties> </record> <record> <name>ALPHA2</name> <comments> </comments> <departments> <department>Default</department> </departments> <members> <Group>ALPHA</Group> <Destination>sm1234</Destination> </members> <ta_properties> <FullName> </FullName> </ta_properties> </record> </records> </SystemXchange>