@natlibfi/marc-record-validators-melinda 9.0.11 → 9.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,243 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = _default;
7
+ exports.fieldNormalizeControlNumbers = fieldNormalizeControlNumbers;
8
+ exports.normalizeAs = normalizeAs;
9
+ exports.normalizeControlSubfieldValue = normalizeControlSubfieldValue;
10
+
11
+ var _clone = _interopRequireDefault(require("clone"));
12
+
13
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
+
15
+ // Relocated from melinda-marc-record-merge-reducers (and renamed)
16
+ //import createDebugLogger from 'debug';
17
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:normalizeIdentifiers');
18
+ function fieldToString(f) {
19
+ return `${f.tag} ${f.ind1}${f.ind2} ‡${formatSubfields(f)}`;
20
+
21
+ function formatSubfields(field) {
22
+ //return field.subfields.map(sf => `${sf.code}${sf.value || ''}`).join('‡');
23
+ return field.subfields.map(sf => `${sf.code}${sf.value}`).join(' ‡');
24
+ }
25
+ }
26
+ /*
27
+ function nvdebug(message, func) {
28
+ if (func) { // eslint-disable-line functional/no-conditional-statement
29
+ func(message);
30
+ }
31
+ console.info(message); // eslint-disable-line no-console
32
+ }
33
+ */
34
+
35
+
36
+ function _default() {
37
+ // NB! We should and could handle ISNIs here as well.
38
+ return {
39
+ description: 'Normalizes identifiers such as subfield $0 values',
40
+ validate,
41
+ fix
42
+ };
43
+
44
+ function fix(record) {
45
+ const res = {
46
+ message: [],
47
+ fix: [],
48
+ valid: true
49
+ }; //message.fix = []; // eslint-disable-line functional/immutable-data
50
+ // Actual parsing of all fields
51
+
52
+ /*
53
+ if (!record.fields) {
54
+ return false;
55
+ }
56
+ */
57
+ //nvdebug(`NORMALIZE CONTROL NUMBER FIX`, debug);
58
+
59
+ record.fields.forEach(field => {
60
+ //nvdebug(` NORMALIZE CONTROL NUMBER FIX ${fieldToString(field)}`, debug);
61
+ fieldNormalizeControlNumbers(field); //validateField(field, true, message);
62
+ }); // message.valid = !(message.message.length >= 1); // eslint-disable-line functional/immutable-data
63
+
64
+ return res;
65
+ }
66
+
67
+ function validate(record) {
68
+ const res = {
69
+ message: []
70
+ }; //nvdebug(`NORMALIZE CONTROL NUMBER VALIDATE`, debug);
71
+ // Actual parsing of all fields
72
+
73
+ /*
74
+ if (!record.fields) {
75
+ return false;
76
+ }
77
+ */
78
+
79
+ record.fields.forEach(field => {
80
+ //nvdebug(` NORMALIZE CONTROL NUMBER VALIDATE ${fieldToString(field)}`, debug);
81
+ validateField(field, res);
82
+ });
83
+ res.valid = !(res.message.length >= 1); // eslint-disable-line functional/immutable-data
84
+
85
+ return res;
86
+ }
87
+
88
+ function validateField(field, res) {
89
+ if (!field.subfields) {
90
+ return;
91
+ }
92
+
93
+ const normalizedField = (0, _clone.default)(field);
94
+ fieldNormalizeControlNumbers(normalizedField);
95
+ const orig = fieldToString(field);
96
+ const mod = fieldToString(normalizedField);
97
+
98
+ if (orig !== mod) {
99
+ // Fail as the input is "broken"/"crap"/sumthing
100
+ res.message.push(`'${orig}' could do with control number identifier normalization`); // eslint-disable-line functional/immutable-data
101
+
102
+ return;
103
+ }
104
+
105
+ return;
106
+ }
107
+ }
108
+
109
+ const alephInternal01 = '(FIN01)';
110
+ const alephInternal10 = '(FIN10)';
111
+ const alephInternal11 = '(FIN11)';
112
+ const alephInternal12 = '(FIN12)';
113
+ const alephInternal13 = '(FIN13)';
114
+ const standard01 = '(FI-MELINDA)';
115
+ const standard10 = '(FI-ASTERI-S)';
116
+ const standard11 = '(FI-ASTERI-N)';
117
+ const standard12 = '(FI-ASTERI-A)';
118
+ const standard13 = '(FI-ASTERI-W)';
119
+ const both01 = {
120
+ ALEPH_INTERNAL: alephInternal01,
121
+ STANDARD: standard01
122
+ };
123
+ const both10 = {
124
+ ALEPH_INTERNAL: alephInternal10,
125
+ STANDARD: standard10
126
+ };
127
+ const both11 = {
128
+ ALEPH_INTERNAL: alephInternal11,
129
+ STANDARD: standard11
130
+ };
131
+ const both12 = {
132
+ ALEPH_INTERNAL: alephInternal12,
133
+ STANDARD: standard12
134
+ };
135
+ const both13 = {
136
+ ALEPH_INTERNAL: alephInternal13,
137
+ STANDARD: standard13
138
+ };
139
+ const mappings = {
140
+ 'FCC': both01,
141
+ '(FI-ASTERI-A)': both12,
142
+ '(FI-ASTERI-N)': both11,
143
+ '(FI-ASTERI-S)': both10,
144
+ '(FI-ASTERI-W)': both13,
145
+ '(FI-MELINDA)': both01,
146
+ '(FIN01)': both01,
147
+ '(FIN10)': both10,
148
+ '(FIN11)': both11,
149
+ '(FIN12)': both12,
150
+ '(FIN13)': both13,
151
+ 'http://urn.fi/URN:NBN:fi:au:finaf:': both11,
152
+ 'https://urn.fi/URN:NBN:fi:au:finaf:': both11
153
+ };
154
+
155
+ function normalizeNineDigitIDs(value, targetFormat = 'ALEPH_INTERNAL') {
156
+ // $value should be prefix + nine-digits. Do nothing if nine-digit tail condition is not met:
157
+ const nineDigitTail = value.slice(-9);
158
+
159
+ if (!/^[0-9]{9}$/u.test(nineDigitTail)) {
160
+ return value;
161
+ } // Normalize prefix:
162
+
163
+
164
+ const currPrefix = value.slice(0, -9);
165
+
166
+ if (currPrefix in mappings) {
167
+ //nvdebug(`${currPrefix}, TF:${targetFormat}...`);
168
+ //nvdebug(`${JSON.stringify(mappings[currPrefix])}`);
169
+ return `${mappings[currPrefix][targetFormat]}${nineDigitTail}`;
170
+ }
171
+
172
+ return value;
173
+ }
174
+
175
+ function isIsni(value) {
176
+ if (/^\(isni\)(?: ?[0-9]{4}){4}$/u.test(value)) {
177
+ return true;
178
+ }
179
+
180
+ if (/^https:\/\/isni.org\/isni\/[0-9]{16}$/u.test(value)) {
181
+ return true;
182
+ }
183
+
184
+ return false;
185
+ }
186
+
187
+ function normalizeIsni(value) {
188
+ if (isIsni(value)) {
189
+ return `https://isni.org/isni/${value.replace(/[^0-9]/gu, '')}`;
190
+ }
191
+
192
+ return value;
193
+ }
194
+
195
+ function normalizeControlSubfieldValue(value = '', targetFormat = 'ALEPH_INTERNAL') {
196
+ if (isIsni(value)) {
197
+ return normalizeIsni(value);
198
+ }
199
+
200
+ const normalizedValue = normalizeNineDigitIDs(value, targetFormat);
201
+
202
+ if (normalizedValue !== value) {
203
+ return normalizedValue;
204
+ } // Something for isni IDs?
205
+
206
+
207
+ return value;
208
+ } //export function normalizableSubfieldPrefix(tag, sf) {
209
+
210
+
211
+ function normalizeAs(tag, subfieldCode) {
212
+ //nvdebug(`nAs ${tag}, ${subfieldCode}`);
213
+ if (subfieldCode === '0' || subfieldCode === '1' || subfieldCode === 'w') {
214
+ return 'ALEPH_INTERNAL';
215
+ }
216
+
217
+ if (tag === '035' && ['a', 'z'].includes(subfieldCode)) {
218
+ return 'STANDARD';
219
+ }
220
+
221
+ return undefined;
222
+ }
223
+
224
+ function fieldNormalizeControlNumbers(field) {
225
+ // Rename "Prefixes" as "ControlNumberIdentifiers"?
226
+ // No, since isni etc... however, just "ControlNumber" would do...
227
+ // "identifiers" ?
228
+ if (!field.subfields) {
229
+ return;
230
+ }
231
+
232
+ field.subfields.forEach(sf => {
233
+ const targetFormat = normalizeAs(field.tag, sf.code);
234
+
235
+ if (targetFormat !== undefined) {
236
+ //nvdebug(`NORMALIZE SUBFIELD $${sf.code} IN FIELD: '${fieldToString(field)}' TO ${targetFormat}`);
237
+ sf.value = normalizeControlSubfieldValue(sf.value, targetFormat); // eslint-disable-line functional/immutable-data
238
+
239
+ return;
240
+ }
241
+ });
242
+ }
243
+ //# sourceMappingURL=normalize-identifiers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize-identifiers.js","names":["fieldToString","f","tag","ind1","ind2","formatSubfields","field","subfields","map","sf","code","value","join","description","validate","fix","record","res","message","valid","fields","forEach","fieldNormalizeControlNumbers","validateField","length","normalizedField","clone","orig","mod","push","alephInternal01","alephInternal10","alephInternal11","alephInternal12","alephInternal13","standard01","standard10","standard11","standard12","standard13","both01","ALEPH_INTERNAL","STANDARD","both10","both11","both12","both13","mappings","normalizeNineDigitIDs","targetFormat","nineDigitTail","slice","test","currPrefix","isIsni","normalizeIsni","replace","normalizeControlSubfieldValue","normalizedValue","normalizeAs","subfieldCode","includes","undefined"],"sources":["../src/normalize-identifiers.js"],"sourcesContent":["// Relocated from melinda-marc-record-merge-reducers (and renamed)\n//import createDebugLogger from 'debug';\nimport clone from 'clone';\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:normalizeIdentifiers');\n\n\nfunction fieldToString(f) {\n return `${f.tag} ${f.ind1}${f.ind2} ‡${formatSubfields(f)}`;\n\n function formatSubfields(field) {\n //return field.subfields.map(sf => `${sf.code}${sf.value || ''}`).join('‡');\n return field.subfields.map(sf => `${sf.code}${sf.value}`).join(' ‡');\n }\n}\n\n/*\nfunction nvdebug(message, func) {\n if (func) { // eslint-disable-line functional/no-conditional-statement\n func(message);\n }\n console.info(message); // eslint-disable-line no-console\n}\n*/\n\nexport default function () {\n\n // NB! We should and could handle ISNIs here as well.\n return {\n description: 'Normalizes identifiers such as subfield $0 values',\n validate, fix\n };\n\n function fix(record) {\n const res = {message: [], fix: [], valid: true};\n //message.fix = []; // eslint-disable-line functional/immutable-data\n\n // Actual parsing of all fields\n /*\n if (!record.fields) {\n return false;\n }\n */\n\n //nvdebug(`NORMALIZE CONTROL NUMBER FIX`, debug);\n record.fields.forEach(field => {\n //nvdebug(` NORMALIZE CONTROL NUMBER FIX ${fieldToString(field)}`, debug);\n\n fieldNormalizeControlNumbers(field);\n //validateField(field, true, message);\n });\n\n // message.valid = !(message.message.length >= 1); // eslint-disable-line functional/immutable-data\n return res;\n }\n\n function validate(record) {\n const res = {message: []};\n //nvdebug(`NORMALIZE CONTROL NUMBER VALIDATE`, debug);\n // Actual parsing of all fields\n /*\n if (!record.fields) {\n return false;\n }\n */\n\n record.fields.forEach(field => {\n //nvdebug(` NORMALIZE CONTROL NUMBER VALIDATE ${fieldToString(field)}`, debug);\n validateField(field, res);\n });\n\n res.valid = !(res.message.length >= 1); // eslint-disable-line functional/immutable-data\n return res;\n }\n\n function validateField(field, res) {\n if (!field.subfields) {\n return;\n }\n\n const normalizedField = clone(field);\n fieldNormalizeControlNumbers(normalizedField);\n\n const orig = fieldToString(field);\n const mod = fieldToString(normalizedField);\n if (orig !== mod) { // Fail as the input is \"broken\"/\"crap\"/sumthing\n res.message.push(`'${orig}' could do with control number identifier normalization`); // eslint-disable-line functional/immutable-data\n return;\n }\n\n return;\n }\n}\n\nconst alephInternal01 = '(FIN01)';\nconst alephInternal10 = '(FIN10)';\nconst alephInternal11 = '(FIN11)';\nconst alephInternal12 = '(FIN12)';\nconst alephInternal13 = '(FIN13)';\n\nconst standard01 = '(FI-MELINDA)';\nconst standard10 = '(FI-ASTERI-S)';\nconst standard11 = '(FI-ASTERI-N)';\nconst standard12 = '(FI-ASTERI-A)';\nconst standard13 = '(FI-ASTERI-W)';\n\nconst both01 = {ALEPH_INTERNAL: alephInternal01, STANDARD: standard01};\nconst both10 = {ALEPH_INTERNAL: alephInternal10, STANDARD: standard10};\nconst both11 = {ALEPH_INTERNAL: alephInternal11, STANDARD: standard11};\nconst both12 = {ALEPH_INTERNAL: alephInternal12, STANDARD: standard12};\nconst both13 = {ALEPH_INTERNAL: alephInternal13, STANDARD: standard13};\n\nconst mappings = {\n 'FCC': both01,\n '(FI-ASTERI-A)': both12,\n '(FI-ASTERI-N)': both11,\n '(FI-ASTERI-S)': both10,\n '(FI-ASTERI-W)': both13,\n '(FI-MELINDA)': both01,\n '(FIN01)': both01,\n '(FIN10)': both10,\n '(FIN11)': both11,\n '(FIN12)': both12,\n '(FIN13)': both13,\n 'http://urn.fi/URN:NBN:fi:au:finaf:': both11,\n 'https://urn.fi/URN:NBN:fi:au:finaf:': both11\n};\n\nfunction normalizeNineDigitIDs(value, targetFormat = 'ALEPH_INTERNAL') {\n // $value should be prefix + nine-digits. Do nothing if nine-digit tail condition is not met:\n const nineDigitTail = value.slice(-9);\n if (!(/^[0-9]{9}$/u).test(nineDigitTail)) {\n return value;\n }\n // Normalize prefix:\n const currPrefix = value.slice(0, -9);\n\n if (currPrefix in mappings) {\n //nvdebug(`${currPrefix}, TF:${targetFormat}...`);\n //nvdebug(`${JSON.stringify(mappings[currPrefix])}`);\n return `${mappings[currPrefix][targetFormat]}${nineDigitTail}`;\n }\n return value;\n}\n\nfunction isIsni(value) {\n if ((/^\\(isni\\)(?: ?[0-9]{4}){4}$/u).test(value)) {\n return true;\n }\n if ((/^https:\\/\\/isni.org\\/isni\\/[0-9]{16}$/u).test(value)) {\n return true;\n }\n return false;\n}\n\nfunction normalizeIsni(value) {\n if (isIsni(value)) {\n return `https://isni.org/isni/${value.replace(/[^0-9]/gu, '')}`;\n }\n return value;\n}\n\n\nexport function normalizeControlSubfieldValue(value = '', targetFormat = 'ALEPH_INTERNAL') {\n if (isIsni(value)) {\n return normalizeIsni(value);\n }\n\n const normalizedValue = normalizeNineDigitIDs(value, targetFormat);\n if (normalizedValue !== value) {\n return normalizedValue;\n }\n\n // Something for isni IDs?\n return value;\n}\n\n//export function normalizableSubfieldPrefix(tag, sf) {\nexport function normalizeAs(tag, subfieldCode) {\n //nvdebug(`nAs ${tag}, ${subfieldCode}`);\n if (subfieldCode === '0' || subfieldCode === '1' || subfieldCode === 'w') {\n return 'ALEPH_INTERNAL';\n }\n\n if (tag === '035' && ['a', 'z'].includes(subfieldCode)) {\n return 'STANDARD';\n }\n return undefined;\n}\n\nexport function fieldNormalizeControlNumbers(field) {\n // Rename \"Prefixes\" as \"ControlNumberIdentifiers\"?\n // No, since isni etc... however, just \"ControlNumber\" would do...\n // \"identifiers\" ?\n if (!field.subfields) {\n return;\n }\n\n field.subfields.forEach(sf => {\n const targetFormat = normalizeAs(field.tag, sf.code);\n if (targetFormat !== undefined) {\n //nvdebug(`NORMALIZE SUBFIELD $${sf.code} IN FIELD: '${fieldToString(field)}' TO ${targetFormat}`);\n sf.value = normalizeControlSubfieldValue(sf.value, targetFormat); // eslint-disable-line functional/immutable-data\n return;\n }\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+
3
+ var _chai = require("chai");
4
+
5
+ var _marcRecord = require("@natlibfi/marc-record");
6
+
7
+ var _normalizeIdentifiers = _interopRequireDefault(require("./normalize-identifiers"));
8
+
9
+ var _fixura = require("@natlibfi/fixura");
10
+
11
+ var _fixugen = _interopRequireDefault(require("@natlibfi/fixugen"));
12
+
13
+ var _debug = _interopRequireDefault(require("debug"));
14
+
15
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
+
17
+ (0, _fixugen.default)({
18
+ callback,
19
+ path: [__dirname, '..', 'test-fixtures', 'normalize-identifiers'],
20
+ useMetadataFile: true,
21
+ recurse: false,
22
+ fixura: {
23
+ reader: _fixura.READERS.JSON
24
+ },
25
+ mocha: {
26
+ before: () => testValidatorFactory()
27
+ }
28
+ });
29
+ const debug = (0, _debug.default)('@natlibfi/marc-record-validators-melinda/normalize-identifiers:test');
30
+
31
+ async function testValidatorFactory() {
32
+ const validator = await (0, _normalizeIdentifiers.default)();
33
+ (0, _chai.expect)(validator).to.be.an('object').that.has.any.keys('description', 'validate');
34
+ (0, _chai.expect)(validator.description).to.be.a('string');
35
+ (0, _chai.expect)(validator.validate).to.be.a('function');
36
+ }
37
+
38
+ async function callback({
39
+ getFixture,
40
+ enabled = true,
41
+ fix = false
42
+ }) {
43
+ if (enabled === false) {
44
+ debug('TEST SKIPPED!');
45
+ return;
46
+ }
47
+
48
+ const validator = await (0, _normalizeIdentifiers.default)();
49
+ const record = new _marcRecord.MarcRecord(getFixture('record.json'));
50
+ const expectedResult = getFixture('expectedResult.json'); // console.log(expectedResult); // eslint-disable-line
51
+
52
+ if (!fix) {
53
+ const result = await validator.validate(record);
54
+ (0, _chai.expect)(result).to.eql(expectedResult);
55
+ return;
56
+ }
57
+
58
+ await validator.fix(record);
59
+ (0, _chai.expect)(record).to.eql(expectedResult);
60
+ }
61
+ //# sourceMappingURL=normalize-identifiers.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize-identifiers.spec.js","names":["generateTests","callback","path","__dirname","useMetadataFile","recurse","fixura","reader","READERS","JSON","mocha","before","testValidatorFactory","debug","createDebugLogger","validator","validatorFactory","expect","to","be","an","that","has","any","keys","description","a","validate","getFixture","enabled","fix","record","MarcRecord","expectedResult","result","eql"],"sources":["../src/normalize-identifiers.spec.js"],"sourcesContent":["import {expect} from 'chai';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './normalize-identifiers';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\nimport createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [__dirname, '..', 'test-fixtures', 'normalize-identifiers'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n mocha: {\n before: () => testValidatorFactory()\n }\n});\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/normalize-identifiers:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n expect(validator)\n .to.be.an('object')\n .that.has.any.keys('description', 'validate');\n\n expect(validator.description).to.be.a('string');\n expect(validator.validate).to.be.a('function');\n}\n\nasync function callback({getFixture, enabled = true, fix = false}) {\n if (enabled === false) {\n debug('TEST SKIPPED!');\n return;\n }\n\n const validator = await validatorFactory();\n const record = new MarcRecord(getFixture('record.json'));\n const expectedResult = getFixture('expectedResult.json');\n // console.log(expectedResult); // eslint-disable-line\n\n if (!fix) {\n const result = await validator.validate(record);\n expect(result).to.eql(expectedResult);\n return;\n }\n\n await validator.fix(record);\n expect(record).to.eql(expectedResult);\n}\n"],"mappings":";;AAAA;;AACA;;AACA;;AACA;;AACA;;AACA;;;;AAEA,IAAAA,gBAAA,EAAc;EACZC,QADY;EAEZC,IAAI,EAAE,CAACC,SAAD,EAAY,IAAZ,EAAkB,eAAlB,EAAmC,uBAAnC,CAFM;EAGZC,eAAe,EAAE,IAHL;EAIZC,OAAO,EAAE,KAJG;EAKZC,MAAM,EAAE;IACNC,MAAM,EAAEC,eAAA,CAAQC;EADV,CALI;EAQZC,KAAK,EAAE;IACLC,MAAM,EAAE,MAAMC,oBAAoB;EAD7B;AARK,CAAd;AAYA,MAAMC,KAAK,GAAG,IAAAC,cAAA,EAAkB,qEAAlB,CAAd;;AAEA,eAAeF,oBAAf,GAAsC;EACpC,MAAMG,SAAS,GAAG,MAAM,IAAAC,6BAAA,GAAxB;EAEA,IAAAC,YAAA,EAAOF,SAAP,EACGG,EADH,CACMC,EADN,CACSC,EADT,CACY,QADZ,EAEGC,IAFH,CAEQC,GAFR,CAEYC,GAFZ,CAEgBC,IAFhB,CAEqB,aAFrB,EAEoC,UAFpC;EAIA,IAAAP,YAAA,EAAOF,SAAS,CAACU,WAAjB,EAA8BP,EAA9B,CAAiCC,EAAjC,CAAoCO,CAApC,CAAsC,QAAtC;EACA,IAAAT,YAAA,EAAOF,SAAS,CAACY,QAAjB,EAA2BT,EAA3B,CAA8BC,EAA9B,CAAiCO,CAAjC,CAAmC,UAAnC;AACD;;AAED,eAAezB,QAAf,CAAwB;EAAC2B,UAAD;EAAaC,OAAO,GAAG,IAAvB;EAA6BC,GAAG,GAAG;AAAnC,CAAxB,EAAmE;EACjE,IAAID,OAAO,KAAK,KAAhB,EAAuB;IACrBhB,KAAK,CAAC,eAAD,CAAL;IACA;EACD;;EAED,MAAME,SAAS,GAAG,MAAM,IAAAC,6BAAA,GAAxB;EACA,MAAMe,MAAM,GAAG,IAAIC,sBAAJ,CAAeJ,UAAU,CAAC,aAAD,CAAzB,CAAf;EACA,MAAMK,cAAc,GAAGL,UAAU,CAAC,qBAAD,CAAjC,CARiE,CASjE;;EAEA,IAAI,CAACE,GAAL,EAAU;IACR,MAAMI,MAAM,GAAG,MAAMnB,SAAS,CAACY,QAAV,CAAmBI,MAAnB,CAArB;IACA,IAAAd,YAAA,EAAOiB,MAAP,EAAehB,EAAf,CAAkBiB,GAAlB,CAAsBF,cAAtB;IACA;EACD;;EAED,MAAMlB,SAAS,CAACe,GAAV,CAAcC,MAAd,CAAN;EACA,IAAAd,YAAA,EAAOc,MAAP,EAAeb,EAAf,CAAkBiB,GAAlB,CAAsBF,cAAtB;AACD"}
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "url": "git@github.com:natlibfi/marc-record-validators-melinda.git"
15
15
  },
