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>