my $root = $tree->getDocumentElement;
my $csv = Text::CSV_XS->new();
+my %id_map;
-print 'id,description,allocated,start,end,"duration (s)","percent complete"' . "\n";
+my @headers = ('id', 'description', 'allocated', 'start', 'end', 'duration (s)', 'percent complete',
+ 'predecessor');
+my %headers;
+for my $i (0..$#headers) {
+ $headers{$headers[$i]} = $i;
+}
+
+# Print out the headers line.
+$csv->combine (@headers);
+print $csv->string() . "\n";
+my @rows;
for my $tasks ($root->findnodes('/project/tasks')) {
- find_tasks($tasks);
+ find_tasks($tasks, \@rows);
+}
+
+# Go through all the rows and find any predecessors that refer to tasks
+# later in the file.
+for my $row (@rows) {
+ $row->[$headers{'predecessor'}] =~ s/PARSE2:(\d+)/$id_map{$1}/;
+
+ $csv->combine (@{ $row });
+ print $csv->string() . "\n";
}
+
sub find_tasks {
my $node = shift;
+ my $rows = shift;
my $level = shift || 0;
my @id = @_;
for my $task ($node->findnodes('task')) {
$id[$level]++;
my @fields = ();
- push @fields,
- join('.', @id),
+ my $id = join('.', @id);
+ $id_map{$task->findvalue('@id')} = $id;
+
+ push @fields, $id,
$task->findvalue('@name');
push @fields, find_allocated($task);
$task->findvalue('@work'),
$task->findvalue('@percent-complete');
- $csv->combine (@fields);
- print $csv->string() . "\n";
+ push @fields, find_predecessors($task);
+
+ push @rows, \@fields;
push @id, '0';
- find_tasks($task, $level + 1, @id);
+ find_tasks($task, $rows, $level + 1, @id);
pop @id;
}
}
return join(', ', @resources);
}
+sub find_predecessors {
+ my $task = shift;
+
+ my @predecessors = ();
+
+ for my $predecessor ($task->findnodes('predecessors/predecessor')) {
+ my $id = $predecessor->findvalue('@predecessor-id');
+ push @predecessors, ($id_map{$id} || "PARSE2:$id") . ' '
+ . $predecessor->findvalue('@type');
+ }
+
+ return join(', ', sort @predecessors);
+}
+
sub date_convert {
my $date = shift;