The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
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>