File Coverage

blib/lib/App/MARC/Filter.pm
Criterion Covered Total %
statement 139 142 97.8
branch 40 50 80.0
condition 15 15 100.0
subroutine 20 20 100.0
pod 2 2 100.0
total 216 229 94.3


line stmt bran cond sub pod time code
1             package App::MARC::Filter;
2              
3 4     4   183593 use strict;
  4         10  
  4         175  
4 4     4   56 use warnings;
  4         8  
  4         224  
5              
6 4     4   2308 use Class::Utils qw(set_params);
  4         70601  
  4         101  
7 4     4   379 use English;
  4         9  
  4         28  
8 4     4   2311 use Error::Pure qw(err);
  4         16  
  4         1215  
9 4     4   4797 use Getopt::Std;
  4         10353  
  4         606  
10 4     4   35 use List::Util 1.33 qw(any none);
  4         99  
  4         355  
11 4     4   2852 use MARC::File::XML (BinaryEncoding => 'utf8', RecordFormat => 'MARC21');
  4         795337  
  4         67  
12 4     4   2764 use MARC::Leader;
  4         49653  
  4         197  
13 4     4   2305 use MARC::Leader::Utils qw(material_type);
  4         4717  
  4         80  
14 4     4   315 use Readonly;
  4         9  
  4         184  
15 4     4   1969 use Unicode::UTF8 qw(encode_utf8 decode_utf8);
  4         2717  
  4         6328  