16
16
  "license": "MIT",
17
- "version": "9.0.11",
17
+ "version": "9.0.12",
18
18
  "main": "./dist/index.js",
19
19
  "publishConfig": {
20
20
  "access": "public"
@@ -41,7 +41,7 @@
41
41
  "@natlibfi/marc-record-validate": "^7.0.1",
42
42
  "cld3-asm": "^3.1.1",
43
43
  "debug": "^4.3.3",
44
- "isbn3": "^1.1.18",
44
+ "isbn3": "^1.1.26",
45
45
  "langs": "^2.0.0",
46
46
  "node-fetch": "^2.6.7",
47
47
  "xml2js": ">=0.4.23 <1.0.0",
@@ -0,0 +1,206 @@
1
+ // Relocated from melinda-marc-record-merge-reducers (and renamed)
2
+ //import createDebugLogger from 'debug';
3
+ import clone from 'clone';
4
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:normalizeIdentifiers');
5
+
6
+
7
+ function fieldToString(f) {
8
+ return `${f.tag} ${f.ind1}${f.ind2} ‡${formatSubfields(f)}`;
9
+
10
+ function formatSubfields(field) {
11
+ //return field.subfields.map(sf => `${sf.code}${sf.value || ''}`).join('‡');
12
+ return field.subfields.map(sf => `${sf.code}${sf.value}`).join(' ‡');
13
+ }
14
+ }
15
+
16
+ /*
17
+ function nvdebug(message, func) {
18
+ if (func) { // eslint-disable-line functional/no-conditional-statement
19
+ func(message);
20
+ }
21
+ console.info(message); // eslint-disable-line no-console
22
+ }
23
+ */
24
+
25
+ export default function () {
26
+
27
+ // NB! We should and could handle ISNIs here as well.
28
+ return {
29
+ description: 'Normalizes identifiers such as subfield $0 values',
30
+ validate, fix
31
+ };
32
+
33
+ function fix(record) {
34
+ const res = {message: [], fix: [], valid: true};
35
+ //message.fix = []; // eslint-disable-line functional/immutable-data
36
+
37
+ // Actual parsing of all fields
38
+ /*
39
+ if (!record.fields) {
40
+ return false;
41
+ }
42
+ */
43
+
44
+ //nvdebug(`NORMALIZE CONTROL NUMBER FIX`, debug);
45
+ record.fields.forEach(field => {
46
+ //nvdebug(` NORMALIZE CONTROL NUMBER FIX ${fieldToString(field)}`, debug);
47
+
48
+ fieldNormalizeControlNumbers(field);
49
+ //validateField(field, true, message);
50
+ });
51
+
52
+ // message.valid = !(message.message.length >= 1); // eslint-disable-line functional/immutable-data
53
+ return res;
54
+ }
55
+
56
+ function validate(record) {
57
+ const res = {message: []};
58
+ //nvdebug(`NORMALIZE CONTROL NUMBER VALIDATE`, debug);
59
+ // Actual parsing of all fields
60
+ /*
61
+ if (!record.fields) {
62
+ return false;
63
+ }
64
+ */
65
+
66
+ record.fields.forEach(field => {
67
+ //nvdebug(` NORMALIZE CONTROL NUMBER VALIDATE ${fieldToString(field)}`, debug);
68
+ validateField(field, res);
69
+ });
70
+
71
+ res.valid = !(res.message.length >= 1); // eslint-disable-line functional/immutable-data
72
+ return res;
73
+ }
74
+
75
+ function validateField(field, res) {
76
+ if (!field.subfields) {
77
+ return;
78
+ }
79
+
80
+ const normalizedField = clone(field);
81
+ fieldNormalizeControlNumbers(normalizedField);
82
+
83
+ const orig = fieldToString(field);
84
+ const mod = fieldToString(normalizedField);
85
+ if (orig !== mod) { // Fail as the input is "broken"/"crap"/sumthing
86
+ res.message.push(`'${orig}' could do with control number identifier normalization`); // eslint-disable-line functional/immutable-data
87
+ return;
88
+ }
89
+
90
+ return;
91
+ }
92
+ }
93
+
94
+ const alephInternal01 = '(FIN01)';
95
+ const alephInternal10 = '(FIN10)';
96
+ const alephInternal11 = '(FIN11)';
97
+ const alephInternal12 = '(FIN12)';
98
+ const alephInternal13 = '(FIN13)';
99
+
100
+ const standard01 = '(FI-MELINDA)';
101
+ const standard10 = '(FI-ASTERI-S)';
102
+ const standard11 = '(FI-ASTERI-N)';
103
+ const standard12 = '(FI-ASTERI-A)';
104
+ const standard13 = '(FI-ASTERI-W)';
105
+
106
+ const both01 = {ALEPH_INTERNAL: alephInternal01, STANDARD: standard01};
107
+ const both10 = {ALEPH_INTERNAL: alephInternal10, STANDARD: standard10};
108
+ const both11 = {ALEPH_INTERNAL: alephInternal11, STANDARD: standard11};
109
+ const both12 = {ALEPH_INTERNAL: alephInternal12, STANDARD: standard12};
110
+ const both13 = {ALEPH_INTERNAL: alephInternal13, STANDARD: standard13};
111
+
112
+ const mappings = {
113
+ 'FCC': both01,
114
+ '(FI-ASTERI-A)': both12,
115
+ '(FI-ASTERI-N)': both11,
116
+ '(FI-ASTERI-S)': both10,
117
+ '(FI-ASTERI-W)': both13,
118
+ '(FI-MELINDA)': both01,
119
+ '(FIN01)': both01,
120
+ '(FIN10)': both10,
121
+ '(FIN11)': both11,
122
+ '(FIN12)': both12,
123
+ '(FIN13)': both13,
124
+ 'http://urn.fi/URN:NBN:fi:au:finaf:': both11,
125
+ 'https://urn.fi/URN:NBN:fi:au:finaf:': both11
126
+ };
127
+
128
+ function normalizeNineDigitIDs(value, targetFormat = 'ALEPH_INTERNAL') {
129
+ // $value should be prefix + nine-digits. Do nothing if nine-digit tail condition is not met:
130
+ const nineDigitTail = value.slice(-9);
131
+ if (!(/^[0-9]{9}$/u).test(nineDigitTail)) {
132
+ return value;
133
+ }
134
+ // Normalize prefix:
135
+ const currPrefix = value.slice(0, -9);
136
+
137
+ if (currPrefix in mappings) {
138
+ //nvdebug(`${currPrefix}, TF:${targetFormat}...`);
139
+ //nvdebug(`${JSON.stringify(mappings[currPrefix])}`);
140
+ return `${mappings[currPrefix][targetFormat]}${nineDigitTail}`;
141
+ }
142
+ return value;
143
+ }
144
+
145
+ function isIsni(value) {
146
+ if ((/^\(isni\)(?: ?[0-9]{4}){4}$/u).test(value)) {
147
+ return true;
148
+ }
149
+ if ((/^https:\/\/isni.org\/isni\/[0-9]{16}$/u).test(value)) {
150
+ return true;
151
+ }
152
+ return false;
153
+ }
154
+
155
+ function normalizeIsni(value) {
156
+ if (isIsni(value)) {
157
+ return `https://isni.org/isni/${value.replace(/[^0-9]/gu, '')}`;
158
+ }
159
+ return value;
160
+ }
161
+
162
+
163
+ export function normalizeControlSubfieldValue(value = '', targetFormat = 'ALEPH_INTERNAL') {
164
+ if (isIsni(value)) {
165
+ return normalizeIsni(value);
166
+ }
167
+
168
+ const normalizedValue = normalizeNineDigitIDs(value, targetFormat);
169
+ if (normalizedValue !== value) {
170
+ return normalizedValue;
171
+ }
172
+
173
+ // Something for isni IDs?
174
+ return value;
175
+ }
176
+
177
+ //export function normalizableSubfieldPrefix(tag, sf) {
178
+ export function normalizeAs(tag, subfieldCode) {
179
+ //nvdebug(`nAs ${tag}, ${subfieldCode}`);
180
+ if (subfieldCode === '0' || subfieldCode === '1' || subfieldCode === 'w') {
181
+ return 'ALEPH_INTERNAL';
182
+ }
183
+
184
+ if (tag === '035' && ['a', 'z'].includes(subfieldCode)) {
185
+ return 'STANDARD';
186
+ }
187
+ return undefined;
188
+ }
189
+
190
+ export function fieldNormalizeControlNumbers(field) {
191
+ // Rename "Prefixes" as "ControlNumberIdentifiers"?
192
+ // No, since isni etc... however, just "ControlNumber" would do...
193
+ // "identifiers" ?
194
+ if (!field.subfields) {
195
+ return;
196
+ }
197
+
198
+ field.subfields.forEach(sf => {
199
+ const targetFormat = normalizeAs(field.tag, sf.code);
200
+ if (targetFormat !== undefined) {
201
+ //nvdebug(`NORMALIZE SUBFIELD $${sf.code} IN FIELD: '${fieldToString(field)}' TO ${targetFormat}`);
202
+ sf.value = normalizeControlSubfieldValue(sf.value, targetFormat); // eslint-disable-line functional/immutable-data
203
+ return;
204
+ }
205
+ });
206
+ }
@@ -0,0 +1,52 @@
1
+ import {expect} from 'chai';
2
+ import {MarcRecord} from '@natlibfi/marc-record';
3
+ import validatorFactory from './normalize-identifiers';
4
+ import {READERS} from '@natlibfi/fixura';
5
+ import generateTests from '@natlibfi/fixugen';
6
+ import createDebugLogger from 'debug';
7
+
8
+ generateTests({
9
+ callback,
10
+ path: [__dirname, '..', 'test-fixtures', 'normalize-identifiers'],
11
+ useMetadataFile: true,
12
+ recurse: false,
13
+ fixura: {
14
+ reader: READERS.JSON
15
+ },
16
+ mocha: {
17
+ before: () => testValidatorFactory()
18
+ }
19
+ });
20
+ const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/normalize-identifiers:test');
21
+
22
+ async function testValidatorFactory() {
23
+ const validator = await validatorFactory();
24
+
25
+ expect(validator)
26
+ .to.be.an('object')
27
+ .that.has.any.keys('description', 'validate');
28
+
29
+ expect(validator.description).to.be.a('string');
30
+ expect(validator.validate).to.be.a('function');
31
+ }
32
+
33
+ async function callback({getFixture, enabled = true, fix = false}) {
34
+ if (enabled === false) {
35
+ debug('TEST SKIPPED!');
36
+ return;
37
+ }
38
+
39
+ const validator = await validatorFactory();
40
+ const record = new MarcRecord(getFixture('record.json'));
41
+ const expectedResult = getFixture('expectedResult.json');
42
+ // console.log(expectedResult); // eslint-disable-line
43
+
44
+ if (!fix) {
45
+ const result = await validator.validate(record);
46
+ expect(result).to.eql(expectedResult);
47
+ return;
48
+ }
49
+
50
+ await validator.fix(record);
51
+ expect(record).to.eql(expectedResult);
52
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "message": [
3
+ "'100 ‡aSirén, Matti ‡ekirjoittaja. ‡0(FI-ASTERI-N)000654321' could do with control number identifier normalization",
4
+ "'773 ‡wFCC000123456 ‡twhatever' could do with control number identifier normalization",
5
+ "'773 ‡w(FI-MELINDA)000666666 ‡twhatever 2' could do with control number identifier normalization"
6
+ ],
7
+ "valid": false
8
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "description": "Validate fields (look for normalizable subfields)",
3
+ "enabled": true,
4
+ "fix": false
5
+ }
@@ -0,0 +1,81 @@
1
+ {
2
+ "fields": [
3
+ {
4
+ "tag": "005",
5
+ "value": "20220202020202.0"
6
+ },
7
+ {
8
+ "tag": "035",
9
+ "ind1": " ",
10
+ "ind2": " ",
11
+ "subfields": [
12
+ {
13
+ "code": "a",
14
+ "value": "1234"
15
+ }
16
+ ]
17
+ },
18
+ {
19
+ "tag": "100",
20
+ "ind1": " ",
21
+ "ind2": " ",
22
+ "subfields": [
23
+ {
24
+ "code": "a",
25
+ "value": "Sirén, Matti"
26
+ },
27
+ {
28
+ "code": "e",
29
+ "value": "kirjoittaja."
30
+ },
31
+ {
32
+ "code": "0",
33
+ "value": "(FI-ASTERI-N)000654321"
34
+ }
35
+ ]
36
+ },
37
+ {
38
+ "tag": "245",
39
+ "ind1": " ",
40
+ "ind2": " ",
41
+ "subfields": [
42
+ {
43
+ "code": "a",
44
+ "value": "title"
45
+ }
46
+ ]
47
+
48
+ },
49
+ {
50
+ "tag": "773",
51
+ "ind1": " ",
52
+ "ind2": " ",
53
+ "subfields": [
54
+ {
55
+ "code": "w",
56
+ "value": "FCC000123456"
57
+ },
58
+ {
59
+ "code": "t",
60
+ "value": "whatever"
61
+ }
62
+ ]
63
+ },
64
+ {
65
+ "tag": "773",
66
+ "ind1": " ",
67
+ "ind2": " ",
68
+ "subfields": [
69
+ {
70
+ "code": "w",
71
+ "value": "(FI-MELINDA)000666666"
72
+ },
73
+ {
74
+ "code": "t",
75
+ "value": "whatever 2"
76
+ }
77
+ ]
78
+ }
79
+
80
+ ]
81
+ }
@@ -0,0 +1,92 @@
1
+ {
2
+ "_validationOptions": {},
3
+ "fields": [
4
+ {
5
+ "tag": "005",
6
+ "value": "20220202020202.0"
7
+ },
8
+ {
9
+ "ind1": " ",
10
+ "ind2": " ",
11
+ "subfields": [
12
+ {
13
+ "code": "z",
14
+ "value": "(FI-ASTERI-A)001234321"
15
+ }
16
+ ],
17
+ "tag": "035"
18
+ },
19
+ {
20
+ "ind1": " ",
21
+ "ind2": " ",
22
+ "subfields": [
23
+ {
24
+ "code": "z",
25
+ "value": "(FI-ASTERI-A)009876789"
26
+ }
27
+ ],
28
+ "tag": "035"
29
+ },
30
+ {
31
+ "ind1": " ",
32
+ "ind2": " ",
33
+ "subfields": [
34
+ {
35
+ "code": "a",
36
+ "value": "Sirén, Matti"
37
+ },
38
+ {
39
+ "code": "e",
40
+ "value": "kirjoittaja."
41
+ },
42
+ {
43
+ "code": "0",
44
+ "value": "(FIN11)000654321"
45
+ }
46
+ ],
47
+ "tag": "100"
48
+ },
49
+ {
50
+ "ind1": " ",
51
+ "ind2": " ",
52
+ "subfields": [
53
+ {
54
+ "code": "a",
55
+ "value": "title"
56
+ }
57
+ ],
58
+ "tag": "245"
59
+ },
60
+ {
61
+ "ind1": " ",
62
+ "ind2": " ",
63
+ "subfields": [
64
+ {
65
+ "code": "w",
66
+ "value": "(FIN01)000123456"
67
+ },
68
+ {
69
+ "code": "t",
70
+ "value": "whatever"
71
+ }
72
+ ],
73
+ "tag": "773"
74
+ },
75
+ {
76
+ "ind1": " ",
77
+ "ind2": " ",
78
+ "subfields": [
79
+ {
80
+ "code": "w",
81
+ "value": "(FIN01)000666666"
82
+ },
83
+ {
84
+ "code": "t",
85
+ "value": "whatever 2"
86
+ }
87
+ ],
88
+ "tag": "773"
89
+ }
90
+ ],
91
+ "leader": ""
92
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "description": "Fix (normalize) various identifiers)",
3
+ "enabled": true,
4
+ "fix": true
5
+ }
@@ -0,0 +1,92 @@
1
+ {
2
+ "fields": [
3
+ {
4
+ "tag": "005",
5
+ "value": "20220202020202.0"
6
+ },
7
+ {
8
+ "tag": "035",
9
+ "ind1": " ",
10
+ "ind2": " ",
11
+ "subfields": [
12
+ {
13
+ "code": "z",
14
+ "value": "(FIN12)001234321"
15
+ }
16
+ ]
17
+ },
18
+ {
19
+ "ind1": " ",
20
+ "ind2": " ",
21
+ "subfields": [
22
+ {
23
+ "code": "z",
24
+ "value": "(FI-ASTERI-A)009876789"
25
+ }
26
+ ],
27
+ "tag": "035"
28
+ },
29
+ {
30
+ "tag": "100",
31
+ "ind1": " ",
32
+ "ind2": " ",
33
+ "subfields": [
34
+ {
35
+ "code": "a",
36
+ "value": "Sirén, Matti"
37
+ },
38
+ {
39
+ "code": "e",
40
+ "value": "kirjoittaja."
41
+ },
42
+ {
43
+ "code": "0",
44
+ "value": "(FI-ASTERI-N)000654321"
45
+ }
46
+ ]
47
+ },
48
+ {
49
+ "tag": "245",
50
+ "ind1": " ",
51
+ "ind2": " ",
52
+ "subfields": [
53
+ {
54
+ "code": "a",
55
+ "value": "title"
56
+ }
57
+ ]
58
+
59
+ },
60
+ {
61
+ "tag": "773",
62
+ "ind1": " ",
63
+ "ind2": " ",
64
+ "subfields": [
65
+ {
66
+ "code": "w",
67
+ "value": "FCC000123456"
68
+ },
69
+ {
70
+ "code": "t",
71
+ "value": "whatever"
72
+ }
73
+ ]
74
+ },
75
+ {
76
+ "tag": "773",
77
+ "ind1": " ",
78
+ "ind2": " ",
79
+ "subfields": [
80
+ {
81
+ "code": "w",
82
+ "value": "(FI-MELINDA)000666666"
83
+ },
84
+ {
85
+ "code": "t",
86
+ "value": "whatever 2"
87
+ }
88
+ ]
89
+ }
90
+
91
+ ]
92
+ }
@@ -0,0 +1,63 @@
1
+ {
2
+ "_validationOptions": {},
3
+ "fields": [
4
+ {
5
+ "tag": "005",
6
+ "value": "20220202020202.0"
7
+ },
8
+ {
9
+ "tag": "035",
10
+ "ind1": " ",
11
+ "ind2": " ",
12
+ "subfields": [
13
+ {
14
+ "code": "a",
15
+ "value": "(FI-MELINDA)001234321"
16
+ }
17
+ ]
18
+ },
19
+ {
20
+ "tag": "035",
21
+ "ind1": " ",
22
+ "ind2": " ",
23
+ "subfields": [
24
+ {
25
+ "code": "z",
26
+ "value": "(FI-MELINDA)001234321"
27
+ }
28
+ ]
29
+ },
30
+ {
31
+ "tag": "100",
32
+ "ind1": " ",
33
+ "ind2": " ",
34
+ "subfields": [
35
+ {
36
+ "code": "a",
37
+ "value": "Sirén, Matti"
38
+ },
39
+ {
40
+ "code": "e",
41
+ "value": "kirjoittaja."
42
+ },
43
+ {
44
+ "code": "0",
45
+ "value": "(FIN11)000654321"
46
+ }
47
+ ]
48
+ },
49
+ {
50
+ "tag": "245",
51
+ "ind1": " ",
52
+ "ind2": " ",
53
+ "subfields": [
54
+ {
55
+ "code": "a",
56
+ "value": "title"
57
+ }
58
+ ]
59
+
60
+ }
61
+ ],
62
+ "leader": ""
63
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "description": "Normalize 035 $a and $z always to standardized (ISIL)<sysnro> format",
3
+ "enabled": true,
4
+ "fix": true
5
+ }
@@ -0,0 +1,61 @@
1
+ {
2
+ "fields": [
3
+ {
4
+ "tag": "005",
5
+ "value": "20220202020202.0"
6
+ },
7
+ {
8
+ "tag": "035",
9
+ "ind1": " ",
10
+ "ind2": " ",
11
+ "subfields": [
12
+ {
13
+ "code": "a",
14
+ "value": "(FI-MELINDA)001234321"
15
+ }
16
+ ]
17
+ },
18
+ {
19
+ "tag": "035",
20
+ "ind1": " ",
21
+ "ind2": " ",
22
+ "subfields": [
23
+ {
24
+ "code": "z",
25
+ "value": "(FI-MELINDA)001234321"
26
+ }
27
+ ]
28
+ },
29
+ {
30
+ "tag": "100",
31
+ "ind1": " ",
32
+ "ind2": " ",
33
+ "subfields": [
34
+ {
35
+ "code": "a",
36
+ "value": "Sirén, Matti"
37
+ },
38
+ {
39
+ "code": "e",
40
+ "value": "kirjoittaja."
41
+ },
42
+ {
43
+ "code": "0",
44
+ "value": "(FI-ASTERI-N)000654321"
45
+ }
46
+ ]
47
+ },
48
+ {
49
+ "tag": "245",
50
+ "ind1": " ",
51
+ "ind2": " ",
52
+ "subfields": [
53
+ {
54
+ "code": "a",
55
+ "value": "title"
56
+ }
57
+ ]
58
+
59
+ }
60
+ ]
61
+ }
@@ -0,0 +1,79 @@
1
+ {
2
+ "_validationOptions": {},
3
+ "fields": [
4
+ {
5
+ "tag": "005",
6
+ "value": "20220202020202.0"
7
+ },
8
+ {
9
+ "tag": "100",
10
+ "ind1": " ",
11
+ "ind2": " ",
12
+ "subfields": [
13
+ {
14
+ "code": "a",
15
+ "value": "Sirén, Matti"
16
+ },
17
+ {
18
+ "code": "e",
19
+ "value": "kirjoittaja."
20
+ },
21
+ {
22
+ "code": "0",
23
+ "value": "https://isni.org/isni/0123456789012345"
24
+ }
25
+ ]
26
+ },
27
+ {
28
+ "tag": "245",
29
+ "ind1": " ",
30
+ "ind2": " ",
31
+ "subfields": [
32
+ {
33
+ "code": "a",
34
+ "value": "title"
35
+ }
36
+ ]
37
+
38
+ },
39
+ {
40
+ "tag": "700",
41
+ "ind1": " ",
42
+ "ind2": " ",
43
+ "subfields": [
44
+ {
45
+ "code": "a",
46
+ "value": "Sukunimi, Etunimi"
47
+ },
48
+ {
49
+ "code": "e",
50
+ "value": "kirjoittaja."
51
+ },
52
+ {
53
+ "code": "0",
54
+ "value": "https://isni.org/isni/1111222233334444"
55
+ }
56
+ ]
57
+ },
58
+ {
59
+ "tag": "700",
60
+ "ind1": " ",
61
+ "ind2": " ",
62
+ "subfields": [
63
+ {
64
+ "code": "a",
65
+ "value": "Meikäläinen, Matti,"
66
+ },
67
+ {
68
+ "code": "e",
69
+ "value": "kirjoittaja."
70
+ },
71
+ {
72
+ "code": "0",
73
+ "value": "https://isni.org/isni/9876543210123456"
74
+ }
75
+ ]
76
+ }
77
+ ],
78
+ "leader": ""
79
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "description": "Normalize $0 ISNI values",
3
+ "enabled": true,
4
+ "fix": true
5
+ }
@@ -0,0 +1,77 @@
1
+ {
2
+ "fields": [
3
+ {
4
+ "tag": "005",
5
+ "value": "20220202020202.0"
6
+ },
7
+ {
8
+ "tag": "100",
9
+ "ind1": " ",
10
+ "ind2": " ",
11
+ "subfields": [
12
+ {
13
+ "code": "a",
14
+ "value": "Sirén, Matti"
15
+ },
16
+ {
17
+ "code": "e",
18
+ "value": "kirjoittaja."
19
+ },
20
+ {
21
+ "code": "0",
22
+ "value": "(isni) 0123 4567 8901 2345"
23
+ }
24
+ ]
25
+ },
26
+ {
27
+ "tag": "245",
28
+ "ind1": " ",
29
+ "ind2": " ",
30
+ "subfields": [
31
+ {
32
+ "code": "a",
33
+ "value": "title"
34
+ }
35
+ ]
36
+
37
+ },
38
+ {
39
+ "tag": "700",
40
+ "ind1": " ",
41
+ "ind2": " ",
42
+ "subfields": [
43
+ {
44
+ "code": "a",
45
+ "value": "Sukunimi, Etunimi"
46
+ },
47
+ {
48
+ "code": "e",
49
+ "value": "kirjoittaja."
50
+ },
51
+ {
52
+ "code": "0",
53
+ "value": "(isni)1111 2222 3333 4444"
54
+ }
55
+ ]
56
+ },
57
+ {
58
+ "tag": "700",
59
+ "ind1": " ",
60
+ "ind2": " ",
61
+ "subfields": [
62
+ {
63
+ "code": "a",
64
+ "value": "Meikäläinen, Matti,"
65
+ },
66
+ {
67
+ "code": "e",
68
+ "value": "kirjoittaja."
69
+ },
70
+ {
71
+ "code": "0",
72
+ "value": "https://isni.org/isni/9876543210123456"
73
+ }
74
+ ]
75
+ }
76
+ ]
77
+ }