bibframe

package
v0.26.1 Latest Latest
Warning

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

Go to latest
Published: Jul 10, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

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.

BIBFRAME is a different data model than MARC — a graph, not a leader+fields record — so this is a one-way MARC->BIBFRAME crosswalk, not a codec, following a subset of the LoC marc2bibframe2 mapping. Two serializations are produced, both hand-written with the standard library only (no RDF dependency):

  • RDF/XML (Encode / Writer / WriteFile) — the canonical LoC serialization.
  • JSON-LD (EncodeJSONLD / JSONLDWriter / WriteJSONLDFile).

The collection Writers implement codex.RecordWriter, so they plug into codex.Convert as conversion targets; both wrap their records in a container (an rdf:RDF element or a JSON-LD @graph) and must be closed:

w := bibframe.NewWriter(out) // RDF/XML; or NewJSONLDWriter for JSON-LD
codex.Convert(iso2709.NewReader(src), w)
w.Close()

The crosswalk covers the common fields (titles, contributions, subjects, language, classification, summary on the Work; title, provision, extent, edition, identifiers and electronic locator on the Instance). Fields outside that set are not carried, and BIBFRAME cannot round-trip back to full MARC.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Decode added in v0.3.0

func Decode(data []byte) ([]*codex.Record, error)

Decode parses a BIBFRAME document — RDF/XML, JSON-LD, Turtle or N-Triples, autodetected — and reverse-crosswalks every bf:Work (with its linked bf:Instance) to a MARC 21 record. It reads the vocabulary the forward crosswalk emits and the common shape of LoC marc2bibframe2 output. BIBFRAME is a lossier model than MARC, so the result carries the crosswalked fields rather than reproducing the original record byte for byte; re-encoding it yields an equivalent BIBFRAME graph.

func Encode

func Encode(r *codex.Record) ([]byte, error)

Encode converts a record to a standalone BIBFRAME RDF/XML document.

func EncodeJSONLD

func EncodeJSONLD(r *codex.Record) ([]byte, error)

EncodeJSONLD converts a record to a standalone BIBFRAME JSON-LD document.

func EncodeNQuads added in v0.4.0

func EncodeNQuads(r *codex.Record, graph rdf.Term) ([]byte, error)

EncodeNQuads converts a record to a BIBFRAME N-Quads document whose statements are all tagged with the given graph term — the record's provenance, or named graph. A zero-value graph term produces plain N-Triples (the default graph).

func EncodeNTriples added in v0.3.0

func EncodeNTriples(r *codex.Record) ([]byte, error)

EncodeNTriples converts a record to a standalone BIBFRAME N-Triples document.

func EncodeTurtle added in v0.3.0

func EncodeTurtle(r *codex.Record) ([]byte, error)

EncodeTurtle converts a record to a standalone BIBFRAME Turtle document.

func Provenance added in v0.4.0

func Provenance(graph, source, agent rdf.Term, generatedAt string) *rdf.Graph

Provenance returns PROV-O triples describing a named graph as an entity that was generated from a source, attributed to an agent, at a time — the nanopublication / W3C PROV pattern of asserting provenance with the data-graph IRI itself as the subject, kept distinct from the data it describes. This complements the in-graph bf:AdminMetadata: AdminMetadata travels inside every serialization for BIBFRAME consumers, while these triples give an N-Quads dataset a separate, machine-readable provenance record about each named graph.

Zero-value source or agent terms and an empty generatedAt are omitted. Serialize the result into a provenance graph alongside the data graph named by graph, e.g. with an rdf.Encoder:

var enc rdf.Encoder
buf = enc.AppendNQuads(buf, dataGraph, g)                         // the record, in graph g
buf = enc.AppendNQuads(buf, bibframe.Provenance(g, src, who, ts), provGraph) // its provenance

func ReadFile added in v0.3.0

func ReadFile(path string) ([]*codex.Record, error)

ReadFile reads and decodes every BIBFRAME record in the file at path.

func RecordGraph added in v0.4.0

