marc

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 16, 2026 License: BSD-2-Clause Imports: 14 Imported by: 0

README

gomarc

gomarc reads, writes, and modifies bibliographic records encoded in MARC21. It's a Go port of the Python library pymarc, covering the binary MARC21 transmission format, MARC-8 to Unicode conversion, MARC-in-JSON, and MARCXML.

Installation

go get github.com/beyto1974/gomarc@v1.0.0
import marc "github.com/beyto1974/gomarc"

Public repo, so the normal module proxy (proxy.golang.org) and checksum database (sum.golang.org) resolve it with no extra setup.

The v1 API is stable: within v1.x the exported surface of marc and marc/schema only grows, it doesn't change shape.

Reading

f, err := os.Open("marc.dat")
if err != nil {
	log.Fatal(err)
}
defer f.Close()

reader := marc.NewReader(f)
for {
	record, err := reader.Next()
	if errors.Is(err, io.EOF) {
		break
	}
	if err != nil {
		log.Println(err) // Reader is permissive: bad records are skipped, not fatal
		continue
	}
	title, _ := record.Title()
	fmt.Println(title)
}

A *marc.Record has convenience methods for common fields: Title, Author, ISBN, ISSN, Subjects, Location, Notes, PhysicalDescription, Publisher, PubYear. For anything else you need the numeric field tag and subfield code directly:

value, ok := record.Get("245").Subfield("a")

Repeating fields (e.g. subjects) come back as a slice via GetFields:

for _, f := range record.GetFields("650") {
	fmt.Println(f)
}

Writing

record, err := marc.NewRecord()
if err != nil {
	log.Fatal(err)
}
record.AddField(marc.NewDataField("245", "0", "1",
	marc.Subfield{Code: "a", Value: "The pragmatic programmer : "},
	marc.Subfield{Code: "b", Value: "from journeyman to master /"},
	marc.Subfield{Code: "c", Value: "Andrew Hunt, David Thomas."},
))

out, err := os.Create("file.dat")
if err != nil {
	log.Fatal(err)
}
defer out.Close()

writer := marc.NewWriter(out)
if err := writer.Write(record); err != nil {
	log.Fatal(err)
}

Updating

Read a record in, modify it, write it back out:

record, err := reader.Next()
if err != nil {
	log.Fatal(err)
}
if err := record.Get("245").SetSubfield("a", "The Zombie Programmer : "); err != nil {
	log.Fatal(err)
}

data, err := record.AsMARC()
if err != nil {
	log.Fatal(err)
}
os.WriteFile("file.dat", data, 0o644)

JSON and XML

The main benefit of JSON or XML over binary MARC21 is that they use UTF-8 throughout, rather than the archaic MARC-8 encoding, and can be read with standard tooling instead of a MARC-specific library.

JSON

s, err := record.AsJSON()
records, err := marc.ParseJSON(data)

XML

records, err := marc.ParseXML(r) // r is an io.Reader

To stream a large MARCXML file one record at a time instead of loading it all into memory:

xr := marc.NewXMLReader(r)
for {
	record, err := xr.Next()
	if errors.Is(err, io.EOF) {
		break
	}
	title, _ := record.Title()
	fmt.Println(title)
}

Example CLI

cmd/marcdump is a small example program that dumps a binary MARC21 file as MARCMaker-style text (default) or MARC-in-JSON (-json):

go run ./cmd/marcdump testdata/marc.dat
go run ./cmd/marcdump -json testdata/marc.dat

Performance & Comparison with pymarc

gomarc features a high-performance, streaming parser architecture designed for high-throughput processing, featuring zero-allocation field tag normalization, direct byte-slice integer parsing, and reflection-free MARCXML decoding.

Benchmarks (gomarc vs. pymarc)
Task / File Format pymarc Execution Time gomarc Execution Time pymarc Memory Footprint gomarc Memory Footprint Speedup
NLM MARCXML Dataset (catplus.marcxml.xml, 2,663 recs, 15.2 MB) 858.86 ms 367.78 ms (138 µs/rec) ~140 MB ~25 MB ~2.3x faster
MARCXML Parsing (batch.xml, 2 recs) 493.92 µs 155.41 µs 3.43 MB 61.2 KB (1,559 allocs) ~3.2x faster (~56x less memory)
ISO 2709 MARC (test.dat, 10 recs) 1,922.14 µs 123.46 µs 83.9 KB 78.6 KB (2,155 allocs) ~15.5x faster

To run the built-in benchmarks with memory profiling:

go test -bench=Benchmark -benchmem ./...

Testing

go test ./...

