marcjs
Version:
MARC record Node.js library
541 lines (450 loc) • 12.6 kB
Markdown
# marcjs
[](https://github.com/fredericd/marcjs/actions?query=workflow%3A%22Github+CI%22)
[](https://www.npmjs.com/package/marcjs)
[](https://opensource.org/licenses/MIT)
MARC record Node.js library
## Getting Started
Install the module with: `npm install marcjs`
```javascript
const { Marc, Record } = require('marcjs');
let record = new Record();
record.append(['245', ' 1', 'a', 'Middlemarch /', 'b', 'Georges Eliot.']);
console.log(record.as('Text'));
console.log(Marc.format(record, 'Marcxml'));
```
## Usage
This script reads an ISO2709 file, adds a field to each record, and writes each
record into an ISO2709 file, a MARCXML file, a JSON file, and a text file.
```javascript
const { Marc } = require('marcjs');
const fs = require('fs');
const input = fs.createReadStream('BNF-Livres-01.mrc');
const parser = Marc.createStream('Iso2709', 'Parser');
let trans = Marc.transform((record) => {
// Delete 9.. tags and add a 801 field
record.fields = record.fields.filter((field) => field[0][0] !== '9');
record.append( [ '801', ' ', 'a', 'Tamil s.a.r.l.', 'b', '2021-01-01' ] );
});
const transStream = input.pipe(parser).pipe(trans);
// Pipe the stream of transformed biblio record to 4 different writers
['marcxml', 'iso2709', 'json', 'mij', 'text'].forEach((type) => {
const output = fs.createWriteStream(`bib-edited.${type}`);
const formater = Marc.createStream(type, 'Formater');
formater.pipe(output);
transStream.pipe(formater)
});
const tick = setInterval(() => { console.log(reader.count); }, 100);
input.on('end', () => {
console.log("Number of processed biblio records: " + reader.count);
clearInterval(tick);
});
```
## `Marc` object
The Marc object has [two properties](#marc-properties):
* parser
* formater
Marc has [three functions](#marc-functions):
* createStream()
* parse()
* transform()
### `Marc` properties
The class has two properties defining the serialization formats that MARC
module is able to read and write.
* **parser** -- The serialization format that MARC can read: Iso2709,
Marcxml, and MiJ (MARC-in-JSON).
* **formater** --The serialisation format that MARC can write: Iso2709,
Marcxml, MiJ, Text, Json.
```javascript
const knownParser = Object.keys(Marc.parser);
console.log(knownParser); // Display Marc format that marcjs can parse
```
### `Marc` functions
#### createStream(type, what)
Returns a duplex stream for specific serialization formats. The stream has a
property `count` containing the number of records handled. The _type_ is the
type of serialization format: ISO2709, Marcxml, Json, MiJ. The _what_ is the
type of action the stream is doing: _Parser_ ou _Formater_.
- A parser receives data from a nodejs Stream and produces objects of type
Record.
- A formater receives Record objects and send them to a nodejs Stream.
Usage:
```javascript
const iso2709Parser = Marc.createStream('Iso2709', 'Parser');
const marcxmlParser = Marc.createStream('Marcxml', 'Parser');
const textFormater = Marc.createStream('Text', 'Formater');
```
Read an ISO2709 file and display its text version to the screen:
```javascript
const { Marc } = require('marcjs');
const fs = require('fs');
const input = fs.createReadStream('bib.mrc');
const parser = Marc.createStream('Iso2709', 'Parser');
const formater = Marc.createStream('Text', 'Formater');
input.pipe(parser).pipe(formater).pipe(process.stdout);
```
One-liner version:
```javascript
const { Marc } = require('marcjs');
const fs = require('fs');
fs.createReadStream('bib.mrc')
.pipe(Marc.createStream('Iso2709', 'Parser'))
.pipe(Marc.createStream('Text', 'Formater'))
.pipe(process.stdout);
```
Version with marcjs Duplex Node.js classes:
```javascript
const { Iso2709Parser, TextFormater } = require('marcjs');
fs.createReadStream('bib.mrc')
.pipe(new Iso2709Parser())
.pipe(new TextFormater)
.pipe(process.stdout);
```
#### parse(raw, type)
Parse a **raw** record serialized in **type** format, and returns a MARC record.
For example:
```javascript
const { Marc } = require('marcjs');
const marcxml = `<record>
<leader>01288nam 2200337 450 </leader>
<controlfield tag="001">FRBNF345958660000005</controlfield>
<datafield tag="200" ind1="1" ind2=" ">
<subfield code="a">Histoire religieuse du Maine</subfield>
<subfield code="b">Texte imprimé</subfield>
</datafield>
</record>`;
const record = Marc.parse(marcxml, 'marcxml');
```
#### format(record, type)
Format `record` with `type` serialization format. Note that:
For example:
```javascript
const { Marc } = require('marcjs);
// Get a MARC record
console.log(Marc.format(record, 'Text'));
console.log(Marc.format(record, 'Marcxml'));
```
#### transform(function)
Returns a Transform stream transforming a MARC record. It allows chaining
reading, multiple transformation, writing, via piping streams.
Example:
```javascript
const deleteSomeFields = Marc.transform((record) => {
record.delete('8..');
record.delete('6..');
});
... get a record
record = deleteSomeFields(record);
```
## `Record` Class
The Record object has [two attributes](record-attributes) :
* leader
* fields
And Record has [several methods](record-methods):
* append()
* as()
* get()
* match()
* delete()
* clone()
* mij()
### `Record` attributes
The library manipulates MARC biblio records as native Javascript objects which
have two attributes: `leader` and `fields`. Each record is a `Record` object.
Example:
```json
{
"leader": "01243nam 22002173n 450 ",
"fields": [
[
"001",
"FRBNF323046990000009"
],
[
"009",
"http://catalogue.bnf.fr/ark:/12148/cb32304699p"
],
[
"035",
" ",
"a",
"SAFIG04210003-01"
],
[
"039",
" ",
"o",
"CRI",
"a",
"SU063312260001S "
],
[
"100",
" ",
"a",
"19970701d1927 m y0frey0103 ba"
],
[
"101",
"0 ",
"a",
"eng"
],
[
"102",
" ",
"a",
"GB"
],
[
"105",
" ",
"a",
"||||z 00|||"
],
[
"106",
" ",
"a",
"r"
],
[
"200",
"1 ",
"a",
"Greek printing types",
"b",
"Texte imprimé",
"e",
", 1465-1927, facsimiles from an exhibition of books illustrating the development of Greek printing shown in the British Museum, 1927. With an historical introduction by Victor Scholderer. [Preface by Frederic G. Kenyon.]"
],
[
"210",
" ",
"a",
"London, British Museum ; B. Quaritch ; H. Milford",
"a",
"(Oxford, printed by J. Johnson)",
"d",
"1927. Gr. in-fol. (390 x 265), 23 p., fac-sim. [Don 217025] -Ia-"
],
[
"300",
" ",
"a",
"On a joint des comptes rendus extraits du ¸Times Lit. Suppl.¸, 25 August. 1927 et du ¸Library association record¸, 1927, et ¸La première Renaissance des études grecques en France, hellénistes et imprimeurs¸, par Egger, extrait de la ¸Revue de Paris¸, 15 décembre 1868"
],
[
"702",
" |",
"3",
"12331862",
"a",
"Kenyon",
"b",
"Frederic George",
"f",
"1863-1952",
"4",
"080"
],
[
"801",
" 0",
"a",
"FR",
"b",
"BNF",
"c",
"19970701",
"g",
"AFNOR",
"2",
"intermrc"
]
]
}
```
### `Record` methods
#### append()
Append an array of fields to the record. Fields are inserted in order, based on
the tag of the first field. Returns the record itself, so chaining is possible.
For example:
```javascript
record
.append(['952', ' ', 'a', 'MAIN', 'b', 'ANNEX', 'f', '12456', 'i', 'BOOK'],
['952', ' ', 'a', 'MAIN', 'b', 'MAIN', 'f', '45626', 'i', 'DVD'])
.append(['801', ' ', 'a', 'MYLIB']);
```
#### as(format)
Return a string representation of the record, in a specific format given as
method parameter:
* **text** -- A human readable version of the MARC record.
* **iso2709** -- Legacy ISO2709 format.
* **marcxml** -- Standard MARCXML.
* **json** -- JSON stringified version of the native record object.
* **mij** -- MARC-in-JSON. Alternative serialization format, as described here:
https://github.com/marc4j/marc4j/wiki/MARC-in-JSON-Description
Example:
```javascript
let { Record } = require('marcjs');
let record = new Record();
record.append(['245', ' 1', 'a', 'MARC history:', 'b', 'to the end'], ['100', ' ', 'a', 'Fredo']);
console.log(record.as('text'));
console.log(record.as('mij'));
console.log(record.as('marcxml'));
```
#### clone()
Return a new record, clone of the record.
```javascript
const clonedRecord = record.clone();
```
#### delete(match)
Delete all fiels which tag match `match` regular expression. Returns the record
itself for chaining. For example:
```javascript
record.delete(/9..|801/);
```
#### get(match)
Get fields with tag matching a regular expression. Returns an array of fiels in
MARC-in-JSON format. If you want fields in MARC native format, just to a filter:
```javascript
const fields = record.fields.filter((field) => field[0].match(/9..|801/));
```
#### match(match, cb)
```javascript
record.match(/9..|801/, (field) => {} {
```
#### mij()
Return a MARC-in-JSON object representing the MARC record. Example:
```json
{
"leader": "00705cam 2200241 450 ",
"fields": [
{
"001": "FRBNF465957890000009"
},
{
"003": "http://catalogue.bnf.fr/ark:/12148/cb46595789r"
},
{
"010": {
"subfields": [
{
"b": "Br."
}
],
"ind1": " ",
"ind2": " "
}
},
{
"100": {
"subfields": [
{
"a": "20200814g2019 m y0frey50 ba"
}
],
"ind1": " ",
"ind2": " "
}
},
{
"200": {
"subfields": [
{
"a": "Troie"
},
{
"b": "Texte imprimé"
},
{
"f": "David Gemmell"
}
],
"ind1": "1",
"ind2": " "
}
},
{
"210": {
"subfields": [
{
"a": "Paris"
},
{
"c": "Bragelonne"
},
{
"d": "DL 2016-"
}
],
"ind1": " ",
"ind2": " "
}
},
{
"700": {
"subfields": [
{
"3": "13548837"
},
{
"o": "ISNI0000000121449147"
},
{
"a": "Gemmell"
},
{
"b": "David"
},
{
"f": "1948-2006"
},
{
"4": "070"
}
],
"ind1": " ",
"ind2": "|"
}
}
]
}
```
## Other classes
Marc object return other classes than Marc and Record classes. They can be
invoqued directly.
* **Iso2709** — Duplex stream reading/writing ISO2709 serialized records.
* **Marcxml** — Duplex stream reading/writing Marcxml serialized records.
* **MiJ** — Duplex stream reading/writing MARC-in-JSON serialized records.
* **Text** — Writable stream writing Text serialized records.
* **Json** — Writable stream writing Json serialized records. It's the marcjs
native serialization format.
## CLI marcjs
A command line script **marcjs** allows MARC record files manipulation from
command line.
The module must be installed globaly: `npm i marcjs -g`.
Usage:
```bash
Usage: marc -p iso2709|marcxml|mij -f text|iso2709|marcxml|mij -o result file1 file2
```
Default parser is `iso2709` and default formater is `text`. Parser/formater must
be typed in lowercase.
Example:
```
# Same result: output a text version of bib1.mrc and bib2.mrc file
marcjs bib1.mrc bib2.mrc
marcjs -p iso2709 -f text bib1.mrc bib2.mrc
cat bib1.mrc bib2.txt | marcjs
# Output in MARC-in-JSON in bib1.mij file
marcjs -f mij -o bib1.mij bib1.mrc
```
## Versions
* V1 : Until v1.2.3 (December 2020)
* V2 : From 2.0 (January 2021) — V2 changes the way the library is called.
- V3 : From 3.0.2 (March 2025) — Major interface change. Necessary to use
properly nodejs Stream, and back pressure in order to handle very large
stream of data.
## License
Copyright (c) 2025 Frédéric Demians
Licensed under the MIT license.