MARC::Record(3pm)

๐Ÿ“ฆ
version 2.0.7 ยท 5 versions
, in ubuntu noble, ubuntu resolute, ubuntu stonking

๐Ÿ’– MARC::Record ๐Ÿ’–

okay bestie, sit DOWN. this is MARC::Record from the User Contributed Perl Documentation, section 3pm, and it's literally the module that lets you handle MARC records as objects. we're gonna go through every last bit of it together, no skimming, no skipping, periodt. ๐ŸŽ€โœจ


๐ŸŒŸ VERSION ๐ŸŒŸ

Version 2.0.7. that's the one, that's the girl. ๐Ÿ’…


๐Ÿฆ‹ DESCRIPTION ๐Ÿฆ‹

So like โ€” this is the module for handling MARC records as objects. that's the whole vibe. ๐Ÿซถ

And the file-handling stuff? Not here, babe. That lives in MARC::File::*. different department, different floor, iykyk.


๐Ÿ˜ญ ERROR HANDLING ๐Ÿ˜ญ

  • any error that gets generated? it's stored in $MARC::Record::ERROR. that's where you go looking when something's off. ๐Ÿ”
  • warnings are a whole different energy โ€” they're kept with the record, and you get at them with the warnings() method.

๐ŸŒฑ CONSTRUCTORS ๐ŸŒฑ

โœจ new()

The base constructor for the class, and honestly? she gives nothing. she just returns a completely empty record. no fields, no data, a blank canvas, main character before the glow-up. ๐Ÿ’€

So like, to get real data in there you've got two options:

  • populate it yourself with fields, or
  • use one of the MARC::File::* modules to read from a file.

โœจ new_from_usmarc( $marcblob [, \&filter_func($tagno,$tagdata)] )

This one's a wrapper around MARC::File::USMARC::decode(), and the reason it exists is compatibility with older versions of MARC::Record. it's giving "keeping the old friendships alive". ๐Ÿฅน

The wanted_func() is optional. See MARC::File::USMARC::decode for details โ€” that's where the tea is.


๐ŸŽ€ COMMON FIELD RETRIEVAL METHODS ๐ŸŽ€

Okay so here's a lil cluster of convenience methods for the data fields everybody's always grabbing. Super important: each of these returns strings, not MARC::Field objects. ๐Ÿงš