16              
17             Readonly::Array our @OUTPUT_FORMATS => qw(ascii xml);
18             Readonly::Array our @CONTROL_FIELDS => qw(001 003 005 006 007 008);
19              
20             our $VERSION = 0.06;
21              
22             $| = 1;
23              
24             # Constructor.
25             sub new {
26 16     16 1 740655 my ($class, @params) = @_;
27              
28             # Create object.
29 16         67 my $self = bless {}, $class;
30              
31             # Process parameters.
32 16         81 set_params($self, @params);
33              
34             # Object.
35 15         144 return $self;
36             }
37              
38             # Run.
39             sub run {
40 14     14 1 26 my $self = shift;
41              
42             # Process arguments.
43 14         115 $self->{'_opts'} = {
44             'h' => 0,
45             'n' => undef,
46             'o' => 'xml',
47             'r' => 0,
48             'v' => 0,
49             };
50 14 100 100     74 if (! getopts('hn:o:rv', $self->{'_opts'})
      100        
51             || $self->{'_opts'}->{'h'}
52             || @ARGV < 3) {
53              
54 4         237 $self->_usage;
55 4         11 return 1;
56             }
57 10         461 $self->{'_marc_xml_file'} = shift @ARGV;
58 10         58 $self->{'_marc_field'} = shift @ARGV;
59 10 100 100     154 if ($self->{'_marc_field'} ne 'leader'
      100        
60             && $self->{'_marc_field'} ne 'material_type'
61 43     43   305 && none { $_ eq $self->{'_marc_field'} } @CONTROL_FIELDS) {
62              
63 7         70 $self->{'_marc_subfield'} = shift @ARGV;
64             }
65 10         70 $self->{'_marc_value'} = shift @ARGV;
66 10 100       34 if (! defined $self->{'_marc_value'}) {
67 1         7 $self->_usage;
68 1         3 return 1;
69             } else {
70 9         49 $self->{'_marc_value'} = decode_utf8($self->{'_marc_value'});
71             }
72              
73             # Check output format.
74 9 100   18   62 if (none { $self->{'_opts'}->{'o'} eq $_ } @OUTPUT_FORMATS) {
  18         136  
75 1         15 err "Output format '$self->{'_opts'}->{'o'}' doesn't supported.";
76             }
77              
78 8         138 my $marc_file = MARC::File::XML->in($self->{'_marc_xml_file'});
79 8         710 my @ret;
80 8         16 my $num = 1;
81 8         21 $self->{'_num_found'} = 0;
82 8         32 $self->{'_printed'} = 0;
83 8         16 my $previous_record;
84 8         23 while (1) {
85 16 100 100     78 if (defined $self->{'_opts'}->{'n'} && int($self->{'_opts'}->{'n'}) == $self->{'_num_found'}) {
86 1         3 last;
87             }
88              
89 15         30 my $record = eval {
90 15         58 $marc_file->next;
91             };
92 15 100       44884 if ($EVAL_ERROR) {
93 1 50       83 print STDERR "Cannot process '$num' record. ".
94             (
95             defined $previous_record
96             ? "Previous record is ".encode_utf8($previous_record->title)."\n"
97             : ''
98             );
99 1         36 print STDERR "Error: $EVAL_ERROR\n";
100 1         5 next;
101             }
102 14 100       45 if (! defined $record) {
103 7         20 last;
104             }
105 7         15 $previous_record = $record;
106              
107             # Leader.
108 7 100       86 if ($self->{'_marc_field'} eq 'leader') {
    100          
    100          
109 1         5 my $leader = $record->leader;
110 1         13 my $record_to_print = $self->_match($record, $leader);
111 1         5 $self->_print($record_to_print);
112              
113             # Material type.
114             } elsif ($self->{'_marc_field'} eq 'material_type') {
115 1         5 my $leader_string = $record->leader;
116 1         19 my $leader = MARC::Leader->new->parse($leader_string);
117 1         859 my $material_type = material_type($leader);
118 1         111 my $record_to_print = $self->_match($record, $material_type);
119 1         4 $self->_print($record_to_print);
120              
121             # Control fields.
122 25     25   240 } elsif (any { $self->{'_marc_field'} eq $_ } @CONTROL_FIELDS) {
123 1         13 my $control_field = $record->field($self->{'_marc_field'});
124 1         108 my $record_to_print = $self->_match($record, $control_field->as_string);
125 1         4 $self->_print($record_to_print);
126              
127             # Other.
128             } else {
129 4         43 my @fields = $record->field($self->{'_marc_field'});
130 4         945 my $record_to_print;
131 4         14 foreach my $field (@fields) {
132 4         25 my @subfield_values = $field->subfield($self->{'_marc_subfield'});
133 4         138 foreach my $subfield_value (@subfield_values) {
134 4         45 $record_to_print = $self->_match($record, $subfield_value);
135 4 100       12 if (defined $record_to_print) {
136 3         8 last;
137             }
138             }
139 4 100       15 if (defined $record_to_print) {
140 3         8 last;
141             }
142             }
143 4         16 $self->_print($record_to_print);
144             }
145              
146 7 50       60 if ($self->{'_opts'}->{'v'}) {
147 0         0 print STDERR '.';
148             }
149              
150 7         17 $num++;
151             }
152              
153 8 100       27 if ($self->{'_printed'}) {
154 6 50       19 if ($self->{'_opts'}->{'o'} eq 'xml') {
155 6         24 print MARC::File::XML::footer()."\n";
156             }
157             }
158            
159 8         476 return 0;
160             }
161              
162             sub _match {
163 7     7   41 my ($self, $record, $value) = @_;
164              
165 7 50       24 if (! defined $value) {
166 0         0 return;
167             }
168              
169 7 100       27 if ($self->{'_opts'}->{'r'}) {
170 1 50       32 if ($value =~ m/$self->{'_marc_value'}/ms) {
171 1         3 $self->{'_num_found'}++;
172 1         4 return $record;
173             }
174             } else {
175 6 100       44 if ($value eq $self->{'_marc_value'}) {
176 5         9 $self->{'_num_found'}++;
177 5         15 return $record;
178             }
179             }
180              
181 1         4 return;
182             }
183              
184             sub _print {
185 7     7   16 my ($self, $record) = @_;
186              
187 7 100       22 if (! defined $record) {
188 1         3 return;
189             }
190              
191 6 50       23 if (! $self->{'_printed'}) {
192 6 50       20 if ($self->{'_opts'}->{'o'} eq 'xml') {
193 6         31 print MARC::File::XML::header()."\n";
194             }
195             }
196              
197 6 50       566 if ($self->{'_opts'}->{'o'} eq 'xml') {
    0          
198 6         31 print encode_utf8(MARC::File::XML::record($record))."\n";
199             } elsif ($self->{'_opts'}->{'o'} eq 'ascii') {
200 0         0 print encode_utf8($record->as_formatted)."\n";
201             }
202              
203 6         14900 $self->{'_printed'}++;
204              
205 6         37 return;
206             }
207              
208             sub _usage {
209 5     5   9 my $self = shift;
210              
211 5         242 print STDERR "Usage: $0 [-h] [-n num] [-o format] [-r] [-v] [--version] marc_xml_file search_item [sub_search_item] value\n";
212 5         156 print STDERR "\t-h\t\tPrint help.\n";
213 5         52 print STDERR "\t-n num\t\tNumber of records to output (default value is all records).\n";
214 5         46 print STDERR "\t-o format\tOutput MARC format. Possible formats are ascii, xml.\n";
215 5         46 print STDERR "\t-r\t\tUse value as Perl regexp.\n";
216 5         46 print STDERR "\t-v\t\tVerbose mode.\n";
217 5         48 print STDERR "\t--version\tPrint version.\n";
218 5         47 print STDERR "\tmarc_xml_file\tMARC XML file.\n";
219 5         41 print STDERR "\tsearch_item\tSearch item.\n";
220 5         41 print STDERR "\tsub_search_item\tSearch sub item (required in case of MARC field).\n";
221 5         43 print STDERR "\tvalue\t\tValue to filter.\n";
222              
223 5         14 return;
224             }
225              
226             1;
227              
228              
229             __END__
230              
231             =pod
232              
233             =encoding utf8
234              
235             =head1 NAME
236              
237             App::MARC::Filter - Base class for marc-count script.
238              
239             =head1 SYNOPSIS
240              
241             use App::MARC::Filter;
242              
243             my $app = App::MARC::Filter->new;
244             my $exit_code = $app->run;
245              
246             =head1 METHODS
247              
248             =head2 C<new>
249              
250             my $app = App::MARC::Filter->new;
251              
252             Constructor.
253              
254             Returns instance of object.
255              
256             =head2 C<run>
257              
258             my $exit_code = $app->run;
259              
260             Run.
261              
262             Returns 1 for error, 0 for success.
263              
264             =head1 ERRORS
265              
266             new():
267             From Class::Utils::set_params():
268             Unknown parameter '%s'.
269              
270             run():
271             Output format '%s' doesn't supported.
272              
273             =head1 EXAMPLE
274              
275             =for comment filename=filter_by_field015a.pl
276              
277             use strict;
278             use warnings;
279              
280             use App::MARC::Filter;
281             use IO::Barf qw(barf);
282             use File::Temp qw(tempfile);
283             use MIME::Base64;
284              
285             # Content.
286             my $marc_xml_example = <<'END';
287             PD94bWwgdmVyc2lvbiA9ICIxLjAiIGVuY29kaW5nID0gIlVURi04Ij8+CiAgPGNvbGxlY3Rpb24g
288             eG1sbnM9Imh0dHA6Ly93d3cubG9jLmdvdi9NQVJDMjEvc2xpbSIKeG1sbnM6eHNpPSJodHRwOi8v
289             d3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIKeHNpOnNjaGVtYUxvY2F0aW9uPSJo
290             dHRwOi8vd3d3LmxvYy5nb3YvTUFSQzIxL3NsaW0KaHR0cDovL3d3dy5sb2MuZ292L3N0YW5kYXJk
291             cy9tYXJjeG1sL3NjaGVtYS9NQVJDMjFzbGltLnhzZCI+CiAgICA8cmVjb3JkIHhtbG5zPSJodHRw
292             Oi8vd3d3LmxvYy5nb3YvTUFSQzIxL3NsaW0iCnhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcv
293             MjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiCnhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3d3dy5s
294             b2MuZ292L01BUkMyMS9zbGltCmh0dHA6Ly93d3cubG9jLmdvdi9zdGFuZGFyZHMvbWFyY3htbC9z
295             Y2hlbWEvTUFSQzIxc2xpbS54c2QiPgogICAgICA8bGVhZGVyPiAgICAgbmFtIGEyMiAgICAgICAg
296             NDUwMDwvbGVhZGVyPgogICAgICA8Y29udHJvbGZpZWxkIHRhZz0iMDAxIj5jazgzMDAwNzg8L2Nv
297             bnRyb2xmaWVsZD4KICAgICAgPGNvbnRyb2xmaWVsZCB0YWc9IjAwMyI+Q1ogUHJOSzwvY29udHJv
298             bGZpZWxkPgogICAgICA8Y29udHJvbGZpZWxkIHRhZz0iMDA1Ij4yMDIxMDMwOTEyMTk1MS4wPC9j
299             b250cm9sZmllbGQ+CiAgICAgIDxjb250cm9sZmllbGQgdGFnPSIwMDciPnR1PC9jb250cm9sZmll
300             bGQ+CiAgICAgIDxjb250cm9sZmllbGQgdGFnPSIwMDgiPjgzMDMwNHMxOTgyICAgIHhyIGEgICAg
301             ICAgICB1MHwwIHwgY3plPC9jb250cm9sZmllbGQ+CiAgICAgIDxkYXRhZmllbGQgdGFnPSIwMTUi
302             IGluZDE9IiAiIGluZDI9IiAiPgogICAgICAgIDxzdWJmaWVsZCBjb2RlPSJhIj5jbmIwMDAwMDAw
303             OTY8L3N1YmZpZWxkPgogICAgICA8L2RhdGFmaWVsZD4KICAgICAgPGRhdGFmaWVsZCB0YWc9IjAy
304             MCIgaW5kMT0iICIgaW5kMj0iICI+CiAgICAgICAgPHN1YmZpZWxkIGNvZGU9InEiPihCcm/Fvi4p
305             IDo8L3N1YmZpZWxkPgogICAgICAgIDxzdWJmaWVsZCBjb2RlPSJjIj45IEvEjXM8L3N1YmZpZWxk
306             PgogICAgICA8L2RhdGFmaWVsZD4KICAgICAgPGRhdGFmaWVsZCB0YWc9IjAzNSIgaW5kMT0iICIg
307             aW5kMj0iICI+CiAgICAgICAgPHN1YmZpZWxkIGNvZGU9ImEiPihPQ29MQykzOTU2MDY2NDwvc3Vi
308             ZmllbGQ+CiAgICAgIDwvZGF0YWZpZWxkPgogICAgICA8ZGF0YWZpZWxkIHRhZz0iMDQwIiBpbmQx
309             PSIgIiBpbmQyPSIgIj4KICAgICAgICA8c3ViZmllbGQgY29kZT0iYSI+QUJBMDAxPC9zdWJmaWVs
310             ZD4KICAgICAgICA8c3ViZmllbGQgY29kZT0iYiI+Y3plPC9zdWJmaWVsZD4KICAgICAgICA8c3Vi
311             ZmllbGQgY29kZT0iZCI+QUJBMDAxPC9zdWJmaWVsZD4KICAgICAgPC9kYXRhZmllbGQ+CiAgICAg
312             IDxkYXRhZmllbGQgdGFnPSIwODAiIGluZDE9IiAiIGluZDI9IiAiPgogICAgICAgIDxzdWJmaWVs
313             ZCBjb2RlPSJhIj4zNTIvMzUzPC9zdWJmaWVsZD4KICAgICAgICA8c3ViZmllbGQgY29kZT0iMiI+
314             dW5kZWY8L3N1YmZpZWxkPgogICAgICA8L2RhdGFmaWVsZD4KICAgICAgPGRhdGFmaWVsZCB0YWc9
315             IjA4MCIgaW5kMT0iICIgaW5kMj0iICI+CiAgICAgICAgPHN1YmZpZWxkIGNvZGU9ImEiPjMzOC40
316             Njwvc3ViZmllbGQ+CiAgICAgICAgPHN1YmZpZWxkIGNvZGU9IjIiPnVuZGVmPC9zdWJmaWVsZD4K
317             ICAgICAgPC9kYXRhZmllbGQ+CiAgICAgIDxkYXRhZmllbGQgdGFnPSIxMDAiIGluZDE9IjEiIGlu
318             ZDI9IiAiPgogICAgICAgIDxzdWJmaWVsZCBjb2RlPSJhIj5HYWJyaWVsLCBWbGFkaXNsYXY8L3N1
319             YmZpZWxkPgogICAgICAgIDxzdWJmaWVsZCBjb2RlPSI3Ij5temsyMDE0ODUyNzIzPC9zdWJmaWVs
320             ZD4KICAgICAgICA8c3ViZmllbGQgY29kZT0iNCI+YXV0PC9zdWJmaWVsZD4KICAgICAgPC9kYXRh
321             ZmllbGQ+CiAgICAgIDxkYXRhZmllbGQgdGFnPSIyNDUiIGluZDE9IjEiIGluZDI9IjAiPgogICAg
322             ICAgIDxzdWJmaWVsZCBjb2RlPSJhIj5TbHXFvmJ5IHYgc3lzdMOpbXUgbsOhcm9kbsOtY2ggdsO9
323             Ym9yxa8gOjwvc3ViZmllbGQ+CiAgICAgICAgPHN1YmZpZWxkIGNvZGU9ImIiPnZ5YnJhbsOpIGth
324             cGl0b2x5IDogdXLEjWVubyBwcm8gcG9zbC4gZmFrLiBvYmNob2Ruw60sIG9ib3IgRWtvbm9taWth
325             IHNsdcW+ZWIgYSBjZXN0b3Zuw61obyBydWNodSAvPC9zdWJmaWVsZD4KICAgICAgICA8c3ViZmll
326             bGQgY29kZT0iYyI+VmxhZGlzbGF2IEdhYnJpZWwsIExhZGlzbGF2IFphcGFkbG88L3N1YmZpZWxk
327             PgogICAgICA8L2RhdGFmaWVsZD4KICAgICAgPGRhdGFmaWVsZCB0YWc9IjI1MCIgaW5kMT0iICIg
328             aW5kMj0iICI+CiAgICAgICAgPHN1YmZpZWxkIGNvZGU9ImEiPjEuIHZ5ZC48L3N1YmZpZWxkPgog
329             ICAgICA8L2RhdGFmaWVsZD4KICAgICAgPGRhdGFmaWVsZCB0YWc9IjI2MCIgaW5kMT0iICIgaW5k
330             Mj0iICI+CiAgICAgICAgPHN1YmZpZWxkIGNvZGU9ImEiPlByYWhhIDo8L3N1YmZpZWxkPgogICAg
331             ICAgIDxzdWJmaWVsZCBjb2RlPSJiIj5TUE4sPC9zdWJmaWVsZD4KICAgICAgICA8c3ViZmllbGQg
332             Y29kZT0iYyI+MTk4Mjwvc3ViZmllbGQ+CiAgICAgICAgPHN1YmZpZWxkIGNvZGU9ImUiPihQxZnD
333             rWJyYW0gOjwvc3ViZmllbGQ+CiAgICAgICAgPHN1YmZpZWxkIGNvZGU9ImYiPlRaIDY2KTwvc3Vi
334             ZmllbGQ+CiAgICAgIDwvZGF0YWZpZWxkPgogICAgICA8ZGF0YWZpZWxkIHRhZz0iMzAwIiBpbmQx
335             PSIgIiBpbmQyPSIgIj4KICAgICAgICA8c3ViZmllbGQgY29kZT0iYSI+MTkyIHMuIDo8L3N1YmZp
336             ZWxkPgogICAgICAgIDxzdWJmaWVsZCBjb2RlPSJiIj5zY2jDqW1hdGEgOzwvc3ViZmllbGQ+CiAg
337             ICAgICAgPHN1YmZpZWxkIGNvZGU9ImMiPjMwIGNtPC9zdWJmaWVsZD4KICAgICAgPC9kYXRhZmll
338             bGQ+CiAgICAgIDxkYXRhZmllbGQgdGFnPSI1MDAiIGluZDE9IiAiIGluZDI9IiAiPgogICAgICAg
339             IDxzdWJmaWVsZCBjb2RlPSJhIj5Sb3ptbi48L3N1YmZpZWxkPgogICAgICA8L2RhdGFmaWVsZD4K
340             ICAgICAgPGRhdGFmaWVsZCB0YWc9IjUwMCIgaW5kMT0iICIgaW5kMj0iICI+CiAgICAgICAgPHN1
341             YmZpZWxkIGNvZGU9ImEiPjMwMCB2w710Ljwvc3ViZmllbGQ+CiAgICAgIDwvZGF0YWZpZWxkPgog
342             ICAgICA8ZGF0YWZpZWxkIHRhZz0iNTAwIiBpbmQxPSIgIiBpbmQyPSIgIj4KICAgICAgICA8c3Vi
343             ZmllbGQgY29kZT0iYSI+S2FwLiA0LiBuYXBzLiBSxa/FvmVuYSBEdWRvdsOhLCBrYXAuIDguIGpl
344             IHNlc3QuIHogcMWZw61zcMSbdmvFryByxa96LiBhdXRvcsWvPC9zdWJmaWVsZD4KICAgICAgPC9k
345             YXRhZmllbGQ+CiAgICAgIDxkYXRhZmllbGQgdGFnPSI1NTAiIGluZDE9IiAiIGluZDI9IiAiPgog
346             ICAgICAgIDxzdWJmaWVsZCBjb2RlPSJhIj5WeWRhdmF0ZWw6IFbFoEUgdiBQcmF6ZTwvc3ViZmll
347             bGQ+CiAgICAgIDwvZGF0YWZpZWxkPgogICAgICA8ZGF0YWZpZWxkIHRhZz0iNjU1IiBpbmQxPSIg
348             IiBpbmQyPSI3Ij4KICAgICAgICA8c3ViZmllbGQgY29kZT0iYSI+dcSNZWJuaWNlIHZ5c29rw71j
349             aCDFoWtvbDwvc3ViZmllbGQ+CiAgICAgICAgPHN1YmZpZWxkIGNvZGU9IjciPmZkMTMzNzcyPC9z
350             dWJmaWVsZD4KICAgICAgICA8c3ViZmllbGQgY29kZT0iMiI+Y3plbmFzPC9zdWJmaWVsZD4KICAg
351             ICAgPC9kYXRhZmllbGQ+CiAgICAgIDxkYXRhZmllbGQgdGFnPSI3MDAiIGluZDE9IjEiIGluZDI9
352             IiAiPgogICAgICAgIDxzdWJmaWVsZCBjb2RlPSJhIj5aYXBhZGxvLCBMYWRpc2xhdjwvc3ViZmll
353             bGQ+CiAgICAgICAgPHN1YmZpZWxkIGNvZGU9IjQiPmF1dDwvc3ViZmllbGQ+CiAgICAgIDwvZGF0
354             YWZpZWxkPgogICAgICA8ZGF0YWZpZWxkIHRhZz0iNzEwIiBpbmQxPSIyIiBpbmQyPSIgIj4KICAg
355             ICAgICA8c3ViZmllbGQgY29kZT0iYSI+Vnlzb2vDoSDFoWtvbGEgZWtvbm9taWNrw6EgdiBQcmF6
356             ZTwvc3ViZmllbGQ+CiAgICAgICAgPHN1YmZpZWxkIGNvZGU9IjciPmtuMjAwMTA3MDk0MDM8L3N1
357             YmZpZWxkPgogICAgICA8L2RhdGFmaWVsZD4KICAgICAgPGRhdGFmaWVsZCB0YWc9Ijk5OCIgaW5k
358             MT0iICIgaW5kMj0iICI+CiAgICAgICAgPHN1YmZpZWxkIGNvZGU9ImEiPmh0dHA6Ly9hbGVwaC5u
359             a3AuY3ovRi8/ZnVuYz1kaXJlY3QmYW1wO2RvY19udW1iZXI9MDAwMDAwMDk2JmFtcDtsb2NhbF9i
360             YXNlPUNOQjwvc3ViZmllbGQ+CiAgICAgIDwvZGF0YWZpZWxkPgogICAgPC9yZWNvcmQ+Cgo8cmVj
361             b3JkIHhtbG5zPSJodHRwOi8vd3d3LmxvYy5nb3YvTUFSQzIxL3NsaW0iCnhtbG5zOnhzaT0iaHR0
362             cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiCnhzaTpzY2hlbWFMb2NhdGlv
363             bj0iaHR0cDovL3d3dy5sb2MuZ292L01BUkMyMS9zbGltCmh0dHA6Ly93d3cubG9jLmdvdi9zdGFu
364             ZGFyZHMvbWFyY3htbC9zY2hlbWEvTUFSQzIxc2xpbS54c2QiPgogIDxsZWFkZXI+ICAgICBuYW0g
365             YTIyICAgICAgICA0NTAwPC9sZWFkZXI+CiAgPGNvbnRyb2xmaWVsZCB0YWc9IjAwMSI+Y2s4MzAw
366             MDgwPC9jb250cm9sZmllbGQ+CiAgPGNvbnRyb2xmaWVsZCB0YWc9IjAwMyI+Q1ogUHJOSzwvY29u
367             dHJvbGZpZWxkPgogIDxjb250cm9sZmllbGQgdGFnPSIwMDUiPjIwMDUwNTE3MDk0MjEyLjA8L2Nv
368             bnRyb2xmaWVsZD4KICA8Y29udHJvbGZpZWxkIHRhZz0iMDA3Ij50dTwvY29udHJvbGZpZWxkPgog
369             IDxjb250cm9sZmllbGQgdGFnPSIwMDgiPjgzMDMxNnMxOTgzICAgIHhyICAgICAgICAgICB1MHww
370             ICAgY3plPC9jb250cm9sZmllbGQ+CiAgPGRhdGFmaWVsZCB0YWc9IjAxNSIgaW5kMT0iICIgaW5k
371             Mj0iICI+CiAgICA8c3ViZmllbGQgY29kZT0iYSI+Y25iMDAwMDAwMDk4PC9zdWJmaWVsZD4KICA8
372             L2RhdGFmaWVsZD4KICA8ZGF0YWZpZWxkIHRhZz0iMDIwIiBpbmQxPSIgIiBpbmQyPSIgIj4KICAg
373             IDxzdWJmaWVsZCBjb2RlPSJxIj4oQnJvxb4uKSA6PC9zdWJmaWVsZD4KICAgIDxzdWJmaWVsZCBj
374             b2RlPSJjIj4zMCBLxI1zPC9zdWJmaWVsZD4KICA8L2RhdGFmaWVsZD4KICA8ZGF0YWZpZWxkIHRh
375             Zz0iMDM1IiBpbmQxPSIgIiBpbmQyPSIgIj4KICAgIDxzdWJmaWVsZCBjb2RlPSJhIj4oT0NvTEMp
376             Mzk1NjA2ODg8L3N1YmZpZWxkPgogIDwvZGF0YWZpZWxkPgogIDxkYXRhZmllbGQgdGFnPSIwNDAi
377             IGluZDE9IiAiIGluZDI9IiAiPgogICAgPHN1YmZpZWxkIGNvZGU9ImEiPkFCQTAwMTwvc3ViZmll
378             bGQ+CiAgICA8c3ViZmllbGQgY29kZT0iYiI+Y3plPC9zdWJmaWVsZD4KICAgIDxzdWJmaWVsZCBj
379             b2RlPSJkIj5BQkEwMDE8L3N1YmZpZWxkPgogIDwvZGF0YWZpZWxkPgogIDxkYXRhZmllbGQgdGFn
380             PSIwODAiIGluZDE9IiAiIGluZDI9IiAiPgogICAgPHN1YmZpZWxkIGNvZGU9ImEiPjMzOS45MjM8
381             L3N1YmZpZWxkPgogICAgPHN1YmZpZWxkIGNvZGU9IjIiPnVuZGVmPC9zdWJmaWVsZD4KICA8L2Rh
382             dGFmaWVsZD4KICA8ZGF0YWZpZWxkIHRhZz0iMDgwIiBpbmQxPSIgIiBpbmQyPSIgIj4KICAgIDxz
383             dWJmaWVsZCBjb2RlPSJhIj4zMzguNDU8L3N1YmZpZWxkPgogICAgPHN1YmZpZWxkIGNvZGU9IjIi
384             PnVuZGVmPC9zdWJmaWVsZD4KICA8L2RhdGFmaWVsZD4KICA8ZGF0YWZpZWxkIHRhZz0iMTAwIiBp
385             bmQxPSIxIiBpbmQyPSIgIj4KICAgIDxzdWJmaWVsZCBjb2RlPSJhIj5WbGFkeWthLCBKb3NlZjwv
386             c3ViZmllbGQ+CiAgICA8c3ViZmllbGQgY29kZT0iNyI+angyMDA1MDYyODAzNjwvc3ViZmllbGQ+
387             CiAgICA8c3ViZmllbGQgY29kZT0iNCI+YXV0PC9zdWJmaWVsZD4KICA8L2RhdGFmaWVsZD4KICA8
388             ZGF0YWZpZWxkIHRhZz0iMjQ1IiBpbmQxPSIxIiBpbmQyPSIwIj4KICAgIDxzdWJmaWVsZCBjb2Rl
389             PSJhIj5Ww712b2ogYSBwbMOhbnkgcm96dm9qZSBwcsWvbXlzbHUgZXZyb3Bza8O9Y2ggemVtw60g
390             UlZIUCAxOTc2LTE5ODUgLzwvc3ViZmllbGQ+CiAgICA8c3ViZmllbGQgY29kZT0iYyI+dnlwcmFj
391             LiBKb3NlZiBWbGFkeWthPC9zdWJmaWVsZD4KICA8L2RhdGFmaWVsZD4KICA8ZGF0YWZpZWxkIHRh
392             Zz0iMjYwIiBpbmQxPSIgIiBpbmQyPSIgIj4KICAgIDxzdWJmaWVsZCBjb2RlPSJhIj5QcmFoYSA6
393             PC9zdWJmaWVsZD4KICAgIDxzdWJmaWVsZCBjb2RlPSJiIj7DmlZURUksPC9zdWJmaWVsZD4KICAg
394             IDxzdWJmaWVsZCBjb2RlPSJjIj4xOTgzPC9zdWJmaWVsZD4KICA8L2RhdGFmaWVsZD4KICA8ZGF0
395             YWZpZWxkIHRhZz0iMzAwIiBpbmQxPSIgIiBpbmQyPSIgIj4KICAgIDxzdWJmaWVsZCBjb2RlPSJh
396             Ij41NSBzLiA6PC9zdWJmaWVsZD4KICAgIDxzdWJmaWVsZCBjb2RlPSJiIj50Yi4gOzwvc3ViZmll
397             bGQ+CiAgICA8c3ViZmllbGQgY29kZT0iYyI+MzAgY208L3N1YmZpZWxkPgogIDwvZGF0YWZpZWxk
398             PgogIDxkYXRhZmllbGQgdGFnPSI0OTAiIGluZDE9IjEiIGluZDI9IiAiPgogICAgPHN1YmZpZWxk
399             IGNvZGU9ImEiPlB1Ymxpa2FjZSBTSVZPIDs8L3N1YmZpZWxkPgogICAgPHN1YmZpZWxkIGNvZGU9
400             InYiPjE4OTQ8L3N1YmZpZWxkPgogIDwvZGF0YWZpZWxkPgogIDxkYXRhZmllbGQgdGFnPSI1MDAi
401             IGluZDE9IiAiIGluZDI9IiAiPgogICAgPHN1YmZpZWxkIGNvZGU9ImEiPlDFmWVobC4gbGl0PC9z
402             dWJmaWVsZD4KICA8L2RhdGFmaWVsZD4KICA8ZGF0YWZpZWxkIHRhZz0iNTAwIiBpbmQxPSIgIiBp
403             bmQyPSIgIj4KICAgIDxzdWJmaWVsZCBjb2RlPSJhIj5Sb3ptbi48L3N1YmZpZWxkPgogIDwvZGF0
404             YWZpZWxkPgogIDxkYXRhZmllbGQgdGFnPSI1MDAiIGluZDE9IiAiIGluZDI9IiAiPgogICAgPHN1
405             YmZpZWxkIGNvZGU9ImEiPlBvem4uPC9zdWJmaWVsZD4KICA8L2RhdGFmaWVsZD4KICA8ZGF0YWZp
406             ZWxkIHRhZz0iODMwIiBpbmQxPSIgIiBpbmQyPSIwIj4KICAgIDxzdWJmaWVsZCBjb2RlPSJhIj5Q
407             dWJsaWthY2UgU0lWTzwvc3ViZmllbGQ+CiAgPC9kYXRhZmllbGQ+CiAgPGRhdGFmaWVsZCB0YWc9
408             Ijk5OCIgaW5kMT0iICIgaW5kMj0iICI+CiAgICA8c3ViZmllbGQgY29kZT0iYSI+aHR0cDovL2Fs
409             ZXBoLm5rcC5jei9GLz9mdW5jPWRpcmVjdCZhbXA7ZG9jX251bWJlcj0wMDAwMDAwOTgmYW1wO2xv
410             Y2FsX2Jhc2U9Q05CPC9zdWJmaWVsZD4KICA8L2RhdGFmaWVsZD4KPC9yZWNvcmQ+Cgo8L2NvbGxl
411             Y3Rpb24+Cg==
412             END
413              
414             my ($temp_file, $temp_file_fh) = tempfile();
415              
416             barf($temp_file_fh, decode_base64($marc_xml_example));
417              
418             # Arguments.
419             @ARGV = (
420             $temp_file,
421             '015',
422             'a',
423             'cnb000000096',
424             );
425              
426             # Run.
427             exit App::MARC::Filter->new->run;
428              
429             # Output:
430             # <?xml version="1.0" encoding="UTF-8"?>
431             # <collection
432             # xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
433             # xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"
434             # xmlns="http://www.loc.gov/MARC21/slim">
435             #
436             # <record>
437             # <leader> nam a22 4500</leader>
438             # <controlfield tag="001">ck8300078</controlfield>
439             # <controlfield tag="003">CZ PrNK</controlfield>
440             # <controlfield tag="005">20210309121951.0</controlfield>
441             # <controlfield tag="007">tu</controlfield>
442             # <controlfield tag="008">830304s1982 xr a u0|0 | cze</controlfield>
443             # <datafield tag="015" ind1=" " ind2=" ">
444             # <subfield code="a">cnb000000096</subfield>
445             # </datafield>
446             # <datafield tag="020" ind1=" " ind2=" ">
447             # <subfield code="q">(Brož.) :</subfield>
448             # <subfield code="c">9 Kčs</subfield>
449             # </datafield>
450             # <datafield tag="035" ind1=" " ind2=" ">
451             # <subfield code="a">(OCoLC)39560664</subfield>
452             # </datafield>
453             # <datafield tag="040" ind1=" " ind2=" ">
454             # <subfield code="a">ABA001</subfield>
455             # <subfield code="b">cze</subfield>
456             # <subfield code="d">ABA001</subfield>
457             # </datafield>
458             # <datafield tag="080" ind1=" " ind2=" ">
459             # <subfield code="a">352/353</subfield>
460             # <subfield code="2">undef</subfield>
461             # </datafield>
462             # <datafield tag="080" ind1=" " ind2=" ">
463             # <subfield code="a">338.46</subfield>
464             # <subfield code="2">undef</subfield>
465             # </datafield>
466             # <datafield tag="100" ind1="1" ind2=" ">
467             # <subfield code="a">Gabriel, Vladislav</subfield>
468             # <subfield code="7">mzk2014852723</subfield>
469             # <subfield code="4">aut</subfield>
470             # </datafield>
471             # <datafield tag="245" ind1="1" ind2="0">
472             # <subfield code="a">Služby v systému národních výborů :</subfield>
473             # <subfield code="b">vybrané kapitoly : určeno pro posl. fak. obchodní, obor Ekonomika služeb a cestovního ruchu /</subfield>
474             # <subfield code="c">Vladislav Gabriel, Ladislav Zapadlo</subfield>
475             # </datafield>
476             # <datafield tag="250" ind1=" " ind2=" ">
477             # <subfield code="a">1. vyd.</subfield>
478             # </datafield>
479             # <datafield tag="260" ind1=" " ind2=" ">
480             # <subfield code="a">Praha :</subfield>
481             # <subfield code="b">SPN,</subfield>
482             # <subfield code="c">1982</subfield>
483             # <subfield code="e">(Příbram :</subfield>
484             # <subfield code="f">TZ 66)</subfield>
485             # </datafield>
486             # <datafield tag="300" ind1=" " ind2=" ">
487             # <subfield code="a">192 s. :</subfield>
488             # <subfield code="b">schémata ;</subfield>
489             # <subfield code="c">30 cm</subfield>
490             # </datafield>
491             # <datafield tag="500" ind1=" " ind2=" ">
492             # <subfield code="a">Rozmn.</subfield>
493             # </datafield>
494             # <datafield tag="500" ind1=" " ind2=" ">
495             # <subfield code="a">300 výt.</subfield>
496             # </datafield>
497             # <datafield tag="500" ind1=" " ind2=" ">
498             # <subfield code="a">Kap. 4. naps. Růžena Dudová, kap. 8. je sest. z příspěvků růz. autorů</subfield>
499             # </datafield>
500             # <datafield tag="550" ind1=" " ind2=" ">
501             # <subfield code="a">Vydavatel: VŠE v Praze</subfield>
502             # </datafield>
503             # <datafield tag="655" ind1=" " ind2="7">
504             # <subfield code="a">učebnice vysokých škol</subfield>
505             # <subfield code="7">fd133772</subfield>
506             # <subfield code="2">czenas</subfield>
507             # </datafield>
508             # <datafield tag="700" ind1="1" ind2=" ">
509             # <subfield code="a">Zapadlo, Ladislav</subfield>
510             # <subfield code="4">aut</subfield>
511             # </datafield>
512             # <datafield tag="710" ind1="2" ind2=" ">
513             # <subfield code="a">Vysoká škola ekonomická v Praze</subfield>
514             # <subfield code="7">kn20010709403</subfield>
515             # </datafield>
516             # <datafield tag="998" ind1=" " ind2=" ">
517             # <subfield code="a">http://aleph.nkp.cz/F/?func=direct&amp;doc_number=000000096&amp;local_base=CNB</subfield>
518             # </datafield>
519             # </record>
520             #
521             # </collection>
522              
523             =head1 DEPENDENCIES
524              
525             L<Class::Utils>,
526             L<English>,
527             L<Error::Pure>,
528             L<Getopt::Std>,
529             L<List::Util>,
530             L<MARC::File::XML>,
531             L<Readonly>,
532             L<Unicode::UTF8>.
533              
534             =head1 REPOSITORY
535              
536             L<https://github.com/michal-josef-spacek/App-MARC-Filter>
537              
538             =head1 AUTHOR
539              
540             Michal Josef Špaček L<mailto:skim@cpan.org>
541              
542             L<http://skim.cz>
543              
544             =head1 LICENSE AND COPYRIGHT
545              
546             © 2022-2025 Michal Josef Špaček
547              
548             BSD 2-Clause License
549              
550             =head1 VERSION
551              
552             0.06
553              
554             =cut