File Coverage

blib/lib/XML/Filter/DocSplitter.pm
Criterion Covered Total %
statement 71 72 98.6
branch 18 28 64.2
condition 6 12 50.0
subroutine 13 13 100.0
pod 8 8 100.0
total 116 133 87.2


line stmt bran cond sub pod time code
1             package XML::Filter::DocSplitter;
2             {
3             $XML::Filter::DocSplitter::VERSION = '0.46';
4             }
5             # ABSTRACT: Multipass processing of documents
6              
7              
8 2     2   11 use XML::SAX::Base;
  2         4  
  2         21  
9              
10             @ISA = qw( XML::SAX::Base );
11              
12             @EXPORT_OK = qw( DocSplitter );
13              
14 2     2   104 use strict;
  2         4  
  2         79  
15 2     2   11 use Carp;
  2         3  
  2         168  
16 2     2   10 use XML::SAX::EventMethodMaker qw( sax_event_names compile_missing_methods );
  2         9  
  2         1859  
17              
18              
19             ## Inherited.
20              
21              
22             sub set_aggregator {
23 3     3 1 7 my $self = shift;
24 3         7 $self->{Aggregator} = shift;
25              
26 3 50       30 $self->{AggregatorPassThrough} = XML::SAX::Base->new()
27             unless $self->{AggregatorPassThrough};
28              
29 3         167 $self->{AggregatorPassThrough}->set_handler( $self->{Aggregator} );
30             }
31              
32              
33              
34             sub get_aggregator {
35 6     6 1 10 my $self = shift;
36              
37 6         20 return $self->{Aggregator};
38             }
39              
40              
41              
42             sub set_split_path {
43 3     3 1 8 my $self = shift;
44 3         8 my $pat = $self->{SplitPoint} = shift;
45 3 50       17 $pat = "/$pat"
46             unless substr( $pat, 0, 1 ) eq "/";
47 3         9 $pat = quotemeta $pat;
48              
49 3         21 $pat =~ s{\\\*}{[^/]*}g; ## Hmmm, * will match nodes with 0 length names ""
50 3         9 $pat =~ s{\\/\\/}{/.*/}g;
51 3         13 $pat =~ s{^\\/}{^}g;
52              
53 3         88 $self->{SplitPathRe} = qr/$pat(?!\n)\Z/;
54              
55 3         102 return undef;
56             }
57              
58              
59              
60             sub get_split_path {
61 3     3 1 9 my $self = shift;
62              
63 3         52 return $self->{SplitPoint};
64             }
65              
66              
67             sub _check_stack {
68 12     12   17 my $self = shift;
69              
70 12         15 my $stack = join "/", @{$self->{Stack}};
  12         35  
71              
72 12         133 $stack =~ $self->{SplitPathRe};
73             }
74              
75              
76             sub start_document {
77 3     3 1 304 my $self = shift;
78              
79 3         15 my $aggie = $self->get_aggregator;
80 3 50 33     41 $aggie->start_manifold_document( @_ )
81             if $aggie && $aggie->can( "start_manifold_document" );
82 3 50 33     47 $aggie->set_include_all_roots( 1 )
83             if $aggie && $aggie->can( "set_include_all_roots" );
84              
85 3         13 $aggie->start_document( @_ );
86              
87 3         1255 $self->{Stack} = [];
88 3         10 $self->{Splitting} = 0;
89 3 50       11 $self->set_split_path( "/*/*" )
90             unless defined $self->get_split_path;
91              
92             ## don't pass on the start_document, we'll do that once for each
93             ## record.
94 3         10 return undef;
95             }
96              
97              
98             sub start_element {
99 12     12 1 5560 my $self = shift;
100 12         20 my ( $elt ) = @_;
101              
102 12         17 push @{$self->{Stack}}, $elt->{Name};
  12         35  
103              
104 12 100 66     55 if ( ! $self->{Splitting} && $self->_check_stack ) {
    50          
105 9         17 ++$self->{Splitting};
106 9         42 $self->SUPER::start_document( {} );
107             }
108             elsif ( $self->{Splitting} ) {
109 0         0 ++$self->{Splitting};
110             }
111              
112 12 100       38 if ( $self->{Splitting} ) {
113 9         36 return $self->SUPER::start_element( @_ );
114             }
115              
116 3 50       44 $self->{AggregatorPassThrough}->start_element( @_ )
117             if $self->{AggregatorPassThrough};
118              
119 3         11 return undef;
120             }
121              
122              
123             sub end_element {
124 12     12 1 1622 my $self = shift;
125 12         28 my ( $elt ) = @_;
126              
127 12         14 pop @{$self->{Stack}};
  12         25  
128              
129 12         19 my $r ;
130 12 100       35 if ( $self->{Splitting} ) {
131 9         46 $r = $self->SUPER::end_element( @_ )
132             }
133             else {
134 3 50       20 $r = $self->{AggregatorPassThrough}->end_element( @_ )
135             if $self->{AggregatorPassThrough};
136             }
137              
138 12 100 66     1238 if ( $self->{Splitting} && ! --$self->{Splitting} ) {
139             ## ignore the result code, we'll get it in end_document.
140 9         41 $self->SUPER::end_document( {} );
141             }
142              
143 12         35 return $r;
144             }
145              
146              
147             sub end_document {
148 3     3 1 176 my $self = shift;
149              
150 3         12 my $aggie = $self->get_aggregator;
151              
152 3         5 my $r;
153              
154 3 50       11 if ( $aggie ) {
155 3         18 $r = $aggie->end_document( @_ );
156 3 50       40 $r = $aggie->end_manifold_document( @_ )
157             if $aggie->can( "end_manifold_document" );
158             }
159              
160 3         151 return $r;
161             }
162              
163              
164             compile_missing_methods __PACKAGE__, <<'TPL_END', sax_event_names ;
165             sub {
166             my $self = shift;
167             return $self->SUPER::( @_ )
168             if $self->{Splitting};
169              
170             $self->{AggregatorPassThrough}->( @_ )
171             if $self->{AggregatorPassThrough};
172             }
173             TPL_END
174              
175              
176              
177              
178              
179             1;
180              
181             __END__