Test fixtures under testdata/ are copied verbatim from pymarc's own test suite, so behavior can be cross-checked against the original Python implementation.

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

View Source
const (
	LeaderLen         = 24
	DirectoryEntryLen = 12
	SubfieldIndicator = 0x1F
	EndOfField        = 0x1E
	EndOfRecord       = 0x1D
)

Ported from pymarc/constants.py.

Variables

View Source
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

func NewControlField(tag, data string) *Field

NewControlField builds a control field (e.g. tag "001", "008") with raw data.

func NewDataField

func NewDataField(tag, ind1, ind2 string, subfields ...Subfield) *Field

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

func (f *Field) AddSubfield(code, value string)

AddSubfield appends a subfield to the end of the field. No-op on control fields.

func (*Field) AddSubfieldAt

func (f *Field) AddSubfieldAt(code, value string, pos int)

AddSubfieldAt inserts a subfield at pos, or appends if pos is out of range. No-op on control fields.

func (*Field) AsMarc

func (f *Field) AsMarc(encoding string) ([]byte, error)

AsMarc encodes the field into MARC transmission-format bytes. Only "utf-8" encoding is currently supported.

func (*Field) Contains

func (f *Field) Contains(code string) bool

Contains reports whether the field has a subfield with the given code.

func (*Field) DeleteSubfield

func (f *Field) DeleteSubfield(code string) (value string, ok bool)

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

func (f *Field) FormatField() string

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

func (f *Field) GetSubfields(codes ...string) []string

GetSubfields returns the values of all subfields matching any of the given codes, in field order.

func (*Field) Indicator1

func (f *Field) Indicator1() string

Indicator1 returns the first indicator, or "" for control fields.

func (*Field) Indicator2

func (f *Field) Indicator2() string

Indicator2 returns the second indicator, or "" for control fields.

func (*Field) IsControlField

func (f *Field) IsControlField() bool

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

func (f *Field) IsSubjectField() bool

IsSubjectField reports whether the field's tag starts with "6".

func (*Field) LinkageOccurrenceNum

func (f *Field) LinkageOccurrenceNum() (string, bool)

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

func (f *Field) SetIndicator1(value string)

SetIndicator1 sets the first indicator. No-op on control fields.

func (*Field) SetIndicator2

func (f *Field) SetIndicator2(value string)

SetIndicator2 sets the second indicator. No-op on control fields.

func (*Field) SetSubfield

func (f *Field) SetSubfield(code, value string) error

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) String

func (f *Field) String() string

String returns the MARCMaker-style representation of the field.

func (*Field) Subfield

func (f *Field) Subfield(code string) (value string, ok bool)

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

func (f *Field) SubfieldsByCode() map[string][]string

SubfieldsByCode groups subfield values by code, preserving field order within each code.

func (*Field) Value

func (f *Field) Value() string

Value returns the field's subfields (or Data for control fields) joined as a string.

type Indicators

type Indicators struct {
	First  string
	Second string
}

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 NewLeader

func NewLeader(s string) (*Leader, error)

NewLeader builds a Leader from a 24-byte string.

func (*Leader) BaseAddress

func (l *Leader) BaseAddress() string

BaseAddress returns the base address of data (12-16).

func (*Leader) BibliographicLevel

func (l *Leader) BibliographicLevel() byte

BibliographicLevel returns the bibliographic level (07).

func (*Leader) Byte

func (l *Leader) Byte(i int) byte

