Documentation
¶
Overview ¶
Package marc reads, writes, and modifies bibliographic records encoded in MARC21 (https://en.wikipedia.org/wiki/MARC_standards).
It is a Go port of the Python library pymarc (https://gitlab.com/pymarc/pymarc), covering the binary MARC21 transmission format, MARC-8 to Unicode conversion, MARC-in-JSON, and MARCXML.
Reading ¶
Read a batch of binary MARC21 records and print each title:
f, _ := os.Open("marc.dat")
reader := marc.NewReader(f)
for {
record, err := reader.Next()
if errors.Is(err, io.EOF) {
break
}
title, _ := record.Title()
fmt.Println(title)
}
Writing ¶
Build a record and write it out:
record, _ := marc.NewRecord()
record.AddField(marc.NewDataField("245", "0", "1",
marc.Subfield{Code: "a", Value: "The pragmatic programmer : "},
marc.Subfield{Code: "b", Value: "from journeyman to master /"},
))
out, _ := os.Create("file.dat")
writer := marc.NewWriter(out)
writer.Write(record)
JSON and XML ¶
Records can also be (de)serialized as MARC-in-JSON or MARCXML, which use UTF-8 throughout rather than MARC-8:
records, _ := marc.ParseJSON(data) records, _ := marc.ParseXML(r)
Index ¶
- Constants
- Variables
- type Field
- func (f *Field) AddSubfield(code, value string)
- func (f *Field) AddSubfieldAt(code, value string, pos int)
- func (f *Field) AsMarc(encoding string) ([]byte, error)
- func (f *Field) Contains(code string) bool
- func (f *Field) DeleteSubfield(code string) (value string, ok bool)
- func (f *Field) FormatField() string
- func (f *Field) GetSubfields(codes ...string) []string
- func (f *Field) Indicator1() string
- func (f *Field) Indicator2() string
- func (f *Field) IsControlField() bool
- func (f *Field) IsSubjectField() bool
- func (f *Field) LinkageOccurrenceNum() (string, bool)
- func (f *Field) SetIndicator1(value string)
- func (f *Field) SetIndicator2(value string)
- func (f *Field) SetSubfield(code, value string) error
- func (f *Field) String() string
- func (f *Field) Subfield(code string) (value string, ok bool)
- func (f *Field) SubfieldsByCode() map[string][]string
- func (f *Field) Value() string
- type Indicators
- type JSONWriter
- type Leader
- func (l *Leader) BaseAddress() string
- func (l *Leader) BibliographicLevel() byte
- func (l *Leader) Byte(i int) byte
- func (l *Leader) CatalogingForm() byte
- func (l *Leader) CodingScheme() byte
- func (l *Leader) EncodingLevel() byte
- func (l *Leader) ImplementationDefinedLength() byte
- func (l *Leader) IndicatorCount() byte
- func (l *Leader) LengthOfFieldLength() byte
- func (l *Leader) MultipartResource() byte
- func (l *Leader) RecordLength() string
- func (l *Leader) RecordStatus() byte
- func (l *Leader) SetBaseAddress(value string) error
- func (l *Leader) SetBibliographicLevel(value string) error
- func (l *Leader) SetCatalogingForm(value string) error
- func (l *Leader) SetCodingScheme(value string) error
- func (l *Leader) SetEncodingLevel(value string) error
- func (l *Leader) SetImplementationDefinedLength(value string) error
- func (l *Leader) SetIndicatorCount(value string) error
- func (l *Leader) SetLengthOfFieldLength(value string) error
- func (l *Leader) SetMultipartResource(value string) error
- func (l *Leader) SetRecordLength(value string) error
- func (l *Leader) SetRecordStatus(value string) error
- func (l *Leader) SetSlice(position int, value string) error
- func (l *Leader) SetStartingCharacterPositionLength(value string) error
- func (l *Leader) SetSubfieldCodeCount(value string) error
- func (l *Leader) SetTypeOfControl(value string) error
- func (l *Leader) SetTypeOfRecord(value string) error
- func (l *Leader) Slice(start, end int) string
- func (l *Leader) StartingCharacterPositionLength() byte
- func (l *Leader) String() string
- func (l *Leader) SubfieldCodeCount() byte
- func (l *Leader) TypeOfControl() byte
- func (l *Leader) TypeOfRecord() byte
- type Reader
- type ReaderOption
- type Record
- func (r *Record) AddField(fields ...*Field)
- func (r *Record) AddGroupedField(fields ...*Field)
- func (r *Record) AddOrderedField(fields ...*Field)
- func (r *Record) AddedEntries() []*Field
- func (r *Record) AsDict() map[string]any
- func (r *Record) AsJSON() (string, error)
- func (r *Record) AsMARC() ([]byte, error)
- func (r *Record) Author() (string, bool)
- func (r *Record) Contains(tag string) bool
- func (r *Record) DecodeMARC(marc []byte, opts decodeOptions) error
- func (r *Record) Get(tag string) *Field
- func (r *Record) GetFields(tags ...string) []*Field
- func (r *Record) GetLinkedFields(f *Field) ([]*Field, error)
- func (r *Record) ISBN() (string, bool)
- func (r *Record) ISSN() (string, bool)
- func (r *Record) ISSNL() (string, bool)
- func (r *Record) IssnTitle() (string, bool)
- func (r *Record) Location() []*Field
- func (r *Record) Notes() []*Field
- func (r *Record) PhysicalDescription() []*Field
- func (r *Record) PubYear() (string, bool)
- func (r *Record) Publisher() (string, bool)
- func (r *Record) RemoveField(f *Field) error
- func (r *Record) RemoveFields(tags ...string)
- func (r *Record) SUDOC() (string, bool)
- func (r *Record) Series() []*Field
- func (r *Record) String() string
- func (r *Record) Subjects() []*Field
- func (r *Record) Title() (string, bool)
- func (r *Record) UniformTitle() (string, bool)
- type RecordOption
- func WithData(data []byte) RecordOption
- func WithFields(fields ...*Field) RecordOption
- func WithFileEncoding(enc string) RecordOption
- func WithForceUTF8(b bool) RecordOption
- func WithHideUTF8Warnings(b bool) RecordOption
- func WithLeaderString(s string) RecordOption
- func WithToUnicode(b bool) RecordOption
- func WithUTF8Handling(mode string) RecordOption
- type Subfield
- type TextWriter
- type Writer
- type XMLReader
- type XMLWriter
Constants ¶
const ( LeaderLen = 24 DirectoryEntryLen = 12 SubfieldIndicator = 0x1F EndOfField = 0x1E EndOfRecord = 0x1D )
Ported from pymarc/constants.py.
Variables ¶
var ( ErrRecordLengthInvalid = errors.New("invalid record length in first 5 bytes of record") ErrTruncatedRecord = errors.New("record length in leader is greater than the length of data") ErrEndOfRecordNotFound = errors.New("unable to locate end of record marker") ErrRecordLeaderInvalid = errors.New("unable to extract record leader") ErrRecordDirectoryInvalid = errors.New("invalid directory") ErrNoFieldsFound = errors.New("unable to locate fields in record data") ErrBaseAddressInvalid = errors.New("base address exceeds size of record") ErrBaseAddressNotFound = errors.New("unable to locate base address of record") ErrWriteNeedsRecord = errors.New("write requires a *marc.Record argument") ErrNoActiveFile = errors.New("there is no active file to write to") ErrFieldNotFound = errors.New("record does not contain the specified field") ErrBadLeaderValue = errors.New("bad leader value") ErrMissingLinkedFields = errors.New("field includes a subfield 6 but no linked fields could be found") )
Sentinel errors ported from pymarc/exceptions.py. Wrap with fmt.Errorf("%w: ...", ErrX) for dynamic detail, and check with errors.Is.
Functions ¶
This section is empty.
Types ¶
type Field ¶
type Field struct {
Tag string
ControlField bool
Data string
Indicators Indicators
Subfields []Subfield
}
Field represents a single MARC field: either a control field (tag < "010", carrying raw Data) or a data field (carrying Indicators and Subfields). Ported from pymarc/field.py.
func NewControlField ¶
NewControlField builds a control field (e.g. tag "001", "008") with raw data.
func NewDataField ¶
NewDataField builds a data field with the given indicators and subfields. Pass " " for a blank indicator, matching pymarc's default (" ", " ").
func NewField ¶
func NewField(tag string, indicators Indicators, subfields []Subfield, data string) *Field
NewField builds a Field, replicating pymarc's Field.__init__ branching: tags normalized to 3-digit zero-padded form when numeric; tags below "010" become control fields carrying data (indicators/subfields are ignored for those, as in pymarc); all other tags become data fields carrying indicators/subfields.
func (*Field) AddSubfield ¶
AddSubfield appends a subfield to the end of the field. No-op on control fields.
func (*Field) AddSubfieldAt ¶
AddSubfieldAt inserts a subfield at pos, or appends if pos is out of range. No-op on control fields.
func (*Field) AsMarc ¶
AsMarc encodes the field into MARC transmission-format bytes. Only "utf-8" encoding is currently supported.
func (*Field) DeleteSubfield ¶
DeleteSubfield removes and returns the value of the first subfield with the given code. ok is false if none was found (or the field is a control field).
func (*Field) FormatField ¶
FormatField returns the field's subfields as a pretty string: subject fields join v/x/y/z subfields with " -- ", and subfield 6 is skipped.
func (*Field) GetSubfields ¶
GetSubfields returns the values of all subfields matching any of the given codes, in field order.
func (*Field) Indicator1 ¶
Indicator1 returns the first indicator, or "" for control fields.
func (*Field) Indicator2 ¶
Indicator2 returns the second indicator, or "" for control fields.
func (*Field) IsControlField ¶
IsControlField reports whether the field is a control field. Prefer the ControlField field directly; kept for parity with pymarc's is_control_field().
func (*Field) IsSubjectField ¶
IsSubjectField reports whether the field's tag starts with "6".
func (*Field) LinkageOccurrenceNum ¶
LinkageOccurrenceNum returns the occurrence number portion of subfield 6 (e.g. "01" from "880-01"), or ok=false if subfield 6 is absent.
func (*Field) SetIndicator1 ¶
SetIndicator1 sets the first indicator. No-op on control fields.
func (*Field) SetIndicator2 ¶
SetIndicator2 sets the second indicator. No-op on control fields.
func (*Field) SetSubfield ¶
SetSubfield sets the value of the single subfield with the given code. Returns an error if the field is a control field, no subfield has that code, or more than one subfield has that code.
func (*Field) Subfield ¶
Subfield returns the value of the first subfield with the given code. ok is false if the field is a control field or the code is absent.
func (*Field) SubfieldsByCode ¶
SubfieldsByCode groups subfield values by code, preserving field order within each code.
type Indicators ¶
Indicators are the two indicator characters of a non-control Field. Ported from pymarc.field.Indicators.
type JSONWriter ¶
type JSONWriter struct {
// contains filtered or unexported fields
}
JSONWriter writes records as a MARC-in-JSON array. Close must be called to emit the closing bracket. Ported from pymarc.writer.JSONWriter.
func NewJSONWriter ¶
func NewJSONWriter(w io.Writer) (*JSONWriter, error)
NewJSONWriter builds a JSONWriter, writing the opening "[".
func (*JSONWriter) Close ¶
func (jw *JSONWriter) Close() error
Close writes the closing "]". The writer must not be used afterward.
func (*JSONWriter) Write ¶
func (jw *JSONWriter) Write(r *Record) error
Write serializes and writes a single record.
type Leader ¶
type Leader struct {
// contains filtered or unexported fields
}
Leader is the mutable 24-byte MARC record leader. Ported from pymarc/leader.py.
See https://www.loc.gov/marc/bibliographic/bdleader.html for field meanings.
Values are accessed either through named accessors (RecordStatus, BibliographicLevel, ...) or through raw position access (Byte, Slice) mirroring Python's leader[5] / leader[0:4].
func (*Leader) BaseAddress ¶
BaseAddress returns the base address of data (12-16).
func (*Leader) BibliographicLevel ¶
BibliographicLevel returns the bibliographic level (07).
func (*Leader) CatalogingForm ¶
CatalogingForm returns the descriptive cataloging form (18).
func (*Leader) CodingScheme ¶
CodingScheme returns the character coding scheme (09).
func (*Leader) EncodingLevel ¶
EncodingLevel returns the encoding level (17).
func (*Leader) ImplementationDefinedLength ¶
ImplementationDefinedLength returns the length of the implementation-defined portion (22).
func (*Leader) IndicatorCount ¶
IndicatorCount returns the indicator count (10).
func (*Leader) LengthOfFieldLength ¶
LengthOfFieldLength returns the length of the length-of-field portion (20).
func (*Leader) MultipartResource ¶
MultipartResource returns the multipart resource record level (19).
func (*Leader) RecordLength ¶
RecordLength returns the record length (00-04).
func (*Leader) RecordStatus ¶
RecordStatus returns the record status (05).
func (*Leader) SetBaseAddress ¶
SetBaseAddress sets the base address of data (12-16).
func (*Leader) SetBibliographicLevel ¶
SetBibliographicLevel sets the bibliographic level (07).
func (*Leader) SetCatalogingForm ¶
SetCatalogingForm sets the descriptive cataloging form (18).
func (*Leader) SetCodingScheme ¶
SetCodingScheme sets the character coding scheme (09).
func (*Leader) SetEncodingLevel ¶
SetEncodingLevel sets the encoding level (17).
func (*Leader) SetImplementationDefinedLength ¶
SetImplementationDefinedLength sets the length of the implementation-defined portion (22).
func (*Leader) SetIndicatorCount ¶
SetIndicatorCount sets the indicator count (10).
func (*Leader) SetLengthOfFieldLength ¶
SetLengthOfFieldLength sets the length of the length-of-field portion (20).
func (*Leader) SetMultipartResource ¶
SetMultipartResource sets the multipart resource record level (19).
func (*Leader) SetRecordLength ¶
SetRecordLength sets the record length (00-04).
func (*Leader) SetRecordStatus ¶
SetRecordStatus sets the record status (05).
func (*Leader) SetSlice ¶
SetSlice sets the substring starting at position, matching Python's leader[start:] = value.
func (*Leader) SetStartingCharacterPositionLength ¶
SetStartingCharacterPositionLength sets the length of the starting-character-position portion (21).
func (*Leader) SetSubfieldCodeCount ¶
SetSubfieldCodeCount sets the subfield code count (11).
func (*Leader) SetTypeOfControl ¶
SetTypeOfControl sets the type of control (08).
func (*Leader) SetTypeOfRecord ¶
SetTypeOfRecord sets the type of record (06).
func (*Leader) Slice ¶
Slice returns the substring [start:end) (equivalent to Python's leader[start:end]).
func (*Leader) StartingCharacterPositionLength ¶
StartingCharacterPositionLength returns the length of the starting-character-position portion (21).
func (*Leader) SubfieldCodeCount ¶
SubfieldCodeCount returns the subfield code count (11).
func (*Leader) TypeOfControl ¶
TypeOfControl returns the type of control (08).
func (*Leader) TypeOfRecord ¶
TypeOfRecord returns the type of record (06).
type Reader ¶
type Reader struct {
// contains filtered or unexported fields
}
Reader iterates over MARC21 records in transmission format read from an io.Reader. Ported from pymarc.reader.MARCReader.
It is permissive: a bad record yields (nil, err) from Next but does not stop iteration, unless the error is fatal (the record's length/boundary could not be determined), in which case every subsequent Next call returns io.EOF.
func NewReader ¶
func NewReader(r io.Reader, opts ...ReaderOption) *Reader
NewReader builds a Reader over r (or over raw bytes via NewReaderFromBytes).
func NewReaderFromBytes ¶
func NewReaderFromBytes(data []byte, opts ...ReaderOption) *Reader
NewReaderFromBytes builds a Reader over an in-memory MARC blob.
func (*Reader) CurrentChunk ¶
CurrentChunk returns the raw bytes of the most recently attempted record.
type ReaderOption ¶
type ReaderOption = RecordOption
ReaderOption configures a Reader; shares option constructors with NewRecord (leader/fields/data options are ignored by the reader).
type Record ¶
Record represents a MARC record: a Leader plus an ordered list of Fields. Ported from pymarc/record.py.
func NewRecord ¶
func NewRecord(opts ...RecordOption) (*Record, error)
NewRecord builds a Record from options, mirroring pymarc's Record.__init__. If WithData is given (and WithFields is not), the data is decoded via DecodeMARC.
func ParseJSON ¶
ParseJSON parses MARC-in-JSON data, which may be a single record object or an array of record objects, into Records. Matches pymarc's parse_json_to_array.
func (*Record) AddGroupedField ¶
AddGroupedField adds fields, keeping a loose numeric order per the MARC "organization of the record" convention (grouped by first tag digit).
func (*Record) AddOrderedField ¶
AddOrderedField adds fields, keeping a strict numeric tag order.
func (*Record) AddedEntries ¶
AddedEntries returns added-entry fields (7XX).
func (*Record) AsDict ¶
AsDict turns the record into a plain map, matching pymarc's as_dict()/MARC-in-JSON shape.
func (*Record) AsMARC ¶
AsMARC serializes the record into MARC transmission-format bytes, matching pymarc's Record.as_marc().
func (*Record) Author ¶
Author returns the author from field 100, 110, or 111, or ok=false if none present.
func (*Record) DecodeMARC ¶
DecodeMARC populates the record from data in MARC transmission format, matching pymarc's Record.decode_marc. Only to_unicode=true is currently supported; RawField / to_unicode=false is not yet ported.
func (*Record) GetFields ¶
GetFields returns all fields matching any of the given tags, in record order. With no tags, returns all fields.
func (*Record) GetLinkedFields ¶
GetLinkedFields returns the 880 fields linked to f via subfield 6's occurrence number. Returns ErrMissingLinkedFields if f has a subfield 6 but no 880 matches it.
func (*Record) ISBN ¶
ISBN returns the first ISBN in the record (from 020 $a), with dashes and extraneous text stripped, or ok=false if absent/unparseable.
func (*Record) PhysicalDescription ¶
PhysicalDescription returns physical-description fields (300).
func (*Record) PubYear ¶
PubYear returns the publication year from 260 $c, or from 264 $c when the 264's second indicator is "1", or ok=false if neither is present.
func (*Record) Publisher ¶
Publisher returns the publisher from 260 $b, or from 264 $b when the 264's second indicator is "1", or ok=false if neither is present.
func (*Record) RemoveField ¶
RemoveField removes a field by identity (pointer equality). Returns ErrFieldNotFound if the field isn't present.
func (*Record) RemoveFields ¶
RemoveFields removes all fields whose tag matches any of the given tags.
func (*Record) SUDOC ¶
SUDOC returns the Superintendent of Documents classification number (086), or ok=false if absent.
func (*Record) String ¶
String returns the record in MARCMaker format (leader line + one line per field).
func (*Record) UniformTitle ¶
UniformTitle returns the uniform title from field 130 or 240, or ok=false if none present.
type RecordOption ¶
type RecordOption func(*recordConfig)
RecordOption configures NewRecord, mirroring pymarc's Record.__init__ keyword args.
func WithData ¶
func WithData(data []byte) RecordOption
WithData supplies raw MARC transmission-format bytes to decode.
func WithFields ¶
func WithFields(fields ...*Field) RecordOption
WithFields sets the record's fields directly, skipping MARC decoding.
func WithFileEncoding ¶
func WithFileEncoding(enc string) RecordOption
WithFileEncoding sets the non-UTF-8, non-MARC8 charset to assume (default "iso8859-1").
func WithForceUTF8 ¶
func WithForceUTF8(b bool) RecordOption
WithForceUTF8 forces UTF-8 decoding/encoding regardless of the leader's coding scheme.
func WithHideUTF8Warnings ¶
func WithHideUTF8Warnings(b bool) RecordOption
WithHideUTF8Warnings suppresses MARC8 conversion warnings.
func WithLeaderString ¶
func WithLeaderString(s string) RecordOption
WithLeaderString sets the initial 24-byte leader input (default: 24 spaces).
func WithToUnicode ¶
func WithToUnicode(b bool) RecordOption
WithToUnicode controls whether subfield/control-field data is decoded to Go strings (true, default) — to_unicode=false (raw byte passthrough) is not yet implemented.
func WithUTF8Handling ¶
func WithUTF8Handling(mode string) RecordOption
WithUTF8Handling sets the UTF-8 decode error mode: "strict" (default), "replace", or "ignore".
type Subfield ¶
Subfield is a code/value pair within a data Field. Ported from pymarc.field.Subfield.
type TextWriter ¶
type TextWriter struct {
// contains filtered or unexported fields
}
TextWriter writes records in prettified MARCMaker text format, separated by a blank line. Ported from pymarc.writer.TextWriter.
func NewTextWriter ¶
func NewTextWriter(w io.Writer) *TextWriter
NewTextWriter builds a MARCMaker-format TextWriter.
func (*TextWriter) Write ¶
func (w *TextWriter) Write(r *Record) error
Write writes a single record, preceded by a blank line if this isn't the first.
type Writer ¶
type Writer struct {
// contains filtered or unexported fields
}
Writer writes MARC21 records in transmission format to an io.Writer. Ported from pymarc.writer.MARCWriter.
type XMLReader ¶
type XMLReader struct {
// contains filtered or unexported fields
}
XMLReader iterates over <record> elements in a MARCXML collection (or a single bare <record>), decoding one record at a time rather than loading the whole document. Ported from pymarc.marcxml.XmlHandler/parse_xml.
func NewXMLReader ¶
NewXMLReader builds an XMLReader over r.
type XMLWriter ¶
type XMLWriter struct {
// contains filtered or unexported fields
}
XMLWriter writes records as a MARCXML <collection>. Close must be called to emit the closing tag. Ported from pymarc.writer.XMLWriter.
func NewXMLWriter ¶
NewXMLWriter builds an XMLWriter, writing the XML declaration and opening <collection> tag.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
marcdump
command
Command marcdump reads a binary MARC21 file and prints each record, either as MARCMaker-style text (default) or MARC-in-JSON (-json).
|
Command marcdump reads a binary MARC21 file and prints each record, either as MARCMaker-style text (default) or MARC-in-JSON (-json). |
|
Package schema provides machine-readable semantic descriptions of MARC21 record structures for use with LLMs and other schema-aware tooling.
|
Package schema provides machine-readable semantic descriptions of MARC21 record structures for use with LLMs and other schema-aware tooling. |