func RecordGraph(r *codex.Record, idx int) rdf.Term

RecordGraph returns a per-record provenance graph term derived from the record's control number (field 001), or from the stream index idx when the record has no 001, so each record's statements land in a distinct named graph. It is the default graphFor argument to NewNQuadsWriter.

func WriteFile

func WriteFile(path string, records []*codex.Record) error

WriteFile converts every record to a BIBFRAME RDF/XML file.

func WriteJSONLDFile

func WriteJSONLDFile(path string, records []*codex.Record) error

WriteJSONLDFile converts every record to a BIBFRAME JSON-LD file.

func WriteNQuadsFile added in v0.4.0

func WriteNQuadsFile(path string, records []*codex.Record, graphFor func(*codex.Record, int) rdf.Term) error

WriteNQuadsFile writes every record to path as one N-Quads document, tagging each record's statements with the graph term returned by graphFor.

func WriteNTriplesFile added in v0.3.0

func WriteNTriplesFile(path string, records []*codex.Record) error

WriteNTriplesFile writes every record to path as one N-Triples document.

func WriteTurtleFile added in v0.3.0

func WriteTurtleFile(path string, records []*codex.Record) error

WriteTurtleFile writes every record to path as one Turtle document.

Types

type AdminMetadata added in v0.4.0

type AdminMetadata struct {
	ControlNumber          string   // field 001
	ControlOrg             string   // field 003 -- the agency that assigned the 001
	ChangeDate             string   // field 005, as an xsd:dateTime string
	OrigAgency             string   // field 040 $a -- the original cataloging agency
	DescriptionLanguage    string   // field 040 $b -- the language of the description
	Transcriber            string   // field 040 $c -- the transcribing agency
	Modifiers              []string // field 040 $d (repeatable) -- the modifying agencies
	DescriptionConventions []string // field 040 $e (e.g. "rda"), one per $e
}

AdminMetadata is administrative provenance about the record's description — the BIBFRAME bf:AdminMetadata carrying the record control number, the cataloging conventions, the last-change date, and the generation process that produced the RDF. It is what the LoC/BIBFRAME ecosystem reads for provenance.

type BIBFRAME

type BIBFRAME struct {
	Work     Work
	Instance Instance
}

BIBFRAME is the Work/Instance pair derived from one MARC record.

func FromRecord

func FromRecord(r *codex.Record) *BIBFRAME

FromRecord maps a MARC record to a BIBFRAME Work/Instance pair in a single pass over the fields, following the common-field crosswalk.

func (*BIBFRAME) Graph added in v0.6.0

func (bib *BIBFRAME) Graph(base string) *rdf.Graph

