Fletch has got at the heart of your problem. I'd add three things to his observation.
- The first is that you ask where you've gone wrong, but don't include the observed output, so that it's hard to tell. (It's not even clear what the desired output should be—it seems to me that you're ignoring the text completely, and only ever dumping the scene name.)
- The second is that you are assigning the result of ->findnodes, which returns an array, to a scalar, $item. This will put the size of the array in $item, which is almost surely not what you want.
- At the end of your foreach loop, after assigning to $text, you immediately overwrite the value with whatever is in $act{$scene} (nothing, as Fletch observed). Did you mean the assignment to go the other way? If so, you probably really meant to push on to some sort of array reference, since otherwise you'll get only one bit of text per scene.
I'm also confused by your XML. Will it ever contain more than one act? If so, how do you know when the act ends (since the
ACT node seems to end with the title)? I'm going to assume here that you've got only one act (and one play) per XML file, and suggest something that might work. (My XPath is rusty, so take this with a healthy grain of salt.)
for my $scene ( $doc->findnodes('/PLAY/SCENE') ) {
ITEM: for my $item ( $scene->findnodes('SPEECH') ) {
my $speaker = $item->findvalue('SPEAKER');
next ITEM unless $speaker eq $searchterm;
push @{$act{$scene}}, [ map { $_->to_literal } $item->findno
+des('LINE') ];
}
}
You could dump this with something like
for my $scene ( keys %act ) {
print "SCENE $scene:\n";
print "$searchterm:\n", join "\n", @$_ for @{$act{$scene}};
}