Byte returns the byte at position i (equivalent to Python's leader[i]).

func (*Leader) CatalogingForm

func (l *Leader) CatalogingForm() byte

CatalogingForm returns the descriptive cataloging form (18).

func (*Leader) CodingScheme

func (l *Leader) CodingScheme() byte

CodingScheme returns the character coding scheme (09).

func (*Leader) EncodingLevel

func (l *Leader) EncodingLevel() byte

EncodingLevel returns the encoding level (17).

func (*Leader) ImplementationDefinedLength

func (l *Leader) ImplementationDefinedLength() byte

ImplementationDefinedLength returns the length of the implementation-defined portion (22).

func (*Leader) IndicatorCount

func (l *Leader) IndicatorCount() byte

IndicatorCount returns the indicator count (10).

func (*Leader) LengthOfFieldLength

func (l *Leader) LengthOfFieldLength() byte

LengthOfFieldLength returns the length of the length-of-field portion (20).

func (*Leader) MultipartResource

func (l *Leader) MultipartResource() byte

MultipartResource returns the multipart resource record level (19).

func (*Leader) RecordLength

func (l *Leader) RecordLength() string

RecordLength returns the record length (00-04).

func (*Leader) RecordStatus

func (l *Leader) RecordStatus() byte

RecordStatus returns the record status (05).

func (*Leader) SetBaseAddress

func (l *Leader) SetBaseAddress(value string) error

SetBaseAddress sets the base address of data (12-16).

func (*Leader) SetBibliographicLevel

func (l *Leader) SetBibliographicLevel(value string) error

SetBibliographicLevel sets the bibliographic level (07).

func (*Leader) SetCatalogingForm

func (l *Leader) SetCatalogingForm(value string) error

SetCatalogingForm sets the descriptive cataloging form (18).

func (*Leader) SetCodingScheme

func (l *Leader) SetCodingScheme(value string) error

SetCodingScheme sets the character coding scheme (09).

func (*Leader) SetEncodingLevel

func (l *Leader) SetEncodingLevel(value string) error

SetEncodingLevel sets the encoding level (17).

func (*Leader) SetImplementationDefinedLength

func (l *Leader) SetImplementationDefinedLength(value string) error

SetImplementationDefinedLength sets the length of the implementation-defined portion (22).

func (*Leader) SetIndicatorCount

func (l *Leader) SetIndicatorCount(value string) error

SetIndicatorCount sets the indicator count (10).

func (*Leader) SetLengthOfFieldLength

func (l *Leader) SetLengthOfFieldLength(value string) error

SetLengthOfFieldLength sets the length of the length-of-field portion (20).

func (*Leader) SetMultipartResource

func (l *Leader) SetMultipartResource(value string) error

SetMultipartResource sets the multipart resource record level (19).

func (*Leader) SetRecordLength

func (l *Leader) SetRecordLength(value string) error

SetRecordLength sets the record length (00-04).

func (*Leader) SetRecordStatus

func (l *Leader) SetRecordStatus(value string) error

SetRecordStatus sets the record status (05).

func (*Leader) SetSlice

func (l *Leader) SetSlice(position int, value string) error

SetSlice sets the substring starting at position, matching Python's leader[start:] = value.

func (*Leader) SetStartingCharacterPositionLength

func (l *Leader) SetStartingCharacterPositionLength(value string) error

SetStartingCharacterPositionLength sets the length of the starting-character-position portion (21).

func (*Leader) SetSubfieldCodeCount

func (l *Leader) SetSubfieldCodeCount(value string) error

SetSubfieldCodeCount sets the subfield code count (11).

func (*Leader) SetTypeOfControl

func (l *Leader) SetTypeOfControl(value string) error

SetTypeOfControl sets the type of control (08).

func (*Leader) SetTypeOfRecord

func (l *Leader) SetTypeOfRecord(value string) error

SetTypeOfRecord sets the type of record (06).

func (*Leader) Slice

func (l *Leader) Slice(start, end int) string

Slice returns the substring [start:end) (equivalent to Python's leader[start:end]).

func (*Leader) StartingCharacterPositionLength

func (l *Leader) StartingCharacterPositionLength() byte

StartingCharacterPositionLength returns the length of the starting-character-position portion (21).

func (*Leader) String

func (l *Leader) String() string

String returns the raw 24-byte leader.

func (*Leader) SubfieldCodeCount

func (l *Leader) SubfieldCodeCount() byte

SubfieldCodeCount returns the subfield code count (11).

func (*Leader) TypeOfControl

func (l *Leader) TypeOfControl() byte

TypeOfControl returns the type of control (08).

func (*Leader) TypeOfRecord

func (l *Leader) TypeOfRecord() byte

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

func (rd *Reader) CurrentChunk() []byte

CurrentChunk returns the raw bytes of the most recently attempted record.

func (*Reader) Next

func (rd *Reader) Next() (*Record, error)

Next reads and decodes the next record. It returns (nil, io.EOF) once the underlying reader is exhausted, or once a fatal boundary error has occurred. A non-fatal decode error is returned as (nil, err); the reader remains usable for subsequent Next calls.

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

type Record struct {
	Leader    *Leader
	Fields    []*Field
	ToUnicode bool
	ForceUTF8 bool
}

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

func ParseJSON(data []byte) ([]*Record, error)

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 ParseXML

func ParseXML(r io.Reader) ([]*Record, error)

ParseXML parses every <record> in r into Records.

func (*Record) AddField

func (r *Record) AddField(fields ...*Field)

AddField appends one or more fields to the record.

func (*Record) AddGroupedField

func (r *Record) AddGroupedField(fields ...*Field)

AddGroupedField adds fields, keeping a loose numeric order per the MARC "organization of the record" convention (grouped by first tag digit).

func (*Record) AddOrderedField

func (r *Record) AddOrderedField(fields ...*Field)

AddOrderedField adds fields, keeping a strict numeric tag order.

func (*Record) AddedEntries

func (r *Record) AddedEntries() []*Field

AddedEntries returns added-entry fields (7XX).

func (*Record) AsDict

func (r *Record) AsDict() map[string]any

AsDict turns the record into a plain map, matching pymarc's as_dict()/MARC-in-JSON shape.

func (*Record) AsJSON

func (r *Record) AsJSON() (string, error)

AsJSON serializes the record as MARC-in-JSON.

func (*Record) AsMARC

func (r *Record) AsMARC() ([]byte, error)

AsMARC serializes the record into MARC transmission-format bytes, matching pymarc's Record.as_marc().

func (*Record) Author

func (r *Record) Author() (string, bool)

Author returns the author from field 100, 110, or 111, or ok=false if none present.

func (*Record) Contains

func (r *Record) Contains(tag string) bool

Contains reports whether the record has a field with the given tag.

func (*Record) DecodeMARC

func (r *Record) DecodeMARC(marc []byte, opts decodeOptions) error

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) Get

func (r *Record) Get(tag string) *Field

Get returns the first field with the given tag, or nil if absent.

func (*Record) GetFields

func (r *Record) GetFields(tags ...string) []*Field

GetFields returns all fields matching any of the given tags, in record order. With no tags, returns all fields.

func (*Record) GetLinkedFields

func (r *Record) GetLinkedFields(f *Field) ([]*Field, error)

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

func (r *Record) ISBN() (string, bool)

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) ISSN