And if the appropriate field or subfield isn't found, you get back empty strings. which is different from the field() / subfield() methods, those ones hand you back undef when something's missing. The assumption (and it's a fair one) is that these convenience methods are for quick & dirty reports where you do NOT want to be messing around checking if something is undef. respect. ๐Ÿ™ˆ

Also also โ€” no punctuation cleanup is done. none. zero. if the 245a is "Programming Perl / ", then that's exactly what you get back, trailing slash and all. not "Programming Perl". you want it cleaned, that's a you problem, bestie. ๐Ÿ’…

โœจ title()

Returns the title from the 245 tag.

โœจ title_proper()

Returns the title proper from the 245 tag, subfields a, n and p.

โœจ author()

Returns the author from the 100, 110 or 111 tag.

โœจ edition()

Returns the edition from the 250 tag, subfield a.

โœจ publication_date()

Returns the publication date from the 260 tag, subfield c.


๐Ÿ’œ FIELD & SUBFIELD ACCESS METHODS ๐Ÿ’œ

โœจ fields()

Returns a list of all the fields in the record. The list contains a MARC::Field object for each field in the record. the whole squad, assembled. ๐Ÿ”ฅ

โœจ field( tagspec(s) )

Returns a list of tags that match the field specifier, or an empty list if nothing matched.

In scalar context, it returns the first matching tag, or undef if nothing matched.

The field specifier can be:

  • a simple number, i.e. 245, or
  • the . notation of wildcarding โ€” i.e. subject tags are 6...

โœจ subfield( $tag, $subfield )

Shortcut method for getting just a subfield for a tag. These two are equivalent, like literally the same thing, pick your fighter:

my $title = $marc->field('245')->subfield("a");
my $title = $marc->subfield('245',"a");

If either the field or the subfield can't be found, undef is returned. no field, no subfield, no data, no drama. ๐Ÿ˜ญ

โœจ append_fields( @fields )

Appends the field specified by $field to the end of the record. @fields need to be MARC::Field objects. no imposters. ๐Ÿ’…

my $field = MARC::Field->new('590','','','a' => 'My local note.');
$record->append_fields($field);

Returns the number of fields appended. count 'em.

โœจ insert_fields_before( $before_field, @new_fields )

Inserts the field specified by $new_field before the field $before_field.

Returns the number of fields inserted, or undef on failures. Both $before_field and all @new_fields need to be MARC::Field objects. If they are not, an exception will be thrown. so like, don't try it. ๐Ÿ™ˆ

my $before_field = $record->field('260');
my $new_field = MARC::Field->new('250','','','a' => '2nd ed.');
$record->insert_fields_before($before_field,$new_field);

โœจ insert_fields_after( $after_field, @new_fields )

Identical to insert_fields_before(), except the fields are added after $after_field. remember bestie: $after_field and any new fields must be valid MARC::Field objects or else an exception will be thrown. same rules, other direction. ๐Ÿ”„

โœจ insert_fields_ordered( @new_fields )

Will insert fields in strictly numerical order. So a 008 will be filed after a 001 field. neat, tidy, organized โ€” the good girl of field insertion. โœจ

See insert_grouped_field() for an additional ordering if you want a different flavor.

โœจ insert_grouped_field( $field )

Will insert the specified MARC::Field object into the record in grouped order, and return true (1) on success, and false (undef) on failure.

my $field = MARC::Field->new( '510', 'Indexed by Google.' );
$record->insert_grouped_field( $field );

So for example, if a 650 field is inserted with insert_grouped_field(), it will be inserted at the end of the 6XX group of tags. and here's the lore: after discussion, most people wanted the ability to add a new field to the end of the hundred group where it belonged. And the reason is that according to the MARC format, fields within a record are supposed to be grouped by block (hundred groups). which means fields may not necessarily be in tag order. so like, chill, it's on purpose. ๐Ÿซถ

โœจ delete_fields( $field )

Deletes a given list of MARC::Field objects from the record.

# delete all note fields
my @notes = $record->field('5..');
$record->delete_fields(@notes);

delete_fields() will return the number of fields that were deleted. byeeee ๐Ÿ‘‹

โœจ delete_field()

Same thing as delete_fields() but only expects a single MARC::Field to be passed in. Mainly here for backwards compatibility. the older sibling who still shows up. ๐Ÿฅน

โœจ as_usmarc()

This is a wrapper around MARC::File::USMARC::encode() for compatibility with older versions of MARC::Record.

โœจ as_formatted()

Returns a pretty string for printing in a MARC dump. pretty as in formatting pretty, not pretty-pretty, but honestly? both. ๐Ÿ’…

โœจ leader()

Returns the leader for the record. Sets the leader if text is defined. No error checking is done on the validity of the leader. so if you hand it nonsense, it will literally just hold the nonsense. she doesn't check IDs at the door. ๐Ÿ’€

โœจ encoding()

A method for getting/setting the encoding for a record.

The encoding for a record is determined by position 09 in the leader:

  • blank โ†’ MARC-8 encoding
  • 'a' โ†’ UCS/Unicode

encoding() will return a string, either 'MARC-8' or 'UTF-8', appropriately.

If you want to set the encoding for a MARC::Record object you can use the string values:

$record->encoding( 'UTF-8' );
NOTE: MARC::Record objects created from scratch have a default encoding of MARC-8, which has been the standard for years... but many online catlogs and record vendors are migrating to UTF-8.
WARNING: โš ๏ธ you should be sure your record really does contain valid UTF-8 data when you manually set the encoding. don't be out here lying to your own record, bestie. fr fr.

โœจ set_leader_lengths( $reclen, $baseaddr )

Internal function for updating the leader's length and base address. like, internal internal. you didn't see this. ๐Ÿ™ˆ

โœจ clone()

The clone() method makes a copy of an existing MARC record and returns the new version.

Note that you cannot just say:

my $newmarc = $oldmarc;

Because that just makes a copy of the reference, not a new object. sneaky. ๐Ÿ˜ญ You must use the clone() method like so:

my $newmarc = $oldmarc->clone;

You can also specify field specs to filter down only a certain subset of fields. For instance, if you only wanted the title and ISBN tags from a record, you could do this:

my $small_marc = $marc->clone( 245, '020' );

And the order of the fields is preserved as it was in the original record. first come, first served. โœจ

โœจ warnings()

Returns the warnings (as a list) that were created when the record was read. These are things like "Invalid indicators converted to blanks".

my @warnings = $record->warnings();

The warnings are items that you might be interested in, or might not. It depends on how stringently you're checking data. If you're doing some grunt data analysis, you probably don't care. ๐Ÿฅฑ

side effect alert: a side effect of calling warnings() is that the warning buffer will be cleared. so read 'em and they're gone. take a screenshot, bestie. ๐Ÿ“ธ

โœจ add_fields()

okay so add_fields() is now deprecated, and users are encouraged to use append_fields(), insert_fields_after(), and insert_fields_before() since they do what you want, probably. It is still here though, for backwards compatibility. she's retired but she still answers the phone. ๐Ÿซถ

add_fields() adds MARC::Field objects to the end of the list. Returns the number of fields added, or undef if there was an error.

There are three ways of calling add_fields() to add data to the record.

  1. Create a MARC::Field object and add it โ€” the DIY approach ๐Ÿ’…
my $author = MARC::Field->new(
              100, "1", " ", a => "Arnosky, Jim."
              );
$marc->add_fields( $author );
  1. Add the data fields directly, and let add_fields() take care of the objectifying โ€” the low-effort queen approach โœจ
$marc->add_fields(
      245, "1", "0",
              a => "Raccoons and ripe corn /",
              c => "Jim Arnosky.",
              );
  1. Same as #2 above, but pass multiple fields of data in anonymous lists โ€” the bulk order approach ๐Ÿ›๏ธ
$marc->add_fields(
      [ 250, " ", " ", a => "1st ed." ],
      [ 650, "1", " ", a => "Raccoons." ],
      );

๐Ÿ”ฎ DESIGN NOTES ๐Ÿ”ฎ

A brief discussion of why MARC::Record is done the way it is. grab a snack, this is the lore section. ๐Ÿ“

  • It's built for quick prototyping

One of the areas Perl excels is in allowing the programmer to create easy solutions quickly. MARC::Record is designed along those same lines. You want a program to dump all the 6XX tags in a file? MARC::Record is your friend. ๐Ÿซถ

  • It's built for extensibility

Currently, I'm using MARC::Record for analyzing bibliographic data, but who knows what might happen in the future? MARC::Record needs to be just as adept at authority data, too. ๐Ÿ‘‘

  • It's designed around accessor methods

I use method calls everywhere, and I expect calling programs to do the same, rather than accessing internal data directly. If you access an object's hash fields on your own, future releases may break your code. โš ๏ธ so like, hands off the internals, bestie.

  • It's not built for speed

One of the tradeoffs in using accessor methods is some overhead in the method calls. Is this slow? I don't know, I haven't measured. I would suggest that if you're a cycle junkie that you use Benchmark.pm to check to see where your bottlenecks are, and then decide if MARC::Record is for you. ๐Ÿƒโ™€๏ธ


MARC::Field, MARC::Batch, MARC::File::XML, MARC::Charset, MARC::Lint

the whole friend group. ๐ŸŒˆ


๐ŸŒธ SEE ALSO ๐ŸŒธ

A mailing list devoted to the use of Perl in libraries. ๐Ÿ“š

The definitive source for all things MARC. the mothership. ๐Ÿ‘‘

Online version of the free booklet. An excellent overview of the MARC format. Essential. like, required reading, no cap.

Follett Software Company's (http://www.fsc.follett.com/) monthly discussion of various MARC tags. ๐Ÿ—“๏ธ


๐Ÿ“ TODO ๐Ÿ“

  • Incorporate MARC.pm in the distribution.

Combine MARC.pm and MARC::* into one distribution. one big happy family. ๐Ÿซถ

  • Podify MARC.pm
  • Allow regexes across the entire tag

Imagine something like this:

my @sears_headings = $marc->tag_grep( qr/Sears/ );

(from Mike O'Regan)

  • Insert a field in an arbitrary place in the record
  • Modifying an existing field

bestie this is only part 1, there's more where that came from โ€” don't wander off ๐Ÿฆ‹

๐Ÿ’Œ BUGS, WISHES AND CORRESPONDENCE ๐Ÿ’Œ

okay so bestie, if something's broken or you just wanna chat, email me at mrylander@gmail.com and I'll help as best I can ๐Ÿ’– I am always here for bugs, suggestions and patches, no gatekeeping, we love feedback in this house.

But ngl, if you want info fast and want to vibe with actual humans, the perl4lib mailing list is literally the move. Head to http://perl4lib.perl.org for the deets on the list plus other genuinely helpful MARC info โœจ


Also! The MARC::Record dev team runs on the RT bug tracking system at http://rt.cpan.org. So if your email is about a bug or a suggestion, pleeease report it through RT instead โ€” it's a huge help for the team and you'll get notified as things get fixed or updated ๐Ÿซถ (main character behaviour, honestly).

And if the website is giving you the ick, no stress, just send your bug to bug-MARC-Record@rt.cpan.org ๐Ÿ’…

๐ŸŒˆ IDEAS ๐ŸŒˆ

Ideas are things that have been considered but literally nobody has actually asked for yet. (Yes this is a real section. It's giving wishlist energy ๐Ÿ™ˆ)

  • Create multiple output formats.

These could be ASCII or MarcMaker.

๐Ÿ“œ LICENSE ๐Ÿ“œ

This code may be distributed under the same terms as Perl itself. periodt.

Please note that these modules are not products of or supported by the employers of the various contributors to the code. ๐Ÿ‘‘

๐Ÿ‘‘ AUTHORS ๐Ÿ‘‘

  • Andy Lester
  • Mike O'Regan
  • Ed Summers
  • Mike Rylander
  • Galen Charlton

and that's a wrap, bestie ๐Ÿ’– this page is from perl v5.36.0, dated 2022-10-13, and yes it's MARC::Record(3pm) โ€” go forth and catalogue, you absolute icon ๐ŸŒธโœจ๐Ÿฆ‹

๐Ÿ“ฆ where this page comes from