ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я сам не использовал Twig, поэтому этот ответ может быть не идиоматичным - это общий ответ «как сохранить состояние в обработчике обратного вызова».
Три способа передачи информации в обработчики и из них:
ONE. Состояние удерживается в статическом месте
package TwigState;
my %state = ();
# Pass in a state attribute to get
sub getState { $state{$_[0]} }
# Pass in a state attribute to set and a value
sub setState { $state{$_[0]} = $_[1]; }
package main;
sub parse_a_counter { # Better yet, declare all handlers in TwigState
my ($twig, $element) = @_;
my $counter = TwigState::getState('counter');
$counter++;
TwigState::setState('counter', $counter);
}
ВТОРАЯ. Состояние хранится в самом $ t (объекте XML :: Twig) в некотором элементе «state»
# Ideally, XML::Twig or XML::Parser would have a "context" member
# to store context and methods to get/set that context.
# Barring that, simply make one, using a VERY VERY bad design decision
# of treating the object as a hash and just making a key in that hash.
# I'd STRONGLY not recommend doing that and choosing #1 or #3 instead,
# unless there's a ready made context data area in the class.
sub parse_a_counter {
my ($twig, $element) = @_;
my $counter = $twig->getContext('counter');
# BAD: my $counter = $twig->{'_my_context'}->{'counter'};
$counter++;
TwigState::setState('counter', $counter);
$twig->setContext('counter', $counter);
# BAD: $twig->{'_my_context'}->{'counter'} = $counter;
}
# for using DIY context, better pass it in with constructor:
my $twig = new XML::Twig(TwigRoots => $roots,
TwigHandlers => $handlers
_my_context => {});
ТРЕТИЙ. Сделайте обработчик замыканием и сделайте так, чтобы он сохранял состояние таким образом