Documentation
¶
Overview ¶
Package codex is a format-agnostic in-memory model for MARC 21 bibliographic records, shared by the serialization subpackages.
A Record is a 24-byte Leader plus an ordered list of Fields. A control field (tag below "010") holds raw data; a data field carries two indicators and zero or more Subfields. Every MARC serialization maps onto this one model, so the same record round-trips through any format.
The model is domain-agnostic: it exposes leaders, fields, subfields and indicators, and leaves interpretation of specific tags to the caller.
Serialization lives in subpackages, each implementing RecordReader and RecordWriter:
- iso2709 — the binary ISO 2709 interchange format (.mrc)
- marcxml — the Library of Congress MARCXML slim schema (planned)
- marcjson — the MARC-in-JSON structure (planned)
- mrk — the MARCMaker mnemonic text format (planned)
All values exposed by this package are UTF-8 Go strings; each codec is responsible for transcoding its wire encoding to and from UTF-8.
Index ¶
- func All(r RecordReader) iter.Seq2[*Record, error]
- func Close(w RecordWriter) error
- func Convert(r RecordReader, w RecordWriter) error
- func WriteAll(w RecordWriter, records []*Record) error
- type Accessibility
- type Control008
- func (c Control008) CatalogingSource() byte
- func (c Control008) Date1() string
- func (c Control008) Date2() string
- func (c Control008) DateEntered() string
- func (c Control008) DateType() byte
- func (c Control008) FormOfItem() byte
- func (c Control008) IsBraille() bool
- func (c Control008) IsLargePrint() bool
- func (c Control008) Language() string
- func (c Control008) Place() string
- func (c Control008) String() string
- type Field
- type Leader
- type Linkage
- type Record
- func (r *Record) Accessibility() Accessibility
- func (r *Record) AddField(f Field) *Record
- func (r *Record) AlternateGraphic(f Field) (Field, bool)
- func (r *Record) Control008() (Control008, bool)
- func (r *Record) ControlField(tag string) string
- func (r *Record) DataField(tag string) (Field, bool)
- func (r *Record) DataFields(tag string) []Field
- func (r *Record) Encoding() byte
- func (r *Record) Fields() []Field
- func (r *Record) InsertField(f Field) *Record
- func (r *Record) Leader() Leader
- func (r *Record) RemoveFields(tag string) *Record
- func (r *Record) ReplaceField(f Field) *Record
- func (r *Record) SetLeader(l Leader) *Record
- func (r *Record) SubfieldValue(tag string, code byte) string
- func (r *Record) SubfieldValues(tag string, code byte) []string
- func (r *Record) Validate() error
- func (r *Record) Vernacular(tag string, code byte) string
- type RecordCounter
- type RecordReader
- type RecordWriter
- type Subfield
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func All ¶
func All(r RecordReader) iter.Seq2[*Record, error]
All returns an iterator over the records produced by r, for use as
for rec, err := range codex.All(reader) { ... }
It stops at the first error, yielding (nil, err) once; io.EOF ends iteration cleanly without yielding. It works with any RecordReader, so every format shares one iterator.
func Close ¶ added in v0.6.0
func Close(w RecordWriter) error
Close finalizes w when it needs it: if w has a Close method (a writer that buffers a wrapper, such as a marcxml <collection> or a JSON array), Close calls it and returns its error; otherwise Close is a no-op returning nil. Use it after Convert so a wrapper-buffering target completes its output.
func Convert ¶
func Convert(r RecordReader, w RecordWriter) error
Convert reads every record from r and writes it to w, returning the first error encountered (io.EOF is the normal end and is not returned). Because it is written against the interfaces, it converts between any two formats. A writer that buffers a wrapper (e.g. a marcxml <collection> or a marcjson array) still needs finalizing afterward with Close to complete the output.
Example ¶
ExampleConvert converts a binary ISO 2709 record to MARCMaker text using only the format-agnostic RecordReader and RecordWriter interfaces.
rec := codex.NewRecord().
AddField(codex.NewControlField("001", "ex-1")).
AddField(codex.NewDataField("245", '0', '0', codex.NewSubfield('a', "Example record")))
var binary bytes.Buffer
if err := iso2709.NewWriter(&binary).Write(rec); err != nil {
log.Fatal(err)
}
if err := codex.Convert(iso2709.NewReader(&binary), mrk.NewWriter(os.Stdout)); err != nil {
log.Fatal(err)
}
Output: =LDR 00074nam a2200049 4500 =001 ex-1 =245 00$aExample record
Types ¶
type Accessibility ¶ added in v0.2.0
type Accessibility struct {
LargePrint bool // 008 form of item 'd'
Braille bool // 008 form of item 'f'
Tactile bool // 007 category of material 'f' (tactile material)
AccessModes []string // 341 $a content access modes (textual, visual, auditory, tactile)
Features []string // 341 $b-$e assistive features (textual, visual, auditory, tactile)
Notes []string // 532 $a accessibility notes
}
Accessibility summarizes the accessibility metadata a record carries: the 008 form of item, the 007 physical-description category, the 341 Accessibility Content field and the 532 Accessibility Note field. It is the MARC-side view a crosswalk (e.g. to schema.org accessibility properties) can map from.
func (Accessibility) Empty ¶ added in v0.2.0
func (a Accessibility) Empty() bool
Empty reports whether the record carried no accessibility metadata at all.
type Control008 ¶ added in v0.2.0
type Control008 struct {
// contains filtered or unexported fields
}
Control008 provides typed access to the 008 fixed-length data elements. The header positions (00-17) and the trailing positions (35-39) are common to every material type; the material-specific block (18-34) is interpreted using the record's leader, which is why FormOfItem needs it.
MARC 21 fixed fields are positional, so an accessor returns the empty string or a zero byte when the underlying 008 is too short to contain the position, rather than panicking.
func (Control008) CatalogingSource ¶ added in v0.2.0
func (c Control008) CatalogingSource() byte
CatalogingSource returns position 39, the cataloging source code.
func (Control008) Date1 ¶ added in v0.2.0
func (c Control008) Date1() string
Date1 returns positions 07-10, the first date (often the publication year).
func (Control008) Date2 ¶ added in v0.2.0
func (c Control008) Date2() string
Date2 returns positions 11-14, the second date.
func (Control008) DateEntered ¶ added in v0.2.0
func (c Control008) DateEntered() string
DateEntered returns positions 00-05, the date the record was created (yymmdd).
func (Control008) DateType ¶ added in v0.2.0
func (c Control008) DateType() byte
DateType returns position 06, the type of date / publication status code.
func (Control008) FormOfItem ¶ added in v0.2.0
func (c Control008) FormOfItem() byte
FormOfItem returns the form-of-item code from the material-specific block: the byte at position 23 for most materials, or 29 for cartographic and visual materials. Codes include 'd' (large print), 'f' (braille), 'o' (online), 'q' (direct electronic) and 's' (electronic); see Control008.IsLargePrint and Control008.IsBraille for the accessibility-relevant ones.
func (Control008) IsBraille ¶ added in v0.2.0
func (c Control008) IsBraille() bool
IsBraille reports whether the form of item is braille (code 'f').
func (Control008) IsLargePrint ¶ added in v0.2.0
func (c Control008) IsLargePrint() bool
IsLargePrint reports whether the form of item is large print (code 'd').
func (Control008) Language ¶ added in v0.2.0
func (c Control008) Language() string
Language returns positions 35-37, the language code (MARC Code List for Languages / ISO 639-2/B), or "" if absent.
func (Control008) Place ¶ added in v0.2.0
func (c Control008) Place() string
Place returns positions 15-17, the place of publication, production or execution code.
func (Control008) String ¶ added in v0.2.0
func (c Control008) String() string
String returns the raw 008 value.
type Field ¶
Field is a single MARC field. A control field (Tag < "010") carries raw data in Value and has no indicators or subfields. A data field (Tag >= "010") carries two indicators and zero or more subfields. The conventional blank indicator is the ASCII space (' '); an unset (zero) data-field indicator is treated as a blank space when the field is serialized.
func NewControlField ¶
NewControlField constructs a control field (e.g. 001, 003, 008) holding raw data. The tag is not validated here; values below "010" are treated as control fields by the reader and writer.
func NewDataField ¶
NewDataField constructs a data field with the given tag, two indicators and subfields. A blank indicator is conventionally the ASCII space (' ').
func (Field) Indicators ¶
Indicators returns the field's two indicator bytes. For control fields both are zero.
func (Field) Link ¶ added in v0.2.0
Link parses the field's subfield $6 linkage, returning false if it has none or the linkage is malformed. The reference must be exactly "TAG-OO": a 3-character tag, a hyphen, and two occurrence digits, optionally followed by "/" segments carrying a script code and orientation.
func (Field) Subfield ¶
Subfield returns the value of the first subfield with the given code and reports whether one was found.
func (Field) SubfieldValue ¶
SubfieldValue returns the value of the first subfield with the given code, or the empty string if none is present.
func (Field) SubfieldValues ¶
SubfieldValues returns the values of every subfield with the given code, in order, or nil when none match. It sizes the result to the match count so a field with several matching subfields allocates once with no regrowth.
type Leader ¶
type Leader string
Leader is the 24-byte MARC record leader. Helper methods decode the fields this package needs; the raw bytes are available via String.
func (Leader) BaseAddress ¶
BaseAddress returns the base address of data declared in leader bytes [12:17]. It returns 0 if those bytes are not a valid number.
func (Leader) BibLevel ¶
BibLevel returns leader byte 7 (the bibliographic level: 'm' monograph, 's' serial, 'a' monographic component part, etc.), or 0 if the leader is malformed.
func (Leader) Encoding ¶
Encoding returns leader byte 9, the character coding scheme: 'a' for UTF-8 (Unicode) or blank for MARC-8.
func (Leader) RecordLength ¶
RecordLength returns the total record length declared in leader bytes [0:5]. It returns 0 if those bytes are not a valid number.
func (Leader) RecordStatus ¶
RecordStatus returns leader byte 5 (the record status), or 0 if the leader is malformed.
func (Leader) RecordType ¶
RecordType returns leader byte 6 (the type of record), or 0 if the leader is malformed.
type Linkage ¶ added in v0.2.0
type Linkage struct {
Tag string // the linked field's tag (e.g. "880" in a regular field)
Occurrence string // two-digit occurrence number; "00" means no linked field
Script string // script identification code (e.g. "(N" Cyrillic, "$1" CJK), or ""
RightToLeft bool // field orientation code 'r'
}
Linkage is the parsed content of a subfield $6, which ties a field to its alternate-script equivalent in field 880. In a regular field $6 points at the 880 occurrence ("880-01"); in the 880 field it points back at the regular tag ("245-01/(N/r"), optionally carrying a script identification code and a right-to-left field orientation.
func (Linkage) Linked ¶ added in v0.2.0
Linked reports whether the linkage refers to an actual partner field (a nonzero occurrence number).
func (Linkage) ScriptName ¶ added in v0.2.0
ScriptName returns a human-readable name for the $6 script identification code, or "" if absent or unrecognized. The codes are the MARC-8 set designations.
type Record ¶
type Record struct {
// contains filtered or unexported fields
}
Record is a parsed MARC record: its leader and ordered fields.
func NewRecord ¶
func NewRecord() *Record
NewRecord creates an empty record with a syntactically valid default leader (UTF-8 encoding). Fields are added with AddField.
func NewRecordCap ¶
NewRecordCap creates an empty record like NewRecord but with space preallocated for n fields. Codecs that know the field count up front use it to avoid reallocating the field slice while appending.
func ReadAll ¶ added in v0.6.0
func ReadAll(r RecordReader) ([]*Record, error)
ReadAll reads every record from r until io.EOF and returns them in order, or the records read so far together with the first error. It is the loop each codec's ReadFile shares.
func (*Record) Accessibility ¶ added in v0.2.0
func (r *Record) Accessibility() Accessibility
Accessibility gathers the record's accessibility metadata from the 008, 007, 341 and 532 fields. The result is always valid (its zero value means none was found); see Accessibility.Empty.
func (*Record) AddField ¶
AddField appends a field to the record and returns the record for chaining.
func (*Record) AlternateGraphic ¶ added in v0.2.0
AlternateGraphic returns the field linked to f through subfield $6: the 880 field when f is a regular field, or the regular field when f is an 880. It matches on the tag and occurrence number and returns false when f carries no linkage or no partner is present.
func (*Record) Control008 ¶ added in v0.2.0
func (r *Record) Control008() (Control008, bool)
Control008 returns the parsed 008 control field, or false if the record has no 008 or one too short to hold the common header (18 characters).
func (*Record) ControlField ¶
ControlField returns the raw value of the first control field with the given tag, or the empty string if none is present.
func (*Record) DataField ¶
DataField returns the first data field with the given tag and reports whether one was found.
func (*Record) DataFields ¶
DataFields returns every data field with the given tag, in order.
func (*Record) Encoding ¶
Encoding returns the record's declared character encoding (leader byte 9).
func (*Record) Fields ¶
Fields returns all fields in record order. The result is a live view of the record's internal slice: it is valid to read until the next mutating call (AddField, RemoveFields, ReplaceField, InsertField), which may reorder, overwrite, or reallocate the backing array. Retain it across a mutation only after copying.
func (*Record) InsertField ¶
InsertField inserts f keeping the record ordered by ascending tag: f is placed after any existing fields with a tag less than or equal to f's. It returns the record. Insert into an already tag-ordered record to keep it ordered.
func (*Record) RemoveFields ¶
RemoveFields removes every field with the given tag and returns the record. It compacts the field slice in place; the dropped tail is cleared so removed fields are not retained for the lifetime of the backing array.
func (*Record) ReplaceField ¶
ReplaceField replaces the first field that shares f's tag with f, or appends f when no field has that tag. It returns the record.
func (*Record) SubfieldValue ¶
SubfieldValue returns the value of the first subfield with the given code in the first data field with the given tag, or the empty string.
func (*Record) SubfieldValues ¶
SubfieldValues returns the values of every subfield with the given code across all data fields with the given tag, in order, or nil when none match. It sizes the result to the total match count in one pass, so the aggregate allocates once with no regrowth and no per-field intermediate slices.
func (*Record) Validate ¶
Validate reports the first structural problem with the record: a leader that is not 24 bytes, a field tag that is not 3 bytes, a data field with no subfields, a control field carrying subfields, or a data field carrying a raw Value. The last two would be silently dropped by every codec on write, so a record that fails them round-trips lossily. Validate returns nil when the record is structurally well-formed. It does not check tag semantics, indicator values, or character encoding.
func (*Record) Vernacular ¶ added in v0.2.0
Vernacular returns the given subfield from the 880 field linked to the first field with the given tag that has a linked alternate-script (880) partner, or "" if none does. It is a shortcut for the common case of reading an original-script title or name.
type RecordCounter ¶ added in v0.23.0
type RecordCounter interface {
Total() int
}
RecordCounter is the optional interface a RecordReader implements when its source announces the size of the result set up front, as the SRU and Z39.50 search readers do. Test for it with a type assertion:
if rc, ok := r.(codex.RecordCounter); ok && rc.Total() >= 0 {
log.Printf("%d hits", rc.Total())
}
Total reports the number of records the source says its result set holds, or -1 when that is not known: before the first successful fetch, and for the lifetime of a stream whose server never reports a count. Zero is a real answer, meaning the result set is empty.
type RecordReader ¶
RecordReader reads MARC records one at a time from an underlying stream. Each format subpackage provides an implementation; Read returns io.EOF when the stream is exhausted.
type RecordWriter ¶
RecordWriter serializes MARC records to an underlying stream. Each format subpackage provides an implementation.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package bibframe converts MARC 21 records to BIBFRAME 2.0, the Library of Congress linked-data model that replaces the flat MARC record with an RDF graph of related resources: a bf:Work (the intellectual content) and a bf:Instance (a particular publication of it), linked by bf:instanceOf / bf:hasInstance.
|
Package bibframe converts MARC 21 records to BIBFRAME 2.0, the Library of Congress linked-data model that replaces the flat MARC record with an RDF graph of related resources: a bf:Work (the intellectual content) and a bf:Instance (a particular publication of it), linked by bf:instanceOf / bf:hasInstance. |
|
Package citation converts MARC 21 records to the RIS and BibTeX citation formats used by reference managers (Zotero, EndNote, Mendeley) and LaTeX.
|
Package citation converts MARC 21 records to the RIS and BibTeX citation formats used by reference managers (Zotero, EndNote, Mendeley) and LaTeX. |
|
cmd
|
|
|
libcodex
command
Command libcodex is a small toolkit for inspecting and converting the bibliographic records the libcodex library reads and writes.
|
Command libcodex is a small toolkit for inspecting and converting the bibliographic records the libcodex library reads and writes. |
|
Package dublincore converts MARC 21 records to Dublin Core (DCMI), the lowest-common-denominator metadata used by OAI-PMH and most repository software.
|
Package dublincore converts MARC 21 records to Dublin Core (DCMI), the lowest-common-denominator metadata used by OAI-PMH and most repository software. |
|
internal
|
|
|
crosswalk
Package crosswalk holds the small MARC-field helpers shared by the derivative export codecs (mods, dublincore, citation, schemaorg, unimarc): ISBD punctuation trimming, subfield joining, subject assembly, year extraction, and JSON string escaping.
|
Package crosswalk holds the small MARC-field helpers shared by the derivative export codecs (mods, dublincore, citation, schemaorg, unimarc): ISBD punctuation trimming, subfield joining, subject assembly, year extraction, and JSON string escaping. |
|
iso5426
Package iso5426 transcodes between the ISO 5426 character set — the extended Latin character set used by UNIMARC records — and UTF-8.
|
Package iso5426 transcodes between the ISO 5426 character set — the extended Latin character set used by UNIMARC records — and UTF-8. |
|
iso5426/gen
command
Command gen produces tables_gen.go from the ISO 5426 .ucm mapping (the ICU Unicode character map for ISO 5426, the UNIMARC extended-Latin character set).
|
Command gen produces tables_gen.go from the ISO 5426 .ucm mapping (the ICU Unicode character map for ISO 5426, the UNIMARC extended-Latin character set). |
|
marc8
Package marc8 transcodes between MARC-8 byte sequences and UTF-8, supporting every MARC-8 graphic character set:
|
Package marc8 transcodes between MARC-8 byte sequences and UTF-8, supporting every MARC-8 graphic character set: |
|
marc8/gen
command
Command gen produces tables_gen.go from the Library of Congress MARC-8 code tables (codetables.xml), the authoritative mapping between MARC-8 and Unicode.
|
Command gen produces tables_gen.go from the Library of Congress MARC-8 code tables (codetables.xml), the authoritative mapping between MARC-8 and Unicode. |
|
Package iso2709 reads and writes MARC 21 records in the binary ISO 2709 interchange format (.mrc), implementing codex.RecordReader and codex.RecordWriter.
|
Package iso2709 reads and writes MARC 21 records in the binary ISO 2709 interchange format (.mrc), implementing codex.RecordReader and codex.RecordWriter. |
|
Package marcjson reads and writes MARC 21 records in the de-facto "MARC-in-JSON" structure (the pymarc/ruby-marc/marc4j layout), implementing codex.RecordReader and codex.RecordWriter with a hand-rolled tokenizer (see scan.go) rather than encoding/json, so both directions avoid reflection and most per-token allocation.
|
Package marcjson reads and writes MARC 21 records in the de-facto "MARC-in-JSON" structure (the pymarc/ruby-marc/marc4j layout), implementing codex.RecordReader and codex.RecordWriter with a hand-rolled tokenizer (see scan.go) rather than encoding/json, so both directions avoid reflection and most per-token allocation. |
|
Package marcxml reads and writes MARC 21 records in the Library of Congress MARCXML "slim" serialization (namespace http://www.loc.gov/MARC21/slim), implementing codex.RecordReader and codex.RecordWriter using only encoding/xml.
|
Package marcxml reads and writes MARC 21 records in the Library of Congress MARCXML "slim" serialization (namespace http://www.loc.gov/MARC21/slim), implementing codex.RecordReader and codex.RecordWriter using only encoding/xml. |
|
Package mods converts MARC 21 records to MODS (Metadata Object Description Schema), the Library of Congress XML standard that is richer than MARCXML and near-lossless from MARC.
|
Package mods converts MARC 21 records to MODS (Metadata Object Description Schema), the Library of Congress XML standard that is richer than MARCXML and near-lossless from MARC. |
|
Package mrk reads and writes MARC 21 records in the MARCMaker / MARCBreaker mnemonic line format (".mrk"), implementing codex.RecordReader and codex.RecordWriter using only the standard library.
|
Package mrk reads and writes MARC 21 records in the MARCMaker / MARCBreaker mnemonic line format (".mrk"), implementing codex.RecordReader and codex.RecordWriter using only the standard library. |
|
Package rdf is a small, fast, dependency-free RDF toolkit.
|
Package rdf is a small, fast, dependency-free RDF toolkit. |
|
Package schemaorg converts MARC 21 records to schema.org JSON-LD — the vocabulary search engines and reading systems consume on the web.
|
Package schemaorg converts MARC 21 records to schema.org JSON-LD — the vocabulary search engines and reading systems consume on the web. |
|
Package skos reads a SKOS concept scheme (a controlled vocabulary such as homosaurus or LCSH published as RDF) and crosswalks each skos:Concept to a MARC authority record.
|
Package skos reads a SKOS concept scheme (a controlled vocabulary such as homosaurus or LCSH published as RDF) and crosswalks each skos:Concept to a MARC authority record. |
|
Package sru is a client for the SRU (Search/Retrieve via URL) protocol, the modern HTTP successor to Z39.50 used by library catalogs for search and retrieval.
|
Package sru is a client for the SRU (Search/Retrieve via URL) protocol, the modern HTTP successor to Z39.50 used by library catalogs for search and retrieval. |
|
Package unimarc reads UNIMARC bibliographic records and maps them to the MARC 21 model (the codex.Record), so a UNIMARC record flows through every libcodex exporter (mods, dublincore, citation, bibframe, schemaorg).
|
Package unimarc reads UNIMARC bibliographic records and maps them to the MARC 21 model (the codex.Record), so a UNIMARC record flows through every libcodex exporter (mods, dublincore, citation, bibframe, schemaorg). |
|
Package z3950 is a client for the Z39.50 information-retrieval protocol (ANSI/NISO Z39.50 / ISO 23950), the classic library search protocol that SRU succeeded.
|
Package z3950 is a client for the Z39.50 information-retrieval protocol (ANSI/NISO Z39.50 / ISO 23950), the classic library search protocol that SRU succeeded. |