func (r *Record) ISSN() (string, bool)

ISSN returns the ISSN number (022 $a), or ok=false if absent.

func (*Record) ISSNL

func (r *Record) ISSNL() (string, bool)

ISSNL returns the ISSN-L number (022 $l), or ok=false if absent.

func (*Record) IssnTitle

func (r *Record) IssnTitle() (string, bool)

IssnTitle returns the key title of the record (222 $a and $b).

func (*Record) Location

func (r *Record) Location() []*Field

Location returns location fields (852).

func (*Record) Notes

func (r *Record) Notes() []*Field

Notes returns note fields (5XX).

func (*Record) PhysicalDescription

func (r *Record) PhysicalDescription() []*Field

PhysicalDescription returns physical-description fields (300).

func (*Record) PubYear

func (r *Record) PubYear() (string, bool)

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

func (r *Record) Publisher() (string, bool)

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

func (r *Record) RemoveField(f *Field) error

RemoveField removes a field by identity (pointer equality). Returns ErrFieldNotFound if the field isn't present.

func (*Record) RemoveFields

func (r *Record) RemoveFields(tags ...string)

RemoveFields removes all fields whose tag matches any of the given tags.

func (*Record) SUDOC

func (r *Record) SUDOC() (string, bool)

SUDOC returns the Superintendent of Documents classification number (086), or ok=false if absent.

func (*Record) Series

func (r *Record) Series() []*Field

Series returns series fields (440, 490, 800, 810, 811, 830).

func (*Record) String

func (r *Record) String() string

String returns the record in MARCMaker format (leader line + one line per field).

func (*Record) Subjects

func (r *Record) Subjects() []*Field

Subjects returns subject fields (6XX).

func (*Record) Title

func (r *Record) Title() (string, bool)

Title returns the title of the record (245 $a and $b).

func (*Record) UniformTitle

func (r *Record) UniformTitle() (string, bool)

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

type Subfield struct {
	Code  string
	Value string
}

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.

func NewWriter

func NewWriter(w io.Writer) *Writer

NewWriter builds a binary MARC21 Writer.

func (*Writer) Write

func (w *Writer) Write(r *Record) error

Write serializes and writes a single record.

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

func NewXMLReader(r io.Reader) *XMLReader

NewXMLReader builds an XMLReader over r.

func (*XMLReader) Next

func (xr *XMLReader) Next() (*Record, error)

Next decodes and returns the next <record>, or (nil, io.EOF) at end of document.

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

func NewXMLWriter(w io.Writer) (*XMLWriter, error)

NewXMLWriter builds an XMLWriter, writing the XML declaration and opening <collection> tag.

func (*XMLWriter) Close

func (xw *XMLWriter) Close() error

Close writes the closing </collection> tag. The writer must not be used afterward.

func (*XMLWriter) Write

func (xw *XMLWriter) Write(r *Record) error

Write serializes and writes a single record as a <record> element.

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL