1 | package MARC::Record;
|
---|
2 |
|
---|
3 | =head1 NAME
|
---|
4 |
|
---|
5 | MARC::Record - Perl extension for handling MARC records
|
---|
6 |
|
---|
7 | =cut
|
---|
8 |
|
---|
9 | use strict;
|
---|
10 | use integer;
|
---|
11 | eval 'use warnings' if $] >= 5.006;
|
---|
12 |
|
---|
13 | use vars qw( $ERROR );
|
---|
14 |
|
---|
15 | use MARC::Field;
|
---|
16 |
|
---|
17 | =head1 VERSION
|
---|
18 |
|
---|
19 | Version 1.10
|
---|
20 |
|
---|
21 | $Id: Record.pm 3430 2002-09-24 05:17:39Z jrm21 $
|
---|
22 |
|
---|
23 | =cut
|
---|
24 |
|
---|
25 | use vars '$VERSION'; $VERSION = '1.10';
|
---|
26 |
|
---|
27 | use Exporter;
|
---|
28 | use vars qw( @ISA @EXPORTS @EXPORT_OK );
|
---|
29 | @ISA = qw( Exporter );
|
---|
30 | @EXPORTS = qw();
|
---|
31 | @EXPORT_OK = qw( LEADER_LEN );
|
---|
32 |
|
---|
33 | use vars qw( $DEBUG ); $DEBUG = 0;
|
---|
34 |
|
---|
35 | use constant LEADER_LEN => 24;
|
---|
36 |
|
---|
37 | =head1 DESCRIPTION
|
---|
38 |
|
---|
39 | Module for handling MARC records as objects. The file-handling stuff is
|
---|
40 | in MARC::File::*.
|
---|
41 |
|
---|
42 | =head1 EXPORT
|
---|
43 |
|
---|
44 | None.
|
---|
45 |
|
---|
46 | =head1 ERROR HANDLING
|
---|
47 |
|
---|
48 | Any errors generated are stored in C<$MARC::Record::ERROR>.
|
---|
49 | Warnings are kept with the record and accessible in the C<warnings()> method.
|
---|
50 |
|
---|
51 | =head1 METHODS
|
---|
52 |
|
---|
53 | =head2 new()
|
---|
54 |
|
---|
55 | Base constructor for the class. It just returns a completely empty record.
|
---|
56 | To get real data, you'll need to populate it with fields, or use one of
|
---|
57 | the MARC::File::* modules to read from a file.
|
---|
58 |
|
---|
59 | =cut
|
---|
60 |
|
---|
61 | sub new {
|
---|
62 | my $class = shift;
|
---|
63 | $class = ref($class) || $class; # Handle cloning
|
---|
64 | my $self = {
|
---|
65 | _leader => ' ' x 24,
|
---|
66 | _fields => [],
|
---|
67 | _warnings => [],
|
---|
68 | };
|
---|
69 | return bless $self, $class;
|
---|
70 | } # new()
|
---|
71 |
|
---|
72 |
|
---|
73 |
|
---|
74 |
|
---|
75 | =head2 fields()
|
---|
76 |
|
---|
77 | Returns a list of all the fields in the record. The list contains
|
---|
78 | a MARC::Field object for each field in the record.
|
---|
79 |
|
---|
80 | =cut
|
---|
81 |
|
---|
82 | sub fields() {
|
---|
83 | my $self = shift;
|
---|
84 | return @{$self->{_fields}};
|
---|
85 | }
|
---|
86 |
|
---|
87 | =head2 field(tagspec(s))
|
---|
88 |
|
---|
89 | Returns a list of tags that match the field specifier, or in scalar
|
---|
90 | context, just the first matching tag.
|
---|
91 |
|
---|
92 | The field specifier can be a simple number (i.e. "245"), or use the "X"
|
---|
93 | notation of wildcarding (i.e. subject tags are "6XX").
|
---|
94 |
|
---|
95 | =cut
|
---|
96 |
|
---|
97 | my %field_regex;
|
---|
98 |
|
---|
99 | sub field {
|
---|
100 | my $self = shift;
|
---|
101 | my @specs = @_;
|
---|
102 |
|
---|
103 | my @list = ();
|
---|
104 | for my $tag ( @specs ) {
|
---|
105 | my $regex = $field_regex{ $tag };
|
---|
106 |
|
---|
107 | # Compile & stash it if necessary
|
---|
108 | if ( not defined $regex ) {
|
---|
109 | my $pattern = $tag;
|
---|
110 | $pattern =~ s/X/\\d/g;
|
---|
111 | $regex = qr/^$pattern$/;
|
---|
112 | $field_regex{ $tag } = $regex;
|
---|
113 | } # not defined
|
---|
114 |
|
---|
115 | for my $maybe ( $self->fields ) {
|
---|
116 | if ( $maybe->tag =~ $regex ) {
|
---|
117 | return $maybe unless wantarray;
|
---|
118 |
|
---|
119 | push( @list, $maybe );
|
---|
120 | } # if
|
---|
121 | } # for $maybe
|
---|
122 | } # for $tag
|
---|
123 |
|
---|
124 | return @list;
|
---|
125 | }
|
---|
126 |
|
---|
127 | =head2 subfield(tag,subfield)
|
---|
128 |
|
---|
129 | Shortcut method for getting just a subfield for a tag. These are equivalent:
|
---|
130 |
|
---|
131 | my $title = $marc->field(245)->subfield("a");
|
---|
132 | my $title = $marc->subfield(245,"a");
|
---|
133 |
|
---|
134 | If either the field or subfield can't be found, C<undef> is returned.
|
---|
135 |
|
---|
136 | =cut
|
---|
137 |
|
---|
138 | sub subfield($$) {
|
---|
139 | my $self = shift;
|
---|
140 | my $tag = shift;
|
---|
141 | my $subfield = shift;
|
---|
142 |
|
---|
143 | my $field = $self->field($tag) or return undef;
|
---|
144 | return $field->subfield($subfield);
|
---|
145 | } # subfield()
|
---|
146 |
|
---|
147 | =head2 insert_grouped_field(C<$field>)
|
---|
148 |
|
---|
149 | Will insert the specified MARC::Field object into the record in 'grouped
|
---|
150 | order' and return true (1) on success, and false (undef) on failure.
|
---|
151 | For example, if a '650' field is inserted with insert_grouped_field()
|
---|
152 | it will be inserted at the end of the 6XX group of tags. After some discussion
|
---|
153 | on the perl4lib list it was descided that this is ordinarily what you will
|
---|
154 | want. If you would like to insert at a specific point in the record you can use
|
---|
155 | insert_fields_after() and insert_fields_before() methods which are described
|
---|
156 | below.
|
---|
157 |
|
---|
158 | =cut
|
---|
159 |
|
---|
160 | sub insert_grouped_field {
|
---|
161 | my ($self,$new) = @_;
|
---|
162 | _all_parms_are_fields($new) or return(_gripe('Argument must be MARC::Fieldobject'));
|
---|
163 |
|
---|
164 | ## try to find the end of the field group and insert it there
|
---|
165 | my $limit = int($new->tag() / 100);
|
---|
166 | my $found = 0;
|
---|
167 | foreach my $field ($self->fields()) {
|
---|
168 | if ( int($field->tag() / 100) > $limit ) {
|
---|
169 | $self->insert_field_before($field,$new);
|
---|
170 | $found = 1;
|
---|
171 | last;
|
---|
172 | }
|
---|
173 | }
|
---|
174 |
|
---|
175 | ## if we couldn't find the end of the group, then we must not have
|
---|
176 | ## any tags this high yet, so just append it
|
---|
177 | if (!$found) {
|
---|
178 | $self->append_fields($new);
|
---|
179 | }
|
---|
180 |
|
---|
181 | return(1);
|
---|
182 |
|
---|
183 | }
|
---|
184 |
|
---|
185 | =for internal
|
---|
186 |
|
---|
187 | =cut
|
---|
188 |
|
---|
189 | sub _all_parms_are_fields {
|
---|
190 | for ( @_ ) {
|
---|
191 | return 0 unless ref($_) eq 'MARC::Field';
|
---|
192 | }
|
---|
193 | return 1;
|
---|
194 | }
|
---|
195 |
|
---|
196 | =head2 append_field(C<@fields>)
|
---|
197 |
|
---|
198 | Appends the field specified by C<$field> to the end of the record.
|
---|
199 | C<@fields> need to be MARC::Field objects.
|
---|
200 |
|
---|
201 | my $field = MARC::Field->new('590','','','a' => 'My local note.');
|
---|
202 | $record->append_field($field);
|
---|
203 |
|
---|
204 | Returns the number of fields appended.
|
---|
205 |
|
---|
206 | =cut
|
---|
207 |
|
---|
208 | sub append_fields {
|
---|
209 | my $self = shift;
|
---|
210 |
|
---|
211 | _all_parms_are_fields(@_) or return(_gripe('Arguments must be MARC::Field objects'));
|
---|
212 |
|
---|
213 | push(@{ $self->{_fields} }, @_);
|
---|
214 | return scalar @_;
|
---|
215 | }
|
---|
216 |
|
---|
217 | =head2 insert_fields_before($before_field,@new_fields)
|
---|
218 |
|
---|
219 | Inserts the field specified by C<$new_field> before the field C<$before_field>.
|
---|
220 | Returns the number of fields inserted, or undef on failures.
|
---|
221 | Both C<$before_field> and all C<@new_fields> need to be MARC::Field objects.
|
---|
222 |
|
---|
223 | my $before_field = $record->field('260');
|
---|
224 | my $new_field = MARC::Field->new('250','','','a' => '2nd ed.');
|
---|
225 | $record->insert_fields_before($before_field,$new_field);
|
---|
226 |
|
---|
227 | =cut
|
---|
228 |
|
---|
229 | sub insert_fields_before {
|
---|
230 | my $self = shift;
|
---|
231 |
|
---|
232 | _all_parms_are_fields(@_) or return(_gripe('All arguments must be MARC::Field objects'));
|
---|
233 | my ($before,@new) = @_;
|
---|
234 |
|
---|
235 | ## find position of $before
|
---|
236 | my $fields = $self->{_fields};
|
---|
237 | my $pos = 0;
|
---|
238 | foreach my $f (@$fields) {
|
---|
239 | last if ($f == $before);
|
---|
240 | $pos++;
|
---|
241 | }
|
---|
242 |
|
---|
243 | ## insert before $before
|
---|
244 | if ($pos >= @$fields) {
|
---|
245 | return(_gripe("Couldn't find field to insert before"));
|
---|
246 | }
|
---|
247 | splice(@$fields,$pos,0,@new);
|
---|
248 | return scalar @new;
|
---|
249 |
|
---|
250 | }
|
---|
251 |
|
---|
252 | =head2 insert_fields_after($after_field,@new_fields)
|
---|
253 |
|
---|
254 | Identical to L<insert_fields_before()>, but fields are added after C<$after_field>.
|
---|
255 |
|
---|
256 | =cut
|
---|
257 |
|
---|
258 | sub insert_fields_after {
|
---|
259 | my $self = shift;
|
---|
260 |
|
---|
261 | _all_parms_are_fields(@_) or return(_gripe('All arguments must be MARC::Field objects'));
|
---|
262 | my ($after,@new) = @_;
|
---|
263 |
|
---|
264 | ## find position of $after
|
---|
265 | my $fields = $self->{_fields};
|
---|
266 | my $pos = 0;
|
---|
267 | foreach my $f (@$fields) {
|
---|
268 | last if ($f == $after);
|
---|
269 | $pos++;
|
---|
270 | }
|
---|
271 |
|
---|
272 | ## insert after $after
|
---|
273 | if ($pos+1 >= @$fields) {
|
---|
274 | return(_gripe("Couldn't find field to insert after"));
|
---|
275 | }
|
---|
276 | splice(@$fields,$pos+1,0,@new);
|
---|
277 | return scalar @new;
|
---|
278 | }
|
---|
279 |
|
---|
280 | =head2 delete_field(C<$field>)
|
---|
281 |
|
---|
282 | Deletes a field from the record.
|
---|
283 |
|
---|
284 | The field must have been retrieved from the record using the
|
---|
285 | C<field()> method. For example, to delete a 526 tag if it exists:
|
---|
286 |
|
---|
287 | my $tag526 = $marc->field( "526" );
|
---|
288 | if ( $tag526 ) {
|
---|
289 | $marc->delete_field( $tag526 );
|
---|
290 | }
|
---|
291 |
|
---|
292 | C<delete_field()> returns the number of fields that were deleted.
|
---|
293 | This shouldn't be 0 unless you didn't get the tag properly.
|
---|
294 |
|
---|
295 | =cut
|
---|
296 |
|
---|
297 | sub delete_field {
|
---|
298 | my $self = shift;
|
---|
299 | my $deleter = shift;
|
---|
300 | my $list = $self->{_fields};
|
---|
301 |
|
---|
302 | my $old_count = @$list;
|
---|
303 | @$list = grep { $_ != $deleter } @$list;
|
---|
304 | return $old_count - @$list;
|
---|
305 | }
|
---|
306 |
|
---|
307 | =head2 as_usmarc()
|
---|
308 |
|
---|
309 | This is a wrapper around C<MARC::File::USMARC::encode()> for compatibility with
|
---|
310 | older versions of MARC::Record.
|
---|
311 |
|
---|
312 | =cut
|
---|
313 |
|
---|
314 | sub as_usmarc() {
|
---|
315 | my $self = shift;
|
---|
316 |
|
---|
317 | require MARC::File::USMARC;
|
---|
318 |
|
---|
319 | return MARC::File::USMARC::encode( $self );
|
---|
320 | }
|
---|
321 |
|
---|
322 | =head2 as_formatted()
|
---|
323 |
|
---|
324 | Returns a pretty string for printing in a MARC dump.
|
---|
325 |
|
---|
326 | =cut
|
---|
327 |
|
---|
328 | sub as_formatted() {
|
---|
329 | my $self = shift;
|
---|
330 |
|
---|
331 | my @lines = ( "LDR " . ($self->{_leader} || "") );
|
---|
332 | for my $field ( @{$self->{_fields}} ) {
|
---|
333 | push( @lines, $field->as_formatted() );
|
---|
334 | }
|
---|
335 |
|
---|
336 | return join( "\n", @lines );
|
---|
337 | } # as_formatted
|
---|
338 |
|
---|
339 | =head2 title()
|
---|
340 |
|
---|
341 | Returns the title from the 245 tag.
|
---|
342 | Note that it is a string, not a MARC::Field record.
|
---|
343 |
|
---|
344 | =cut
|
---|
345 |
|
---|
346 | sub title() {
|
---|
347 | my $self = shift;
|
---|
348 |
|
---|
349 | my $field = $self->field(245) or return "<no 245 tag found>";
|
---|
350 |
|
---|
351 | return $field->as_string;
|
---|
352 | }
|
---|
353 |
|
---|
354 | =head2 author()
|
---|
355 |
|
---|
356 | Returns the author from the 100, 110 or 111 tag.
|
---|
357 | Note that it is a string, not a MARC::Field record.
|
---|
358 |
|
---|
359 | =cut
|
---|
360 |
|
---|
361 | sub author() {
|
---|
362 | my $self = shift;
|
---|
363 |
|
---|
364 | for my $tag ( qw( 100 110 111 ) ) {
|
---|
365 | my $field = $self->field($tag);
|
---|
366 | return $field->as_string() if $field;
|
---|
367 | }
|
---|
368 |
|
---|
369 | return "<No author tag found>";
|
---|
370 | }
|
---|
371 |
|
---|
372 | =head2 leader([text])
|
---|
373 |
|
---|
374 | Returns the leader for the record. Sets the leader if I<text> is defined.
|
---|
375 | No error checking is done on the validity of the leader.
|
---|
376 |
|
---|
377 | =cut
|
---|
378 |
|
---|
379 | sub leader {
|
---|
380 | my $self = shift;
|
---|
381 | my $text = shift;
|
---|
382 |
|
---|
383 | if ( defined $text ) {
|
---|
384 | (length($text) eq 24)
|
---|
385 | or $self->_warn( "Leader must be 24 bytes long" );
|
---|
386 | $self->{_leader} = $text;
|
---|
387 | } # set the leader
|
---|
388 |
|
---|
389 | return $self->{_leader};
|
---|
390 | } # leader()
|
---|
391 |
|
---|
392 | =head2 set_leader_lengths( $reclen, $baseaddr )
|
---|
393 |
|
---|
394 | Internal function for updating the leader's length and base address.
|
---|
395 |
|
---|
396 | =cut
|
---|
397 |
|
---|
398 | sub set_leader_lengths {
|
---|
399 | my $self = shift;
|
---|
400 | my $reclen = shift;
|
---|
401 | my $baseaddr = shift;
|
---|
402 | substr($self->{_leader},0,5) = sprintf("%05d",$reclen);
|
---|
403 | substr($self->{_leader},12,5) = sprintf("%05d",$baseaddr);
|
---|
404 | }
|
---|
405 |
|
---|
406 | =head2 clone( [field specs] )
|
---|
407 |
|
---|
408 | The C<clone()> method makes a copy of an existing MARC record and returns
|
---|
409 | the new version. Note that you cannot just say:
|
---|
410 |
|
---|
411 | my $newmarc = $oldmarc;
|
---|
412 |
|
---|
413 | This just makes a copy of the reference, not a new object. You must use
|
---|
414 | the C<clone()> method like so:
|
---|
415 |
|
---|
416 | my $newmarc = $oldmarc->clone;
|
---|
417 |
|
---|
418 | You can also specify field specs to filter down only a
|
---|
419 | certain subset of fields. For instance, if you only wanted the
|
---|
420 | title and ISBN tags from a record, you could do this:
|
---|
421 |
|
---|
422 | my $small_marc = $marc->clone( 245, '020' );
|
---|
423 |
|
---|
424 | The order of the fields is preserved as it was in the original record.
|
---|
425 |
|
---|
426 | =cut
|
---|
427 |
|
---|
428 | sub clone {
|
---|
429 | my $self = shift;
|
---|
430 | my @keeper_tags = @_;
|
---|
431 |
|
---|
432 | my $clone = $self->new();
|
---|
433 | $clone->{_leader} = $self->{_leader};
|
---|
434 |
|
---|
435 | my $filtered = @keeper_tags ? [$self->field( @keeper_tags )] : undef;
|
---|
436 |
|
---|
437 | for my $field ( $self->fields() ) {
|
---|
438 | if ( !$filtered || (grep {$field==$_} @$filtered ) ) {
|
---|
439 | $clone->add_fields( $field->clone );
|
---|
440 | }
|
---|
441 | }
|
---|
442 |
|
---|
443 | # XXX FIX THIS $clone->update_leader();
|
---|
444 |
|
---|
445 | return $clone;
|
---|
446 | }
|
---|
447 |
|
---|
448 | =head2 warnings()
|
---|
449 |
|
---|
450 | Returns the warnings that were created when the record was read.
|
---|
451 | These are things like "Invalid indicators converted to blanks".
|
---|
452 |
|
---|
453 | The warnings are items that you might be interested in, or might
|
---|
454 | not. It depends on how stringently you're checking data. If
|
---|
455 | you're doing some grunt data analysis, you probably don't care.
|
---|
456 |
|
---|
457 | A side effect of calling warnings() is that the warning buffer will
|
---|
458 | be cleared.
|
---|
459 |
|
---|
460 | =cut
|
---|
461 |
|
---|
462 | sub warnings() {
|
---|
463 | my $self = shift;
|
---|
464 | my @warnings = @{$self->{_warnings}};
|
---|
465 | $self->{_warnings} = [];
|
---|
466 | return @warnings;
|
---|
467 | }
|
---|
468 |
|
---|
469 | =head2 add_fields()
|
---|
470 |
|
---|
471 | C<add_fields()> is now deprecated, and users are encouraged to use C<append_field()>,
|
---|
472 | C<insert_field_after()>, and C<insert_field_before()> since they do what you want
|
---|
473 | probably. It is still here though, for backwards compatability.
|
---|
474 |
|
---|
475 | C<add_fields()> adds MARC::Field objects to the end of the list. Returns the
|
---|
476 | number of fields added, or C<undef> if there was an error.
|
---|
477 |
|
---|
478 | There are three ways of calling C<add_fields()> to add data to the record.
|
---|
479 |
|
---|
480 | =over 4
|
---|
481 |
|
---|
482 | =item 1 Create a MARC::Field object and add it
|
---|
483 |
|
---|
484 | my $author = MARC::Field->new(
|
---|
485 | 100, "1", " ", a => "Arnosky, Jim."
|
---|
486 | );
|
---|
487 | $marc->add_fields( $author );
|
---|
488 |
|
---|
489 | =item 2 Add the data fields directly, and let C<add_fields()> take care of the objectifying.
|
---|
490 |
|
---|
491 | $marc->add_fields(
|
---|
492 | 245, "1", "0",
|
---|
493 | a => "Raccoons and ripe corn /",
|
---|
494 | c => "Jim Arnosky.",
|
---|
495 | );
|
---|
496 |
|
---|
497 | =item 3 Same as #2 above, but pass multiple fields of data in anonymous lists
|
---|
498 |
|
---|
499 | $marc->add_fields(
|
---|
500 | [ 250, " ", " ", a => "1st ed." ],
|
---|
501 | [ 650, "1", " ", a => "Raccoons." ],
|
---|
502 | );
|
---|
503 |
|
---|
504 | =back
|
---|
505 |
|
---|
506 | =cut
|
---|
507 |
|
---|
508 | sub add_fields {
|
---|
509 | my $self = shift;
|
---|
510 |
|
---|
511 | my $nfields = 0;
|
---|
512 | my $fields = $self->{_fields};
|
---|
513 |
|
---|
514 | while ( my $parm = shift ) {
|
---|
515 | # User handed us a list of data (most common possibility)
|
---|
516 | if ( ref($parm) eq "" ) {
|
---|
517 | my $field = MARC::Field->new( $parm, @_ )
|
---|
518 | or return _gripe( $MARC::Field::ERROR );
|
---|
519 | push( @$fields, $field );
|
---|
520 | ++$nfields;
|
---|
521 | last; # Bail out, we're done eating parms
|
---|
522 |
|
---|
523 | # User handed us an object.
|
---|
524 | } elsif ( ref($parm) eq "MARC::Field" ) {
|
---|
525 | push( @$fields, $parm );
|
---|
526 | ++$nfields;
|
---|
527 |
|
---|
528 | # User handed us an anonymous list of parms
|
---|
529 | } elsif ( ref($parm) eq "ARRAY" ) {
|
---|
530 | my $field = MARC::Field->new(@$parm)
|
---|
531 | or return _gripe( $MARC::Field::ERROR );
|
---|
532 | push( @$fields, $field );
|
---|
533 | ++$nfields;
|
---|
534 |
|
---|
535 | } else {
|
---|
536 | return _gripe( "Unknown parm of type", ref($parm), " passed to add_fields()" );
|
---|
537 | } # if
|
---|
538 |
|
---|
539 | } # while
|
---|
540 |
|
---|
541 | return $nfields;
|
---|
542 | }
|
---|
543 |
|
---|
544 | =head2 new_from_usmarc( $marcblob )
|
---|
545 |
|
---|
546 | This is a wrapper around C<MARC::File::USMARC::decode()> for compatibility with
|
---|
547 | older versions of MARC::Record.
|
---|
548 |
|
---|
549 | =cut
|
---|
550 |
|
---|
551 | sub new_from_usmarc {
|
---|
552 | my $blob = shift;
|
---|
553 | $blob = shift if (ref($blob) || ($blob eq "MARC::Record"));
|
---|
554 |
|
---|
555 | require MARC::File::USMARC;
|
---|
556 |
|
---|
557 | return MARC::File::USMARC::decode( $blob );
|
---|
558 | }
|
---|
559 |
|
---|
560 |
|
---|
561 | # NOTE: _warn is an object method
|
---|
562 | sub _warn {
|
---|
563 | my $self = shift;
|
---|
564 |
|
---|
565 | push( @{$self->{_warnings}}, join( "", @_ ) );
|
---|
566 | }
|
---|
567 |
|
---|
568 |
|
---|
569 | # NOTE: _gripe is NOT an object method
|
---|
570 | sub _gripe {
|
---|
571 | $ERROR = join( "", @_ );
|
---|
572 |
|
---|
573 | warn $ERROR;
|
---|
574 |
|
---|
575 | return undef;
|
---|
576 | }
|
---|
577 |
|
---|
578 |
|
---|
579 | 1;
|
---|
580 |
|
---|
581 | __END__
|
---|
582 |
|
---|
583 | =head1 DESIGN NOTES
|
---|
584 |
|
---|
585 | A brief discussion of why MARC::Record is done the way it is:
|
---|
586 |
|
---|
587 | =over 4
|
---|
588 |
|
---|
589 | =item * It's built for quick prototyping
|
---|
590 |
|
---|
591 | One of the areas Perl excels is in allowing the programmer to
|
---|
592 | create easy solutions quickly. MARC::Record is designed along
|
---|
593 | those same lines. You want a program to dump all the 6XX
|
---|
594 | tags in a file? MARC::Record is your friend.
|
---|
595 |
|
---|
596 | =item * It's built for extensibility
|
---|
597 |
|
---|
598 | Currently, I'm using MARC::Record for analyzing bibliographic
|
---|
599 | data, but who knows what might happen in the future? MARC::Record
|
---|
600 | needs to be just as adept at authority data, too.
|
---|
601 |
|
---|
602 | =item * It's designed around accessor methods
|
---|
603 |
|
---|
604 | I use method calls everywhere, and I expect calling programs to do
|
---|
605 | the same, rather than accessing internal data directly. If you
|
---|
606 | access an object's hash fields on your own, future releases may
|
---|
607 | break your code.
|
---|
608 |
|
---|
609 | =item * It's not built for speed
|
---|
610 |
|
---|
611 | One of the tradeoffs in using accessor methods is some overhead
|
---|
612 | in the method calls. Is this slow? I don't know, I haven't measured.
|
---|
613 | I would suggest that if you're a cycle junkie that you use
|
---|
614 | Benchmark.pm to check to see where your bottlenecks are, and then
|
---|
615 | decide if MARC::Record is for you.
|
---|
616 |
|
---|
617 | =back
|
---|
618 |
|
---|
619 | =head1 RELATED MODULES
|
---|
620 |
|
---|
621 | L<MARC::Record>, L<MARC::Lint>
|
---|
622 |
|
---|
623 | =head1 SEE ALSO
|
---|
624 |
|
---|
625 | =over 4
|
---|
626 |
|
---|
627 | =item * perl4lib (L<http://www.rice.edu/perl4lib/>)
|
---|
628 |
|
---|
629 | A mailing list devoted to the use of Perl in libraries.
|
---|
630 |
|
---|
631 | =item * Library Of Congress MARC pages (L<http://www.loc.gov/marc/>)
|
---|
632 |
|
---|
633 | The definitive source for all things MARC.
|
---|
634 |
|
---|
635 |
|
---|
636 | =item * I<Understanding MARC Bibliographic> (L<http://lcweb.loc.gov/marc/umb/>)
|
---|
637 |
|
---|
638 | Online version of the free booklet. An excellent overview of the MARC format. Essential.
|
---|
639 |
|
---|
640 |
|
---|
641 | =item * Tag Of The Month (L<http://www.tagofthemonth.com/>)
|
---|
642 |
|
---|
643 | Follett Software Company's
|
---|
644 | (L<http://www.fsc.follett.com/>) monthly discussion of various MARC tags.
|
---|
645 |
|
---|
646 | =back
|
---|
647 |
|
---|
648 | =head1 TODO
|
---|
649 |
|
---|
650 | =over 4
|
---|
651 |
|
---|
652 | =item * Incorporate MARC.pm in the distribution.
|
---|
653 |
|
---|
654 | Combine MARC.pm and MARC::* into one distribution.
|
---|
655 |
|
---|
656 | =item * Podify MARC.pm
|
---|
657 |
|
---|
658 | =item * Allow regexes across the entire tag
|
---|
659 |
|
---|
660 | Imagine something like this:
|
---|
661 |
|
---|
662 | my @sears_headings = $marc->tag_grep( /Sears/ );
|
---|
663 |
|
---|
664 | (from Mike O'Regan)
|
---|
665 |
|
---|
666 | =item * Insert a field in an arbitrary place in the record
|
---|
667 |
|
---|
668 | =item * Allow deleting a field
|
---|
669 |
|
---|
670 | for my $field ( $record->field( "856" ) ) {
|
---|
671 | $record->delete_field( $field ) unless useful($field);
|
---|
672 | } # for
|
---|
673 |
|
---|
674 | (from Anne Highsmith [email protected])
|
---|
675 |
|
---|
676 |
|
---|
677 | =item * Modifying an existing field
|
---|
678 |
|
---|
679 | =back
|
---|
680 |
|
---|
681 | =head1 IDEAS
|
---|
682 |
|
---|
683 | Ideas are things that have been considered, but nobody's actually asked for.
|
---|
684 |
|
---|
685 | =over 4
|
---|
686 |
|
---|
687 | =item * Create multiple output formats.
|
---|
688 |
|
---|
689 | These could be ASCII, XML, or MarcMaker.
|
---|
690 |
|
---|
691 | =back
|
---|
692 |
|
---|
693 | =head1 LICENSE
|
---|
694 |
|
---|
695 | This code may be distributed under the same terms as Perl itself.
|
---|
696 |
|
---|
697 | Please note that these modules are not products of or supported by the
|
---|
698 | employers of the various contributors to the code.
|
---|
699 |
|
---|
700 | =head1 AUTHOR
|
---|
701 |
|
---|
702 | Andy Lester, E<lt>[email protected]<gt> or E<lt>[email protected]<gt>
|
---|
703 |
|
---|
704 | =cut
|
---|
705 |
|
---|