@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.
- package/dist/normalize-identifiers.js +243 -0
- package/dist/normalize-identifiers.js.map +1 -0
- package/dist/normalize-identifiers.spec.js +61 -0
- package/dist/normalize-identifiers.spec.js.map +1 -0
- package/package.json +2 -2
- package/src/normalize-identifiers.js +206 -0
- package/src/normalize-identifiers.spec.js +52 -0
- package/test-fixtures/normalize-identifiers/01/expectedResult.json +8 -0
- package/test-fixtures/normalize-identifiers/01/metadata.json +5 -0
- package/test-fixtures/normalize-identifiers/01/record.json +81 -0
- package/test-fixtures/normalize-identifiers/02/expectedResult.json +92 -0
- package/test-fixtures/normalize-identifiers/02/metadata.json +5 -0
- package/test-fixtures/normalize-identifiers/02/record.json +92 -0
- package/test-fixtures/normalize-identifiers/03/expectedResult.json +63 -0
- package/test-fixtures/normalize-identifiers/03/metadata.json +5 -0
- package/test-fixtures/normalize-identifiers/03/record.json +61 -0
- package/test-fixtures/normalize-identifiers/04/expectedResult.json +79 -0
- package/test-fixtures/normalize-identifiers/04/metadata.json +5 -0
- package/test-fixtures/normalize-identifiers/04/record.json +77 -0
|
@@ -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.
|
|
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.
|
|
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,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,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,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,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
|
+
}
|