Graph builds the RDF graph of a BIBFRAME Work/Instance pair, using base as the local-identifier stem for the node IRIs (#<base>Work and #<base>Instance). It is the entry point for callers that assemble a BIBFRAME directly from a non-MARC source and want the same graph shape FromRecord produces; serialize the result with rdf's NQuads, NTriples or Turtle encoders. FromRecord(r).Graph( base) is equivalent to the graph the record writers emit.

base is sanitized to the characters valid in an IRI fragment (dropping spaces, '#', '/', etc.), so a caller-supplied identifier cannot produce an invalid node IRI (e.g. "#my idWork") or defeat the reader's controlNumber recovery.

type Classification

type Classification struct {
	Class       string // "ClassificationLcc", "ClassificationDdc" or "Classification"
	Value       string // classification portion ($a)
	Label       string // human display text for the coded Value (rdfs:label); display-only, optional
	ItemPortion string // item/cutter portion (bf:itemPortion, $b); optional
	Edition     string // Dewey edition (bf:edition): "full" or "abridged"; optional
	Source      string // classification scheme (bf:source), e.g. "bisacsh"; optional
}

Classification is a call number with its BIBFRAME class.

type Contribution

type Contribution struct {
	Primary bool   // a bflc:PrimaryContribution (1xx) vs a plain bf:Contribution (7xx)
	Class   string // agent class: "Person", "Family", "Organization", "Jurisdiction" or "Meeting"
	Label   string // agent name
	Roles   []Role // controlled and/or literal roles, in field order
}

Contribution links an Agent to the Work with zero or more roles.

type DigitalCharacteristic added in v0.11.0

type DigitalCharacteristic struct {
	Class string // "FileType" or "EncodingFormat"
	Label string
}

DigitalCharacteristic is one 347 digital-file characteristic: the bflc class refining it (FileType for $a, EncodingFormat for $b) and its label.

type ElectronicLocator added in v0.15.0

type ElectronicLocator struct {
	URL       string // $u -- the access URL (the node IRI)
	Materials string // $3 -- materials specified, e.g. "Image", "Thumbnail", "Excerpt"; the display label
	Note      string // $z -- public note
	LinkText  string // $y -- link text to display in place of the URL
}

ElectronicLocator is one 856 access link: the URL plus the display context real vendor records carry alongside it. On the graph it is an rdf:Description node (the URL as its IRI) hanging off bf:electronicLocator, with Materials as rdfs:label, Note as a literal bf:note, and LinkText as a bf:note node typed bf:noteType "link text".

type Identifier

type Identifier struct {
	Class     string // "Isbn", "Issn" or "Identifier"
	Value     string
	Source    string // identifier scheme (bf:source), e.g. a provider code; optional
	Qualifier string // qualifying note (bf:qualifier), e.g. "electronic bk"; optional
	Status    string // bf:status: statusCancInv or statusIncorrect; "" when valid
}

Identifier is a typed identifier carried by the Instance.

type Instance

type Instance struct {
	Titles                  []Title
	VariantTitles           []VariantTitle // 246 cover/spine titles
	ResponsibilityStatement string
	EditionStatement        string
	Provisions              []Provision
	CopyrightDate           string // 264 _4 $c -> bf:copyrightDate; optional
	Extent                  []string
	Dimensions              []string                // 300 $c -> bf:dimensions
	Duration                []string                // 306 $a playing times -> bf:duration
	Media                   []RDATerm               // RDA media types (337) -> bf:media
	Carrier                 []RDATerm               // RDA carrier types (338) -> bf:carrier
	DigitalCharacteristics  []DigitalCharacteristic // 347 -> bf:digitalCharacteristic
	Issuance                string                  // mode of issuance (leader/07) -> bf:issuance IRI; optional
	Notes                   []Note                  // 5xx notes routed to the Instance (e.g. 500 general, 504 bibliography)
	Identifiers             []Identifier
	ElectronicLocator       []ElectronicLocator
	Admin                   *AdminMetadata
}

Instance is a particular publication of the Work (bf:Instance).

type JSONLDWriter

type JSONLDWriter struct {
	// contains filtered or unexported fields
}

JSONLDWriter converts records and writes them into a JSON-LD @graph array. Close must be called to terminate the document.

func NewJSONLDWriter

func NewJSONLDWriter(w io.Writer) *JSONLDWriter

NewJSONLDWriter returns a Writer that writes a BIBFRAME JSON-LD document to w.

func (*JSONLDWriter) Close

func (wr *JSONLDWriter) Close() error

func (*JSONLDWriter) Write

func (wr *JSONLDWriter) Write(r *codex.Record) error

type NQuadsWriter added in v0.4.0

type NQuadsWriter struct {
	// contains filtered or unexported fields
}

NQuadsWriter writes a collection of records as N-Quads, tagging each record's statements with a provenance graph term. It reuses one encoder so blank-node labels stay unique across the whole stream — otherwise two records that each number their blanks from scratch would collide and merge in the output.

func NewNQuadsWriter added in v0.4.0

func NewNQuadsWriter(w io.Writer, graphFor func(*codex.Record, int) rdf.Term) *NQuadsWriter

NewNQuadsWriter returns an NQuadsWriter over w. graphFor maps each record (and its zero-based stream index) to its provenance graph term; a nil graphFor (or one returning a zero-value term) writes the default graph, equivalent to N-Triples. It implements codex.RecordWriter, so it works as a codex.Convert target. Pass RecordGraph for a per-record named graph keyed on the control number, or the stream index when the record has no 001.

func (*NQuadsWriter) Close added in v0.4.0

func (nw *NQuadsWriter) Close() error

Close reports the first write error, if any.

func (*NQuadsWriter) Write added in v0.4.0

func (nw *NQuadsWriter) Write(r *codex.Record) error

Write serializes one record's BIBFRAME graph as N-Quads under its graph term.

type NTriplesWriter added in v0.3.0

type NTriplesWriter struct {
	// contains filtered or unexported fields
}

NTriplesWriter writes a collection of records as N-Triples. Because N-Triples has no document framing, records simply concatenate; Close is a no-op kept for API symmetry with the other writers.

func NewNTriplesWriter added in v0.3.0

func NewNTriplesWriter(w io.Writer) *NTriplesWriter

NewNTriplesWriter returns an NTriplesWriter over w. It implements codex.RecordWriter, so it works as a codex.Convert target.

func (*NTriplesWriter) Close added in v0.3.0

func (nw *NTriplesWriter) Close() error

Close reports the first write error, if any.

func (*NTriplesWriter) Write added in v0.3.0

func (nw *NTriplesWriter) Write(r *codex.Record) error

Write serializes one record's BIBFRAME graph, keeping its blank-node labels distinct from every other record's in the stream.

type Note added in v0.8.0

type Note struct {
	Type  string // bf:noteType token (e.g. "bibliography", "language"); "" for a general note
	Label string // the note text
}

Note is a typed 5xx note: a bf:noteType token (empty for a general 500 note) and the note text.

type Provision

type Provision struct {
	Class     string // "Publication", "Production", "Distribution" or "Manufacture"
	Place     string // transcribed place ($a) -> bflc:simplePlace
	Publisher string // transcribed agent ($b) -> bflc:simpleAgent
	Date      string // date ($c or 008) -> bf:date + bflc:simpleDate
	Country   string // 008/15-17 country code -> controlled bf:place IRI; optional
}

Provision is a provision-activity node (bf:Publication / bf:Production / bf:Distribution / bf:Manufacture) carrying the transcribed place / agent / date and, on the publication node, the 008 country as a controlled bf:place IRI.

type RDATerm added in v0.8.0

type RDATerm struct {
	Code  string // RDA code ($b) -> vocabulary IRI; "" for a label-only term
	Label string // RDA term ($a) -> rdfs:label
}

RDATerm is an RDA content/media/carrier term: a code ($b, driving the vocabulary IRI) and/or a transcribed label ($a).

type Reader added in v0.3.0

type Reader struct {
	// contains filtered or unexported fields
}

Reader reads BIBFRAME records from a stream. A BIBFRAME document is a single RDF graph, so the first Read parses the whole input; successive calls return the reconstructed records in document order, then io.EOF.

func NewReader added in v0.3.0

func NewReader(r io.Reader) *Reader

NewReader returns a Reader over r. It implements codex.RecordReader, so a BIBFRAME document can be a source for codex.Convert.

func (*Reader) Read added in v0.3.0

func (rd *Reader) Read() (*codex.Record, error)

Read returns the next record, or io.EOF when the document is exhausted.

type RelatedWork added in v0.8.0

type RelatedWork struct {
	Primary bool   // from a 1xx name-title main entry vs a 7xx added entry
	Class   string // creator agent class: Person/Family/Organization/Jurisdiction/Meeting
	Name    string // creator name (the subfields before $t)
	Title   Title  // the related work's title ($t)
}

RelatedWork is a name-title access point (a 1xx/7xx carrying a $t): a related bf:Work, reached by bf:relatedTo, that pairs the linking name (its creator) with the referenced work's title. This is the flat, label-oriented stand-in for m2b's Hub-routed name-title relation.

type Relation added in v0.8.0

type Relation struct {
	Relationship string // bf:relationship code (e.g. "continues", "otherPhysicalFormat")
	Name         string // linked resource creator ($a); optional
	Title        string // linked resource title ($t, or $s); the primary access point
	ISSN         string // linked resource ISSN ($x) -> bf:Issn; optional
	ISBN         string // linked resource ISBN ($z) -> bf:Isbn; optional (776 print/ebook pairing)
}

Relation is a 76x-78x work-to-work linking entry (preceding/succeeding title, host item, other physical format). It emits a bf:relation -> bf:Relation node carrying a bf:relationship vocabulary IRI and a bf:associatedResource -> bf:Work, modeled flat (a blank associated Work labeled with the linked resource's title) rather than m2b's IRI-minted Hub target.

type Role added in v0.8.0

type Role struct {
	IRI  string // relator IRI (LoC relators vocabulary or a verbatim URI); "" for a literal role
	Term string // rdfs:label text -- the role term, or the relator code when only a $4 code is present
}

Role is a single contributor role: a relator IRI (from a $4 relator code or URI) with an optional label, or a bare literal term (from $e/$j).

type Series added in v0.25.0

type Series struct {
	Title       string // 490 $a -> bf:Series / bf:title / bf:Title / bf:mainTitle
	Enumeration string // 490 $v -> bf:seriesEnumeration on the bf:Relation; optional
	ISSN        string // 490 $x -> bf:Series / bf:identifiedBy / bf:Issn; optional
	Traced      bool   // 490 ind1 = '1': series traced, an mstatus/tr alongside mstatus/t
}

Series is one transcribed series statement (490), modeled as marc2bibframe2 models it: a bf:relation on the Work whose bf:relationship is relationship/series and whose bf:associatedResource is a bf:Series. The volume designation hangs off the relation, not the series resource, because it describes how *this* work sits in the series rather than the series itself.

The shape matters beyond fidelity to LC. The predecessor emitted the statement and the enumeration as two flat literal lists on the Instance, paired by position; RDF graphs are sets, so two 490s sharing a $v collapsed into one triple and the pairing was destroyed by any conformant consumer. One relation node per 490 gives each enumeration a distinct subject.

type Subject

type Subject struct {
	Class     string // "Topic", "Place", "Person", "Organization" or "Meeting"
	Label     string
	Source    string // subject thesaurus code (bf:source), e.g. "lcsh", "mesh"; optional
	Authority string // authority IRI ($0); when set the bf:subject node is this IRI, not a blank node; optional
}

Subject is a topical, geographic or name access point on the Work.

type Title

type Title struct {
	Type       string // "" for the transcribed title, "uniform" for 130/240
	MainTitle  string
	Subtitle   string
	PartNumber string
	PartName   string
	NonSortNum string // 245 ind2 nonfiling character count (1-9) -> bflc:nonSortNum
}

Title is a bf:Title with its component portions.

type TurtleWriter added in v0.3.0

type TurtleWriter struct {
	// contains filtered or unexported fields
}

TurtleWriter writes a collection of records as Turtle, emitting the @prefix header once before the first record.

func NewTurtleWriter added in v0.3.0

func NewTurtleWriter(w io.Writer) *TurtleWriter

NewTurtleWriter returns a TurtleWriter over w. It implements codex.RecordWriter.

func (*TurtleWriter) Close added in v0.3.0

func (tw *TurtleWriter) Close() error

Close reports the first write error, if any.

func (*TurtleWriter) Write added in v0.3.0

func (tw *TurtleWriter) Write(r *codex.Record) error

Write serializes one record, preceded by the prefix header on the first call, keeping its blank-node labels distinct from every other record's in the stream.

type VariantTitle added in v0.8.0

type VariantTitle struct {
	Parallel    bool   // 246 ind2=1 -> bf:ParallelTitle, else bf:VariantTitle
	VariantType string // note-type token from 246 ind2 (cover/spine/...) -> bf:variantType; optional
	MainTitle   string
	Subtitle    string
	PartNumber  string
	PartName    string
}

VariantTitle is a 246 variant or parallel title access point.

type Work

type Work struct {
	Class         string // bf class refining bf:Work (e.g. "Text"), or ""
	Content       string // RDA content-type code (336 $b or leader/06 fallback) -> bf:content IRI; optional
	Titles        []Title
	VariantTitles []VariantTitle // 246 variant/parallel titles (non-cover/spine)
	Contributions []Contribution
	RelatedWorks  []RelatedWork
	// Relations and Series both serialize into the Work's single bf:relation
	// list, distinguished only by their bf:relationship IRI. A consumer walking
	// bf:relation must check the relationship before interpreting a node, or it
	// will read a preceding-title entry as a series statement.
	Relations       []Relation // 773/776/780/785 linking entries -> bf:relation
	Series          []Series   // 490 transcribed series statements -> bf:relation, relationship/series
	Subjects        []Subject
	GenreForms      []string
	Languages       []string // content languages: ISO 639-2 codes from 008/35-37 and 041 $a
	OriginalLangs   []string // languages of the original (041 $h) -> bf:part "original"
	Classifications []Classification
	Summary         []string
	Notes           []Note   // 5xx notes routed to the Work (e.g. 546 language)
	TableOfContents []string // 505 -> bf:tableOfContents
}

Work is the intellectual content (bf:Work) plus a specific content class.

type WorkInstances added in v0.6.0

type WorkInstances struct {
	Work      Work
	Instances []Instance
}

WorkInstances is a Work together with the Instances that realize it — different editions, formats or translations of the same intellectual content. It serializes to one BIBFRAME grain in which the Work's triples appear once and each Instance is linked to it in both directions.

func (*WorkInstances) Graph added in v0.6.0

func (wi *WorkInstances) Graph(workBase string, instanceBases []string) *rdf.Graph

Graph assembles the Work at #<workBase>Work and each Instance i at #<instanceBases[i]>Instance, linked bf:hasInstance (Work -> each Instance) and bf:instanceOf (each Instance -> Work). The work and instance bases are independent, so a caller can mint opaque ids at both tiers; every base is sanitized like BIBFRAME.Graph. len(instanceBases) must equal len(wi.Instances).

The whole grain is built with one blank-node counter, so blank labels are unique across the Work and all Instances and RDFC-1.0 canonicalization of the result is stable. Serialize it with rdf's NQuads, NTriples or Turtle encoders; a zero-Instance Work yields just the Work node. It panics if instanceBases does not match wi.Instances in length, which is a caller programming error.

func (*WorkInstances) JSONLD added in v0.7.0

func (wi *WorkInstances) JSONLD(workBase string, instanceBases []string) ([]byte, error)

JSONLD serializes a Work with N Instances to a standalone BIBFRAME JSON-LD document, the JSON-LD counterpart of RDFXML with the same graph shape and length contract.

func (*WorkInstances) RDFXML added in v0.7.0

func (wi *WorkInstances) RDFXML(workBase string, instanceBases []string) ([]byte, error)

RDFXML serializes a Work with N Instances to a standalone BIBFRAME RDF/XML document: the Work at #<workBase>Work with one bf:hasInstance per Instance, and each Instance at #<instanceBases[i]>Instance linked bf:instanceOf back. Every base is sanitized like BIBFRAME.Graph. The result parses to a graph isomorphic to WorkInstances.Graph(workBase, instanceBases). It errors if instanceBases does not match wi.Instances in length. N-Triples, Turtle and N-Quads come from the Graph method's serializers.

type Writer

type Writer struct {
	// contains filtered or unexported fields
}

Writer converts records and writes them as an rdf:RDF graph. Close must be called to emit the closing tag.

func NewWriter

func NewWriter(w io.Writer) *Writer

NewWriter returns a Writer that writes a BIBFRAME RDF/XML graph to w.

func (*Writer) Close

func (wr *Writer) Close() error

Close writes the closing </rdf:RDF> tag.

func (*Writer) Write

func (wr *Writer) Write(r *codex.Record) error

Write converts one record and writes its Work and Instance nodes.

Jump to

Keyboard shortcuts

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