#
# Copyright (C) 1999 Ken MacLeod
# XML::PatAct::Amsterdam is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
# $Id: Amsterdam.pm,v 1.4 1999/12/22 21:15:00 kmacleod Exp $
#
use strict;
use UNIVERSAL;
package XML::PatAct::Amsterdam;
use vars qw{ $VERSION };
# will be substituted by make-rel script
$VERSION = "0.08";
sub new {
my $type = shift;
my $self = ($#_ == 0) ? { %{ (shift) } } : { @_ };
bless $self, $type;
my $usage = <<'EOF';
usage: XML::PatAct::Amsterdam->new( Matcher => $matcher,
Patterns => $patterns );
EOF
die "No Matcher specified\n$usage\n"
if !defined $self->{Matcher};
die "No Patterns specified\n$usage\n"
if !defined $self->{Patterns};
# perform additional initialization here
return $self;
}
sub start_document {
my ($self, $document) = @_;
# initialize the pattern module at the start of a document
$self->{Matcher}->initialize($self);
# create empty name and node lists for passing to `match()'
$self->{Names} = [ ];
$self->{Nodes} = [ ];
$self->{ActionStack} = [ ];
# create a temporary Output_ in case we're creating a standard
# output file that we'll delete later.
if (!$self->{AsString} && !defined($self->{Output})) {
require IO::File;
import IO::File;
$self->{Output_} = new IO::File(">-");
} elsif (defined($self->{Output})) {
$self->{Output_} = $self->{Output};
}
if ($self->{AsString}) {
$self->{Strings} = [];
}
}
sub end_document {
my ($self, $document) = @_;
# notify the pattern module that we're done
$self->{Matcher}->finalize();
if (defined($self->{Output_})) {
delete $self->{Output_};
}
my $string = undef;
if (defined($self->{AsString})) {
$string = join('', @{$self->{Strings}});
delete $self->{Strings};
}
# release all the info that is just used during event handling
$self->{Matcher} = $self->{Names} = $self->{Nodes} = undef;
$self->{ActionStack} = undef;
return($string);
}
sub start_element {
my ($self, $element) = @_;
push @{$self->{Names}}, $element->{Name};
push @{$self->{Nodes}}, $element;
my $index = $self->{Matcher}->match($element,
$self->{Names},
$self->{Nodes});
my $action;
if (!defined $index) {
$action = undef;
} else {
$action = $self->{Patterns}[$index * 2 + 1];
}
push @{$self->{ActionStack}}, $action;
if (defined($action)) {
my $before = $action->{Before};
if (defined $before) {
my $atts = $element->{Attributes};
$before =~ s/\[([\w.:]+)\]/
($1 eq '_element') ? $element->{Name} : $atts->{$1}
/eg;
$self->print($before);
}
}
}
sub end_element {
my ($self, $end_element) = @_;
my $name = pop @{$self->{Names}};
my $element = pop @{$self->{Nodes}};
my $action = pop @{$self->{ActionStack}};
if (defined($action)) {
my $after = $action->{After};
if (defined $after) {
my $atts = $element->{Attributes};
$after =~ s/\[([\w.:]+)\]/
($1 eq '_element') ? $element->{Name} : $atts->{$1}
/eg;
$self->print($after);
}
}
}
sub characters {
my ($self, $characters) = @_;
$self->print($characters->{Data});
}
sub print {
my ($self, $output) = @_;
$self->{Output_}->print($output)
if (defined($self->{Output_}));
push(@{$self->{Strings}}, $output)
if (defined($self->{AsString}));
}
1;
__END__
=head1 NAME
XML::PatAct::Amsterdam - An action module for simplistic style-sheets
=head1 SYNOPSIS
use XML::PatAct::Amsterdam;
my $patterns = [ PATTERN => { Before => 'before',
After => 'after' },
... ];
my $matcher = XML::PatAct::Amsterdam->new( I