I used to be one of the teachers of
this course.
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
use XML::SAX;
use XML::SAX::Writer;
my $out;
my $writer = XML::SAX::Writer->new(Output => \$out);
my $filter = Element_Attribute_Counter->new(Handler => $writer);
my $parser = XML::SAX::ParserFactory->parser(Handler => $filter);
$parser->parse_uri($ARGV[0]);
print "$out\n", Dumper($filter->get_count);
package Element_Attribute_Counter;
use base qw( XML::SAX::Base );
use Scalar::Util qw( refaddr );
my %count;
sub start_element {
my ($self, $element) = @_;
my $addr = refaddr $self;
$count{$addr}{ $element->{Name} }++;
my $attributes = $element->{Attributes};
for my $attribute (keys %$attributes) {
$count{$addr}{ "@" . $attributes->{$attribute}{Name} }++;
}
$element->{Name} = uc $element->{Name};
$self->SUPER::start_element($element);
}
sub get_count {
my $self = shift;
return $count{refaddr $self};
}
Update: As usually with callbacks, the easiest way to communicate is through closures. This example uses a lexical package-scoped variable. Note that each object has a different slot in the hash, so you can use the same class for several objects (the count is "inside-out").