File Coverage

blib/lib/ETR/XML/SAX/FilterHandler.pm
Criterion Covered Total %
statement 9 53 16.9
branch 0 20 0.0
condition n/a
subroutine 3 11 27.2
pod 1 8 12.5
total 13 92 14.1


line stmt bran cond sub pod time code
1             package ETR::XML::SAX::FilterHandler;
2              
3 1     1   17513 use 5.006;
  1         2  
  1         39  
4 1     1   4 use strict;
  1         4  
  1         28  
5 1     1   3 use warnings;
  1         5  
  1         567  
6              
7             =head1 NAME
8              
9             ETR::XML::SAX::FilterHandler - A handler to filter large XML files or streams
10              
11             =head1 VERSION
12              
13             Version 0.02
14              
15             =cut
16              
17             our $VERSION = '0.02';
18              
19             =head1 SYNOPSIS
20              
21             use ETR::XML::SAX::FilterHandler;
22             use XML::SAX::ParserFactory;
23             my $hnd = ETR::XML::SAX::FilterHandler->new({
24              
25             root => books,
26             record => {
27             entry => 1,
28             other_entry => 1
29             },
30             find_data => {
31             "Title 1" => 1,
32             "Title 3" => 1,
33             Oth => 1
34             }
35             });
36             my $str=<
37            
38            
39             Title 1
40            
41            
42             Other title
43            
44            
45             Title 2
46            
47            
48             Title 3
49            
50            
51             EOS
52             my $factory = XML::SAX::ParserFactory->parser(Handler => $hnd);
53              
54             # XML source:
55              
56             # from string:
57             print "\nfrom string:\n======\n";
58             $factory->parse_string($str);
59              
60             # from file
61             print "\nfrom file:\n======\n";
62             $factory->parse_file("books.xml");
63              
64             # from standard input
65             print "\nfrom standard input:\n======\n";
66             $factory->parse_file(*STDIN);
67              
68             Every time you should receive the following result:
69              
70            
71            
72             Title 1
73            
74            
75             Other title
76            
77            
78             Title 3
79            
80            
81              
82             =head1 DESCRIPTION
83              
84             Parse large XML files or streams without being loaded into memory and print
85             to the standard output only the fragments that match to the filtering rules
86             specified by the two parameters: record and find_data.
87              
88             =head1 METHODS
89              
90             =head2 new()
91              
92             new({
93             root => document_root,
94             record => {
95             entry1 => 1,
96             entry2 => 1,
97             ...
98             entrym => 1
99             }
100             find_data => {
101             str1 => 1,
102             str2 => 1,
103             ...
104             strn => 1
105             }
106             })
107              
108             =head3 Parameters:
109              
110             root: a string used to enclose the whole document;
111              
112             record: is a hash with element names considered as being record
113             delimiters;
114              
115             find_data: the record is printed out if at least one string from this hash
116             matches to the xml data.
117              
118             Note: The values from the two hashes have to be set to 1, just to force key to be
119             defined.
120              
121             =cut
122              
123             sub new {
124 0     0 1   my ($type, $arg) = @_;
125             #print Dumper($arg->{tag}{entry});
126             #print "...filter\n";
127 0           return bless {
128             buf => "",
129             open => 0,
130             level => 0,
131             found => 0,
132             isdata => 0,
133             indent => " ",
134             record => $arg->{record},
135             find_data => $arg->{find_data},
136             root => $arg->{root}
137             }, $type;
138             }
139              
140             sub start_document{
141 0     0 0   my $self = shift;
142 0 0         print "<$self->{root}>\n" if defined $self->{root};
143             }
144              
145             sub end_document{
146 0     0 0   my $self = shift;
147             #print "End doc\n";
148 0 0         print "{root}>\n" if defined $self->{root};
149             }
150              
151             sub start_element{
152 0     0 0   my ($self, $el) = @_;
153             #print "Starting el $el->{Name} \n";
154             #print "...record","\n" if defined $self->{record}{$el->{Name}};
155 0 0         if (defined $self->{record}{$el->{Name}}){
    0          
156 0           $self->{buf} = "<$el->{Name}";
157             #print Dumper $el->{Attributes};
158 0           $self->add_attr($el->{Attributes});
159 0           $self->{open} = 1;
160 0           $self->{level} = 0;
161 0           $self->{found} = 0;
162 0           $self->{isdata} = 0;
163             }
164             elsif($self->{open}){
165 0           $self->{level}++;
166             #chomp($el->{Name});
167             #print $el->{Name},"\n";
168             #print $self->{level},"\n";
169 0           $self->indent;
170 0           $self->{buf} .= "<$el->{Name}" ;
171 0           $self->add_attr($el->{Attributes});
172             }
173             }
174              
175             sub end_element{
176 0     0 0   my ($self, $el) = @_;
177             #print "Ending element $el->{Name}\n";
178 0 0         if (defined $self->{record}{$el->{Name}}){
    0          
179 0           $self->{buf} .= "{Name}>\n";
180 0           $self->{open} = 0;
181             #$self->{buf} =~ s/^\s*\n//mg;
182 0 0         print $self->{buf} if $self->{found};
183             }
184             elsif ($self->{open}){
185 0 0         if($self->{isdata}){
186 0           $self->{isdata} = 0;
187             }
188             else{
189 0           $self->{level}--;
190 0           $self->indent;
191             }
192 0           $self->{level}--;
193 0           $self->{buf} .= "{Name}>\n";
194             }
195             }
196              
197             sub characters{
198 0     0 0   my($self, $char) = @_;
199 0           chomp($char->{Data});
200 0 0         if($char->{Data} ne ""){
201 0           chomp($self->{buf});
202 0           $self->{isdata} = 1;
203             }
204              
205 0           $self->{buf} .= $char->{Data};
206 0           my $find = $self->{find_data};
207 0           foreach(keys (%$find)){
208             #print "key=$_","\n";
209 0 0         $self->{found} = 1 if $char->{Data} =~ $_;
210             }
211             }
212              
213             sub indent{
214 0     0 0   my $self = shift;
215 0           $self->{buf} .= ($self->{indent} x $self->{level});
216             }
217             sub add_attr{
218 0     0 0   my ($self, $attr) = @_;
219             #print Dumper($attr);
220 0           foreach (keys( %$attr)){
221 0           $self->{buf} .= " $attr->{$_}{Name}=\"$attr->{$_}{Value}\"";
222             }
223 0           $self->{buf} .= ">\n";
224             }
225              
226              
227              
228              
229             =head1 AUTHOR
230              
231             Daniel Necsoiu, Ericsson, C<< >>
232              
233             =head1 BUGS
234              
235             Please report any bugs or feature requests to C, or through
236             the web interface at L. I will be notified, and then you'll
237             automatically be notified of progress on your bug as I make changes.
238              
239              
240              
241              
242             =head1 SUPPORT
243              
244             You can find documentation for this module with the perldoc command.
245              
246             perldoc ETR::XML::SAX::FilterHandler
247              
248              
249             You can also look for information at:
250              
251             =over 4
252              
253             =item * RT: CPAN's request tracker (report bugs here)
254              
255             L
256              
257             =item * AnnoCPAN: Annotated CPAN documentation
258              
259             L
260              
261             =item * CPAN Ratings
262              
263             L
264              
265             =item * Search CPAN
266              
267             L
268              
269             =back
270              
271              
272             =head1 ACKNOWLEDGEMENTS
273              
274              
275             =head1 LICENSE AND COPYRIGHT
276              
277             Copyright 2015 Daniel Necsoiu, Ericsson.
278              
279             This program is free software; you can redistribute it and/or modify it
280             under the terms of either: the GNU General Public License as published
281             by the Free Software Foundation; or the Artistic License.
282              
283             See L for more information.
284              
285              
286             =cut
287              
288             1; # End of ETR::XML::SAX::FilterHandler