| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Net::OAI::Record::NamespaceFilter; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 1 |  |  | 1 |  | 1230 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 27 |  | 
| 4 | 1 |  |  | 1 |  | 5 | use base qw( XML::SAX::Base ); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 69 |  | 
| 5 | 1 |  |  | 1 |  | 5 | use Storable; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 1955 |  | 
| 6 |  |  |  |  |  |  | our $VERSION = 'v1.016.10'; | 
| 7 |  |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  | our $AUTOLOAD; | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | =head1 NAME | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | Net::OAI::Record::NamespaceFilter - general filter class | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | It will forward any element belonging to a namespace from this list | 
| 19 |  |  |  |  |  |  | to the associated SAX filter and all of the element's children | 
| 20 |  |  |  |  |  |  | (regardless of their respective namespace) to the same one. It can be used either as a | 
| 21 |  |  |  |  |  |  | C or C. | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | This SAX filter takes a hashref C as argument, with namespace | 
| 24 |  |  |  |  |  |  | URIs for keys ('*' for "any") and either | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | over 4 | 
| 27 |  |  |  |  |  |  |  | 
| 28 |  |  |  |  |  |  | =item undef | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  | Matching elements and their subelements are suppressed. | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  | If the list of namespaces ist empty or C is connected to | 
| 33 |  |  |  |  |  |  | the filter, it effectively acts as a plug to Net::OAI::Harvester. This | 
| 34 |  |  |  |  |  |  | might come handy if you are planning to get to the raw result by other | 
| 35 |  |  |  |  |  |  | means, e.g. by tapping the user agent or accessing the result's xml() method: | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  | $plug = Net::OAI::Harvester::Record::NamespaceFilter(); | 
| 38 |  |  |  |  |  |  | $harvester = Net::OAI::Harvester->new( [ | 
| 39 |  |  |  |  |  |  | baseURL => ..., | 
| 40 |  |  |  |  |  |  | recordHandler => $plug, | 
| 41 |  |  |  |  |  |  | ] ); | 
| 42 |  |  |  |  |  |  |  | 
| 43 |  |  |  |  |  |  | my $unparsed; | 
| 44 |  |  |  |  |  |  | open (my $TAP, ">", \$unparsed); | 
| 45 |  |  |  |  |  |  | $harvester->userAgent()->add_handler(response_data => sub { | 
| 46 |  |  |  |  |  |  | my($response, $ua, $h, $data) = @_; | 
| 47 |  |  |  |  |  |  | print $TAP $data; | 
| 48 |  |  |  |  |  |  | }); | 
| 49 |  |  |  |  |  |  |  | 
| 50 |  |  |  |  |  |  | $list = $harvester->listRecords( | 
| 51 |  |  |  |  |  |  | metadataPrefix  => 'a_strange_one', | 
| 52 |  |  |  |  |  |  | recordHandler => $plug, | 
| 53 |  |  |  |  |  |  | ); | 
| 54 |  |  |  |  |  |  |  | 
| 55 |  |  |  |  |  |  | print $unparsed;     # complete OAI response | 
| 56 |  |  |  |  |  |  | print $list->xml();  # should be the same | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | =item a class name of a SAX filter | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | For any record element of the OAI response a new instance | 
| 62 |  |  |  |  |  |  | is created. | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  | =item a code reference for an constructor | 
| 66 |  |  |  |  |  |  |  | 
| 67 |  |  |  |  |  |  | Must return a SAX filter ready to accept a new document. | 
| 68 |  |  |  |  |  |  |  | 
| 69 |  |  |  |  |  |  | The following example returns a text representation of each single | 
| 70 |  |  |  |  |  |  | record: | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | # end_document() events will return \$x | 
| 73 |  |  |  |  |  |  | my $constructor = sub { my $x = ""; | 
| 74 |  |  |  |  |  |  | return XML::SAX::Writer->new(Output => \$x); | 
| 75 |  |  |  |  |  |  | }; | 
| 76 |  |  |  |  |  |  | $my harvester = Net::OAI::Harvester->new( [ | 
| 77 |  |  |  |  |  |  | baseURL => ..., | 
| 78 |  |  |  |  |  |  | ] ); | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | my $filter = Net::OAI::Harvester::Record::NamespaceFilter( | 
| 81 |  |  |  |  |  |  | '*' => $constructor); | 
| 82 |  |  |  |  |  |  |  | 
| 83 |  |  |  |  |  |  | my $list = $harvester->listRecords( | 
| 84 |  |  |  |  |  |  | metadataPrefix  => 'oai_dc', | 
| 85 |  |  |  |  |  |  | recordHandler => $filter, | 
| 86 |  |  |  |  |  |  | ); | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | while( my $r = $list->next() ) { | 
| 89 |  |  |  |  |  |  | my $xmlstringref = $r->recorddata()->result('*'); | 
| 90 |  |  |  |  |  |  | ... | 
| 91 |  |  |  |  |  |  | }; | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | Note: | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  |  | 
| 96 |  |  |  |  |  |  | =item an already instantiated SAX filter | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  | In this case C and C events are | 
| 99 |  |  |  |  |  |  | E forwarded to the filter. | 
| 100 |  |  |  |  |  |  |  | 
| 101 |  |  |  |  |  |  | open my $fh, ">", $some_file; | 
| 102 |  |  |  |  |  |  | $builder = XML::SAX::Writer->new(Output => $fh); | 
| 103 |  |  |  |  |  |  | $builder->start_document(); | 
| 104 |  |  |  |  |  |  | my $rootEL = { Name => 'collection', | 
| 105 |  |  |  |  |  |  | LocalName => 'collection', | 
| 106 |  |  |  |  |  |  | NamespaceURI => "http://www.loc.gov/MARC21/slim", | 
| 107 |  |  |  |  |  |  | Prefix => "", | 
| 108 |  |  |  |  |  |  | Attributes => {} | 
| 109 |  |  |  |  |  |  | }; | 
| 110 |  |  |  |  |  |  | $builder->start_element( $rootEL ); | 
| 111 |  |  |  |  |  |  |  | 
| 112 |  |  |  |  |  |  | # filter for OAI-Namespace in records: forward all | 
| 113 |  |  |  |  |  |  | my $filter = Net::OAI::Harvester::Record::NamespaceFilter( | 
| 114 |  |  |  |  |  |  | 'http://www.loc.gov/MARC21/slim' => $builder); | 
| 115 |  |  |  |  |  |  |  | 
| 116 |  |  |  |  |  |  | my $harvester = Net::OAI::Harvester->new( [ | 
| 117 |  |  |  |  |  |  | baseURL => ..., | 
| 118 |  |  |  |  |  |  | ] ); | 
| 119 |  |  |  |  |  |  |  | 
| 120 |  |  |  |  |  |  | my $list = $harvester->listRecords( | 
| 121 |  |  |  |  |  |  | metadataPrefix  => 'a_strange_one', | 
| 122 |  |  |  |  |  |  | metadataHandler => $filter, | 
| 123 |  |  |  |  |  |  | ); | 
| 124 |  |  |  |  |  |  | # handle resumption tokens if more than the first | 
| 125 |  |  |  |  |  |  | # chunk shall be stored into $fh .... | 
| 126 |  |  |  |  |  |  |  | 
| 127 |  |  |  |  |  |  | $builder->end_element( $rootEL ); | 
| 128 |  |  |  |  |  |  | $builder->end_document(); | 
| 129 |  |  |  |  |  |  | close($fh); | 
| 130 |  |  |  |  |  |  |  | 
| 131 |  |  |  |  |  |  | =back | 
| 132 |  |  |  |  |  |  |  | 
| 133 |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  | =head1 METHODS | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  |  | 
| 137 |  |  |  |  |  |  | =head2 new( [%namespaces] ) | 
| 138 |  |  |  |  |  |  |  | 
| 139 |  |  |  |  |  |  | =cut | 
| 140 |  |  |  |  |  |  |  | 
| 141 |  |  |  |  |  |  | sub new { | 
| 142 | 3 |  |  | 3 | 1 | 3487 | my ( $class, %opts ) = @_; | 
| 143 | 3 |  | 33 |  |  | 30 | my $self = bless { namespaces => {%opts} }, ref( $class ) || $class; | 
| 144 | 3 |  |  |  |  | 12 | $self->{ _activeStack } = []; | 
| 145 | 3 |  |  |  |  | 9 | $self->{ _tagStack } = []; | 
| 146 | 3 |  |  |  |  | 7 | $self->{ _result } = []; | 
| 147 | 3 |  |  |  |  | 8 | $self->{ _prefixmap } = {}; | 
| 148 | 3 |  |  |  |  | 20 | $self->set_handler( undef ); | 
| 149 | 3 |  |  |  |  | 36 | delete $self->{ _noHandler };  # follows set_handler() | 
| 150 | 3 |  |  |  |  | 10 | $self->{ _handlers } = {}; | 
| 151 | 3 |  |  |  |  | 7 | $self->{ _performing } = {}; | 
| 152 | 3 |  |  |  |  | 7 | while ( my ($key, $value) = each %{$self->{ namespaces }} ) { | 
|  | 5 |  |  |  |  | 24 |  | 
| 153 | 2 | 50 |  |  |  | 17 | if ( ! defined $value ) {   # no handler | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 154 |  |  |  |  |  |  | #warn "new(): case 1 for $key"; | 
| 155 |  |  |  |  |  |  | } | 
| 156 |  |  |  |  |  |  | elsif ( ! ref($value) ) {    # class name | 
| 157 |  |  |  |  |  |  | #warn "new(): case 2 for $key"; | 
| 158 | 0 |  |  |  |  | 0 | Net::OAI::Harvester::_verifyHandler( $value ); | 
| 159 |  |  |  |  |  |  | } | 
| 160 |  |  |  |  |  |  | elsif ( ref($value) eq "CODE" ) {    # constructor | 
| 161 |  |  |  |  |  |  | #warn "new(): case 3 for $key"; | 
| 162 |  |  |  |  |  |  | # can't verify now | 
| 163 |  |  |  |  |  |  | } | 
| 164 |  |  |  |  |  |  | else {    # active instance | 
| 165 |  |  |  |  |  |  | #warn "new(): case 4 for $key"; | 
| 166 | 1 |  |  |  |  | 3 | $self->{ _handlers }->{ $key } = $value; | 
| 167 | 1 |  |  |  |  | 4 | $self->{ _performing }->{ $value }--; | 
| 168 |  |  |  |  |  |  | } | 
| 169 |  |  |  |  |  |  | }; | 
| 170 | 3 |  |  |  |  | 11 | return( $self ); | 
| 171 |  |  |  |  |  |  | } | 
| 172 |  |  |  |  |  |  |  | 
| 173 |  |  |  |  |  |  | =head2 result ( [namespace] ) | 
| 174 |  |  |  |  |  |  |  | 
| 175 |  |  |  |  |  |  | If called with a I, it returns the result of the handler, | 
| 176 |  |  |  |  |  |  | i.e. what C returned for the record in question. | 
| 177 |  |  |  |  |  |  | Otherwise it returns a hashref for all the results with the | 
| 178 |  |  |  |  |  |  | corresponding namespaces as keys. | 
| 179 |  |  |  |  |  |  |  | 
| 180 |  |  |  |  |  |  | =cut | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  | sub result { | 
| 183 | 202 |  |  | 202 | 1 | 122309 | my ( $self, $ns ) = @_; | 
| 184 | 202 | 100 |  |  |  | 572 | if ( defined $ns ) { | 
| 185 | 201 |  | 100 |  |  | 941 | return $self->{ _result }->{$ns} || undef} | 
| 186 |  |  |  |  |  |  | else { | 
| 187 | 1 |  |  |  |  | 4 | return $self->{ _result }} | 
| 188 |  |  |  |  |  |  | } | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  |  | 
| 191 |  |  |  |  |  |  | ## Storable hooks | 
| 192 |  |  |  |  |  |  |  | 
| 193 |  |  |  |  |  |  | sub STORABLE_freeze { | 
| 194 | 400 |  |  | 400 | 0 | 45927 | my ($obj, $cloning) = @_; | 
| 195 | 400 | 50 |  |  |  | 1021 | return if $cloning; | 
| 196 | 400 |  |  |  |  | 81023 | return "", $obj->{ _result };   # || undef; | 
| 197 |  |  |  |  |  |  | } | 
| 198 |  |  |  |  |  |  |  | 
| 199 |  |  |  |  |  |  | sub STORABLE_thaw { | 
| 200 | 400 |  |  | 400 | 0 | 14692 | my ($obj, $cloning, $serialized, $listref) = @_; | 
| 201 | 400 | 50 |  |  |  | 967 | return if $cloning; | 
| 202 | 400 |  |  |  |  | 8295 | $obj->{ _result } = $listref; | 
| 203 |  |  |  |  |  |  | #warn "thawed @$listref"; | 
| 204 |  |  |  |  |  |  | } | 
| 205 |  |  |  |  |  |  |  | 
| 206 |  |  |  |  |  |  |  | 
| 207 |  |  |  |  |  |  | ## SAX handlers | 
| 208 |  |  |  |  |  |  |  | 
| 209 |  |  |  |  |  |  | sub start_document { | 
| 210 | 0 |  |  | 0 | 1 | 0 | my ($self, $document) = @_; | 
| 211 | 0 |  |  |  |  | 0 | die "start_document()"; | 
| 212 | 0 |  |  |  |  | 0 | warn "\t\t_activeStack: @{$self->{ _activeStack }}\n"; | 
|  | 0 |  |  |  |  | 0 |  | 
| 213 | 0 |  |  |  |  | 0 | warn "\t\t_tagStack: @{$self->{ _tagStack }}\n"; | 
|  | 0 |  |  |  |  | 0 |  | 
| 214 | 0 |  |  |  |  | 0 | $self->SUPER::start_document( $document ); | 
| 215 |  |  |  |  |  |  | } | 
| 216 |  |  |  |  |  |  | sub end_document { | 
| 217 | 0 |  |  | 0 | 1 | 0 | my ($self, $document) = @_; | 
| 218 | 0 |  |  |  |  | 0 | die "end_document()"; | 
| 219 | 0 |  |  |  |  | 0 | warn "\t\t_activeStack: @{$self->{ _activeStack }}\n"; | 
|  | 0 |  |  |  |  | 0 |  | 
| 220 | 0 |  |  |  |  | 0 | warn "\t\t_tagStack: @{$self->{ _tagStack }}\n"; | 
|  | 0 |  |  |  |  | 0 |  | 
| 221 | 0 |  |  |  |  | 0 | $self->SUPER::end_document( $document ); | 
| 222 |  |  |  |  |  |  | } | 
| 223 |  |  |  |  |  |  |  | 
| 224 |  |  |  |  |  |  | sub start_prefix_mapping { | 
| 225 | 2005 |  |  | 2005 | 1 | 16898 | my ($self, $mapping) = @_; | 
| 226 |  |  |  |  |  |  | #warn "NamespaceFilter: deferred prefix mapping for @{[%$mapping]}\n"; | 
| 227 | 2005 | 100 |  |  |  | 6090 | $self->SUPER::start_prefix_mapping( $mapping ) unless $self->{ _noHandler }; | 
| 228 | 2005 | 50 |  |  |  | 9689 | return if $self->{ _activeStack }->[0]; | 
| 229 |  |  |  |  |  |  | #warn ">>>possibly deferred prefix mapping for @{[%$mapping]}\n"; | 
| 230 | 2005 |  |  |  |  | 5069 | $self->{ _prefixmap }->{ $mapping->{Prefix} } = $mapping; | 
| 231 | 2005 |  |  |  |  | 4947 | my $activehdl = $self->get_handler(); | 
| 232 | 2005 | 0 | 33 |  |  | 14913 | die "wrong assumption" unless (! defined $activehdl) or $self->{ _performing }->{ $activehdl }; | 
| 233 | 2005 |  |  |  |  | 2624 | my $switched; | 
| 234 | 2005 |  |  |  |  | 2532 | foreach my $hdl ( keys %{$self->{ _performing }} ) { | 
|  | 2005 |  |  |  |  | 5253 |  | 
| 235 |  |  |  |  |  |  | #warn "\t-->forwarding prefix mapping @{[%$mapping]}\n\t\tto $hdl at @{$self->{ _tagStack }}\n"; | 
| 236 | 5 |  |  |  |  | 19 | $self->set_handler( $hdl ); | 
| 237 | 5 |  |  |  |  | 72 | $self->SUPER::start_prefix_mapping( $mapping ); | 
| 238 | 5 |  |  |  |  | 166 | $switched = 1; | 
| 239 |  |  |  |  |  |  | } | 
| 240 | 2005 | 100 |  |  |  | 13907 | $self->set_handler( $activehdl ) if $switched; | 
| 241 |  |  |  |  |  |  | } | 
| 242 |  |  |  |  |  |  |  | 
| 243 |  |  |  |  |  |  | sub end_prefix_mapping { | 
| 244 | 1203 |  |  | 1203 | 1 | 21252 | my ($self, $mapping) = @_; | 
| 245 | 1203 | 100 |  |  |  | 3812 | $self->SUPER::end_prefix_mapping( $mapping ) unless $self->{ _noHandler }; | 
| 246 | 1203 | 50 |  |  |  | 5431 | return if $self->{ _activeStack }->[0]; | 
| 247 |  |  |  |  |  |  | #warn "<<{ _tagStack }}\n"; | 
| 248 | 1203 | 50 |  |  |  | 3978 | die "mapping @{[%$mapping]} already removed" unless $self->{ _prefixmap }->{ $mapping->{Prefix} }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 249 | 1203 |  |  |  |  | 3007 | my $activehdl = $self->get_handler();   # always undef | 
| 250 | 1203 | 0 | 33 |  |  | 8539 | die "wrong assumption" unless (! defined $activehdl) or $self->{ _performing }->{ $activehdl }; | 
| 251 | 1203 |  |  |  |  | 1480 | my $switched; | 
| 252 | 1203 |  |  |  |  | 1683 | foreach my $hdl ( keys %{$self->{ _performing }} ) { | 
|  | 1203 |  |  |  |  | 3184 |  | 
| 253 |  |  |  |  |  |  | #warn "\t--->forwarding removed mapping to $hdl"; | 
| 254 | 3 |  |  |  |  | 11 | $self->set_handler( $hdl ); | 
| 255 | 3 |  |  |  |  | 32 | $self->SUPER::end_prefix_mapping( $mapping ); | 
| 256 | 3 |  |  |  |  | 82 | $switched = 1; | 
| 257 |  |  |  |  |  |  | } | 
| 258 | 1203 |  |  |  |  | 2941 | delete $self->{ _prefixmap }->{ $mapping->{Prefix} }; | 
| 259 | 1203 | 100 |  |  |  | 6988 | $self->set_handler( $activehdl ) if $switched; | 
| 260 |  |  |  |  |  |  | } | 
| 261 |  |  |  |  |  |  |  | 
| 262 |  |  |  |  |  |  | sub start_element { | 
| 263 | 10645 |  |  | 10645 | 1 | 69262 | my ( $self, $element ) = @_; | 
| 264 |  |  |  |  |  |  | #warn "\t((( ".$element->{ Name }." ((("; | 
| 265 |  |  |  |  |  |  | #warn "\t\t_activeStack: @{$self->{ _activeStack }}\n"; | 
| 266 |  |  |  |  |  |  | #warn "\t\t_tagStack: @{$self->{ _tagStack }}\n"; | 
| 267 | 10645 | 100 |  |  |  | 25027 | if ( $self->{ _activeStack }->[0] ) {   # handler already set up | 
| 268 |  |  |  |  |  |  | } | 
| 269 |  |  |  |  |  |  | else { | 
| 270 | 6115 | 100 |  |  |  | 15425 | unless ( $self->{ _tagStack }->[0] ) {      # should be the start of a new record | 
| 271 |  |  |  |  |  |  | #warn "initializing for $element->{Name}\n"; | 
| 272 | 401 |  |  |  |  | 783 | $self->{ _result } = {}; | 
| 273 |  |  |  |  |  |  | # start_document here for all defined handlers? | 
| 274 | 401 |  |  |  |  | 1557 | my $activehdl = $self->get_handler();   # always undef | 
| 275 | 401 | 50 |  |  |  | 3018 | die "handler $activehdl already active" if defined $activehdl; | 
| 276 | 401 |  |  |  |  | 504 | my $switched; | 
| 277 |  |  |  |  |  |  |  | 
| 278 | 401 |  |  |  |  | 656 | while ( my ($key, $value) = each %{$self->{ namespaces }} ) { | 
|  | 602 |  |  |  |  | 9142 |  | 
| 279 | 201 |  |  |  |  | 483 | $self->{ _result }->{ $key } = undef; | 
| 280 | 201 |  |  |  |  | 281 | my $hdl; | 
| 281 | 201 | 50 |  |  |  | 1162 | if ( ! defined $value ) {   # no handler | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 282 |  |  |  |  |  |  | #warn "start_element(): case 1 for $key"; | 
| 283 |  |  |  |  |  |  | } | 
| 284 |  |  |  |  |  |  | elsif ( ! ref($value) ) {    # class name | 
| 285 |  |  |  |  |  |  | #warn "start_element(): case 2 for $key"; | 
| 286 | 0 |  |  |  |  | 0 | $hdl = $value->new(); | 
| 287 |  |  |  |  |  |  | } | 
| 288 |  |  |  |  |  |  | elsif ( ref($value) eq "CODE" ) {    # constructor | 
| 289 |  |  |  |  |  |  | #warn "start_element(): case 3 for $key"; | 
| 290 | 200 |  |  |  |  | 744 | $hdl = &$value(); | 
| 291 | 200 |  |  |  |  | 38954 | Net::OAI::Harvester::_verifyHandler( $hdl ); | 
| 292 |  |  |  |  |  |  | } | 
| 293 |  |  |  |  |  |  | else {    # always active instance | 
| 294 |  |  |  |  |  |  | #warn "start_element(): case 4 for $key. Handler is $value"; | 
| 295 |  |  |  |  |  |  | # bugfix for XML::SAX::Writer? | 
| 296 | 1 |  |  |  |  | 2 | $switched = 1; | 
| 297 | 1 |  |  |  |  | 4 | $self->set_handler( $value ); | 
| 298 | 1 |  |  |  |  | 9 | foreach my $mapping ( values %{$self->{ _prefixmap }} ) { | 
|  | 1 |  |  |  |  | 6 |  | 
| 299 |  |  |  |  |  |  | #warn "bugfix supply of deferred @{[%$mapping]}"; | 
| 300 | 4 |  |  |  |  | 134 | $self->SUPER::start_prefix_mapping( $mapping )} | 
| 301 | 1 |  |  |  |  | 34 | next; | 
| 302 |  |  |  |  |  |  | } | 
| 303 |  |  |  |  |  |  |  | 
| 304 | 200 |  |  |  |  | 484 | $self->{ _handlers }->{ $key } = $hdl; | 
| 305 | 200 | 50 |  |  |  | 472 | next unless defined $hdl; | 
| 306 | 200 | 50 |  |  |  | 915 | next if $self->{ _performing }->{ $hdl }++; | 
| 307 | 200 |  |  |  |  | 279 | $switched = 1; | 
| 308 | 200 |  |  |  |  | 644 | $self->set_handler( $hdl ); | 
| 309 |  |  |  |  |  |  | #warn "dispatching start_document for $hdl"; | 
| 310 | 200 |  |  |  |  | 2531 | $self->SUPER::start_document({}); | 
| 311 | 200 |  |  |  |  | 63203 | foreach my $mapping ( values %{$self->{ _prefixmap }} ) { | 
|  | 200 |  |  |  |  | 785 |  | 
| 312 |  |  |  |  |  |  | #warn "supplying deferred @{[%$mapping]} for $hdl"; | 
| 313 | 800 |  |  |  |  | 27223 | $self->SUPER::start_prefix_mapping( $mapping )} | 
| 314 |  |  |  |  |  |  | } | 
| 315 | 401 | 100 |  |  |  | 1774 | $self->set_handler( $activehdl ) if $switched; | 
| 316 |  |  |  |  |  |  | }; | 
| 317 |  |  |  |  |  |  |  | 
| 318 | 6115 | 100 |  |  |  | 27052 | if ( exists $self->{ namespaces }->{$element->{ NamespaceURI }} ) { | 
|  |  | 50 |  |  |  |  |  | 
| 319 | 201 | 50 |  |  |  | 963 | if ( defined (my $hdl = $self->{ _handlers }->{$element->{ NamespaceURI }}) ) { | 
| 320 | 201 |  |  |  |  | 528 | $self->set_handler( $hdl ); | 
| 321 | 201 |  |  |  |  | 2126 | $self->{ _noHandler } = 0; | 
| 322 |  |  |  |  |  |  | }; | 
| 323 |  |  |  |  |  |  | } | 
| 324 |  |  |  |  |  |  | elsif ( exists $self->{ namespaces }->{'*'} ) { | 
| 325 | 0 | 0 |  |  |  | 0 | if ( defined (my $hdl = $self->{ _handlers }->{'*'}) ) { | 
| 326 | 0 |  |  |  |  | 0 | $self->set_handler( $hdl ); | 
| 327 | 0 |  |  |  |  | 0 | $self->{ _noHandler } = 0; | 
| 328 |  |  |  |  |  |  | }; | 
| 329 |  |  |  |  |  |  | } | 
| 330 |  |  |  |  |  |  | else { | 
| 331 | 5914 |  |  |  |  | 7469 | push (@{$self->{ _tagStack }}, $element->{ Name }); | 
|  | 5914 |  |  |  |  | 15020 |  | 
| 332 | 5914 |  |  |  |  | 20378 | return; | 
| 333 |  |  |  |  |  |  | }; | 
| 334 |  |  |  |  |  |  | }; | 
| 335 |  |  |  |  |  |  |  | 
| 336 | 4731 |  |  |  |  | 6319 | push (@{$self->{ _activeStack }}, $element->{ Name }); | 
|  | 4731 |  |  |  |  | 11590 |  | 
| 337 | 4731 | 50 |  |  |  | 12443 | return if $self->{ _noHandler }; | 
| 338 | 4731 |  |  |  |  | 12538 | $self->SUPER::start_element( $element ); | 
| 339 |  |  |  |  |  |  | } | 
| 340 |  |  |  |  |  |  |  | 
| 341 |  |  |  |  |  |  | sub end_element { | 
| 342 | 10645 |  |  | 10645 | 1 | 70362 | my ( $self, $element ) = @_; | 
| 343 |  |  |  |  |  |  | #warn "\t))) ".$element->{ Name }." )))"; | 
| 344 |  |  |  |  |  |  | #warn "\t\t_activeStack: @{$self->{ _activeStack }}\n"; | 
| 345 |  |  |  |  |  |  | #warn "\t\t_tagStack: @{$self->{ _tagStack }}\n"; | 
| 346 | 10645 | 100 |  |  |  | 32515 | if ( $self->{ _activeStack }->[0] ) { | 
|  |  | 50 |  |  |  |  |  | 
| 347 | 4731 | 50 |  |  |  | 11191 | unless ( $self->{ _noHandler } ) { | 
| 348 | 4731 |  |  |  |  | 11856 | $self->SUPER::end_element( $element ); | 
| 349 |  |  |  |  |  |  | }; | 
| 350 | 4731 |  |  |  |  | 523940 | pop (@{$self->{ _activeStack }}); | 
|  | 4731 |  |  |  |  | 10364 |  | 
| 351 | 4731 | 100 |  |  |  | 20273 | return if $self->{ _activeStack }->[0]; | 
| 352 | 201 | 50 |  |  |  | 637 | unless ( $self->{ _noHandler } ) { | 
| 353 | 201 |  |  |  |  | 700 | $self->set_handler(undef); | 
| 354 | 201 |  |  |  |  | 3420 | $self->{ _noHandler } = 1; | 
| 355 |  |  |  |  |  |  | } | 
| 356 |  |  |  |  |  |  | } | 
| 357 |  |  |  |  |  |  | elsif ( $self->{ _tagStack }->[0] ) { | 
| 358 | 5914 |  |  |  |  | 6927 | pop (@{$self->{ _tagStack }}); | 
|  | 5914 |  |  |  |  | 11948 |  | 
| 359 |  |  |  |  |  |  | } | 
| 360 | 6115 | 100 |  |  |  | 25200 | return if $self->{ _tagStack }->[0]; | 
| 361 |  |  |  |  |  |  | # create end_document() event here for all handlers? | 
| 362 |  |  |  |  |  |  | #warn "finalizing for $element->{Name}"; | 
| 363 | 401 |  |  |  |  | 1209 | my $activehdl = $self->get_handler();   # always undef | 
| 364 | 401 | 50 |  |  |  | 3094 | die "handler $activehdl still active" if defined $activehdl; | 
| 365 | 401 |  |  |  |  | 560 | my $switched; | 
| 366 | 401 |  |  |  |  | 597 | while ( my ($key, $value) = each %{$self->{ namespaces }} ) { | 
|  | 602 |  |  |  |  | 2305 |  | 
| 367 | 201 | 50 |  |  |  | 945 | if ( ! defined $value ) { | 
|  |  | 50 |  |  |  |  |  | 
| 368 |  |  |  |  |  |  | #warn "end_element(): case 1 for $key"; | 
| 369 | 0 |  |  |  |  | 0 | $self->{ _result }->{ $key } = ""; | 
| 370 |  |  |  |  |  |  | } | 
| 371 |  |  |  |  |  |  | elsif ( my $hdl = $self->{ _handlers }->{ $key } ) { | 
| 372 | 201 | 50 |  |  |  | 1333 | if ( ! $self->{ _performing }->{ $hdl } ) { | 
|  |  | 100 |  |  |  |  |  | 
| 373 | 0 |  |  |  |  | 0 | warn "already(?) inactive handler $hdl for $key"; | 
| 374 | 0 |  |  |  |  | 0 | delete $self->{ _handlers }->{ $key }; | 
| 375 | 0 |  |  |  |  | 0 | next; | 
| 376 |  |  |  |  |  |  | } | 
| 377 |  |  |  |  |  |  | elsif ( $self->{ _performing }->{ $hdl } < 0 ) {      # always active handler | 
| 378 |  |  |  |  |  |  | #warn "end_element(): case 4 for $key"; | 
| 379 | 1 |  |  |  |  | 3 | $self->{ _result }->{ $key } = undef; | 
| 380 | 1 |  |  |  |  | 3 | next; | 
| 381 |  |  |  |  |  |  | }; | 
| 382 |  |  |  |  |  |  | #warn "end_element(): case 2/3 for $key"; | 
| 383 | 200 |  |  |  |  | 383 | delete $self->{ _handlers }->{ $key }; | 
| 384 | 200 |  |  |  |  | 556 | delete $self->{ _performing }->{ $hdl }; | 
| 385 | 200 |  |  |  |  | 303 | $switched = 1; | 
| 386 | 200 |  |  |  |  | 602 | $self->set_handler( $hdl ); | 
| 387 |  |  |  |  |  |  | # revoke some stored namespace mappings, too? | 
| 388 | 200 |  |  |  |  | 2437 | my $result = $self->SUPER::end_document({}); | 
| 389 |  |  |  |  |  |  | #warn "dispatching end_document for $hdl yielded $result"; | 
| 390 | 200 |  |  |  |  | 15198 | $self->{ _result }->{ $key } = $result; | 
| 391 |  |  |  |  |  |  | } | 
| 392 |  |  |  |  |  |  | else { | 
| 393 | 0 |  |  |  |  | 0 | die " $key not listed as _handler"; | 
| 394 |  |  |  |  |  |  | }; | 
| 395 |  |  |  |  |  |  | }; | 
| 396 | 401 | 100 |  |  |  | 1793 | $self->set_handler( $activehdl ) if $switched; | 
| 397 |  |  |  |  |  |  | } | 
| 398 |  |  |  |  |  |  |  | 
| 399 |  |  |  |  |  |  | sub characters { | 
| 400 | 23211 |  |  | 23211 | 1 | 144324 | my ( $self, $characters ) = @_; | 
| 401 | 23211 | 100 |  |  |  | 53622 | return if $self->{ _noHandler }; | 
| 402 | 22811 |  |  |  |  | 55609 | return $self->SUPER::characters( $characters ); | 
| 403 |  |  |  |  |  |  | } | 
| 404 |  |  |  |  |  |  |  | 
| 405 |  |  |  |  |  |  | sub ignorable_whitespace { | 
| 406 | 0 |  |  | 0 | 1 |  | my ( $self, $characters ) = @_; | 
| 407 | 0 | 0 |  |  |  |  | return if $self->{ _noHandler }; | 
| 408 | 0 |  |  |  |  |  | return $self->SUPER::ignorable_whitespace( $characters ); | 
| 409 |  |  |  |  |  |  | } | 
| 410 |  |  |  |  |  |  |  | 
| 411 |  |  |  |  |  |  | sub comment { | 
| 412 | 0 |  |  | 0 | 1 |  | my ( $self, $comment ) = @_; | 
| 413 | 0 | 0 |  |  |  |  | return if $self->{ _noHandler }; | 
| 414 | 0 |  |  |  |  |  | return $self->SUPER::comment( $comment ); | 
| 415 |  |  |  |  |  |  | } | 
| 416 |  |  |  |  |  |  |  | 
| 417 |  |  |  |  |  |  | sub processing_instruction { | 
| 418 | 0 |  |  | 0 | 1 |  | my ( $self, $pi ) = @_; | 
| 419 | 0 | 0 |  |  |  |  | return if $self->{ _noHandler }; | 
| 420 | 0 |  |  |  |  |  | return $self->SUPER::processing_instruction( $pi ); | 
| 421 |  |  |  |  |  |  | } | 
| 422 |  |  |  |  |  |  |  | 
| 423 |  |  |  |  |  |  | 1; | 
| 424 |  |  |  |  |  |  |  |