@natlibfi/marc-record-validators-melinda 12.0.6 → 12.0.7
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/cyrillux.js +11 -11
- package/dist/cyrillux.js.map +2 -2
- package/dist/dataProvenanceUtils.js +19 -0
- package/dist/dataProvenanceUtils.js.map +7 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +2 -2
- package/dist/merge-fields/controlSubfields.js.map +2 -2
- package/dist/merge-fields/counterpartField.js +149 -152
- package/dist/merge-fields/counterpartField.js.map +3 -3
- package/dist/merge-fields/dataProvenance.js +6 -20
- package/dist/merge-fields/dataProvenance.js.map +2 -2
- package/dist/merge-fields/index.js +1 -1
- package/dist/merge-fields/index.js.map +2 -2
- package/dist/merge-fields/mergableIndicator.js +1 -2
- package/dist/merge-fields/mergableIndicator.js.map +2 -2
- package/dist/merge-fields/mergeConfig.js +2 -0
- package/dist/merge-fields/mergeConfig.js.map +2 -2
- package/dist/merge-fields/mergeConstraints.js +35 -32
- package/dist/merge-fields/mergeConstraints.js.map +3 -3
- package/dist/merge-fields/mergeField.js +4 -3
- package/dist/merge-fields/mergeField.js.map +2 -2
- package/dist/merge-fields/mergeOrAddSubfield.js +8 -7
- package/dist/merge-fields/mergeOrAddSubfield.js.map +2 -2
- package/dist/merge-fields/mergeSubfield.js +5 -1
- package/dist/merge-fields/mergeSubfield.js.map +2 -2
- package/dist/merge-fields/worldKnowledge.js +52 -0
- package/dist/merge-fields/worldKnowledge.js.map +2 -2
- package/dist/merge-fields.test.js +2 -2
- package/dist/merge-fields.test.js.map +2 -2
- package/dist/normalize-dashes.js +2 -2
- package/dist/normalize-dashes.js.map +2 -2
- package/dist/normalizeFieldForComparison.js +8 -14
- package/dist/normalizeFieldForComparison.js.map +2 -2
- package/dist/prepublicationUtils.js +1 -1
- package/dist/prepublicationUtils.js.map +2 -2
- package/dist/punctuation2.js +10 -10
- package/dist/punctuation2.js.map +2 -2
- package/dist/removeDuplicateDataFields.js +1 -24
- package/dist/removeDuplicateDataFields.js.map +2 -2
- package/dist/removeInferiorDataFields.js +3 -2
- package/dist/removeInferiorDataFields.js.map +2 -2
- package/dist/sortSubfields.js +19 -19
- package/dist/sortSubfields.js.map +2 -2
- package/dist/subfield6Utils.js +0 -1
- package/dist/subfield6Utils.js.map +2 -2
- package/dist/subfield8Utils.js +0 -5
- package/dist/subfield8Utils.js.map +2 -2
- package/dist/utils.js +29 -3
- package/dist/utils.js.map +2 -2
- package/package.json +4 -4
- package/src/cyrillux.js +11 -11
- package/src/dataProvenanceUtils.js +21 -0
- package/src/index.js +3 -1
- package/src/merge-fields/controlSubfields.js +0 -1
- package/src/merge-fields/counterpartField.js +191 -290
- package/src/merge-fields/dataProvenance.js +8 -25
- package/src/merge-fields/index.js +1 -1
- package/src/merge-fields/mergableIndicator.js +1 -2
- package/src/merge-fields/mergeConfig.js +2 -1
- package/src/merge-fields/mergeConstraints.js +39 -34
- package/src/merge-fields/mergeField.js +4 -7
- package/src/merge-fields/mergeOrAddSubfield.js +8 -7
- package/src/merge-fields/mergeSubfield.js +11 -2
- package/src/merge-fields/worldKnowledge.js +72 -3
- package/src/merge-fields.test.js +2 -2
- package/src/normalize-dashes.js +2 -2
- package/src/normalizeFieldForComparison.js +19 -20
- package/src/prepublicationUtils.js +1 -1
- package/src/punctuation2.js +10 -10
- package/src/removeDuplicateDataFields.js +24 -24
- package/src/removeInferiorDataFields.js +3 -2
- package/src/sortSubfields.js +19 -19
- package/src/subfield6Utils.js +1 -1
- package/src/subfield8Utils.js +5 -5
- package/src/utils.js +39 -12
- package/test-fixtures/cyrillux/f14/expectedResult.json +32 -0
- package/test-fixtures/cyrillux/f14/metadata.json +10 -0
- package/test-fixtures/cyrillux/f14/record.json +14 -0
- package/test-fixtures/merge-fields/f042_01/expectedResult.json +12 -0
- package/test-fixtures/merge-fields/f042_01/metadata.json +6 -0
- package/test-fixtures/merge-fields/f042_01/record.json +13 -0
- package/test-fixtures/merge-fields/f06/expectedResult.json +42 -0
- package/test-fixtures/merge-fields/f06/metadata.json +6 -0
- package/test-fixtures/merge-fields/f06/record.json +41 -0
- package/test-fixtures/merge-fields/f07/expectedResult.json +18 -0
- package/test-fixtures/merge-fields/f07/metadata.json +6 -0
- package/test-fixtures/merge-fields/f07/record.json +18 -0
- package/test-fixtures/merge-fields/f08/expectedResult.json +12 -0
- package/test-fixtures/merge-fields/f08/metadata.json +7 -0
- package/test-fixtures/merge-fields/f08/record.json +10 -0
- package/test-fixtures/merge-fields/f09/expectedResult.json +14 -0
- package/test-fixtures/merge-fields/f09/metadata.json +6 -0
- package/test-fixtures/merge-fields/f09/record.json +14 -0
- package/test-fixtures/merge-fields/f10/expectedResult.json +25 -0
- package/test-fixtures/merge-fields/f10/metadata.json +6 -0
- package/test-fixtures/merge-fields/f10/record.json +25 -0
- package/test-fixtures/merge-fields/f11/expectedResult.json +40 -0
- package/test-fixtures/merge-fields/f11/metadata.json +7 -0
- package/test-fixtures/merge-fields/f11/record.json +50 -0
- package/test-fixtures/merge-fields/f12/expectedResult.json +17 -0
- package/test-fixtures/merge-fields/f12/metadata.json +6 -0
- package/test-fixtures/merge-fields/f12/record.json +25 -0
- package/test-fixtures/merge-fields/f13/expectedResult.json +18 -0
- package/test-fixtures/merge-fields/f13/metadata.json +6 -0
- package/test-fixtures/merge-fields/f13/record.json +28 -0
- package/test-fixtures/merge-fields/f14/expectedResult.json +25 -0
- package/test-fixtures/merge-fields/f14/metadata.json +6 -0
- package/test-fixtures/merge-fields/f14/record.json +25 -0
- package/test-fixtures/merge-fields/f300_01/expectedResult.json +9 -0
- package/test-fixtures/merge-fields/f300_01/metadata.json +6 -0
- package/test-fixtures/merge-fields/f300_01/record.json +8 -0
- package/test-fixtures/merge-fields/f300_02/expectedResult.json +13 -0
- package/test-fixtures/merge-fields/f300_02/metadata.json +6 -0
- package/test-fixtures/merge-fields/f300_02/record.json +16 -0
- package/test-fixtures/merge-fields/f490_01/expectedResult.json +13 -0
- package/test-fixtures/merge-fields/f490_01/metadata.json +6 -0
- package/test-fixtures/merge-fields/f490_01/record.json +16 -0
- package/test-fixtures/remove-inferior-datafields/f17/expectedResult.json +11 -0
- package/test-fixtures/remove-inferior-datafields/f17/metadata.json +5 -0
- package/test-fixtures/remove-inferior-datafields/f17/record.json +15 -0
package/src/punctuation2.js
CHANGED
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
* (They are jumped over when looking for next (non-controlfield subfield)
|
|
11
11
|
*/
|
|
12
12
|
import {validateSingleField} from './ending-punctuation.js';
|
|
13
|
-
import {tagToDataProvenanceSubfieldCode} from './
|
|
13
|
+
import {tagToDataProvenanceSubfieldCode} from './dataProvenanceUtils.js';
|
|
14
14
|
import {fieldGetUnambiguousTag} from './subfield6Utils.js';
|
|
15
15
|
//import createDebugLogger from 'debug';
|
|
16
|
-
import {fieldToString,
|
|
16
|
+
import {fieldToString, isContentSubfieldCode, nvdebug} from './utils.js';
|
|
17
17
|
import clone from 'clone';
|
|
18
18
|
|
|
19
19
|
//const debug = createDebugLogger('debug/punctuation2');
|
|
@@ -57,7 +57,7 @@ function isIrrelevantSubfield(subfield, tag) {
|
|
|
57
57
|
if (subfield.code === dataProvenanceSubfieldCode) {
|
|
58
58
|
return true;
|
|
59
59
|
}
|
|
60
|
-
return
|
|
60
|
+
return !isContentSubfieldCode(subfield.code); // Currently this contains other stuff as well ($3, $4, $7, $9...)
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
|
|
@@ -123,16 +123,16 @@ const X00RemoveDotAfterBracket = {'code': 'cq', 'context': /\)\.$/u, 'remove': /
|
|
|
123
123
|
// 390, 800, 810, 830...
|
|
124
124
|
const cleanPuncBeforeLanguage = {'code': 'atvxyz', 'followedBy': 'l', 'context': puncIsProbablyPunc, 'remove': / *[.,:;]$/u};
|
|
125
125
|
|
|
126
|
-
const addX00aComma = {'add': ',', 'code': '
|
|
126
|
+
const addX00aComma = {'add': ',', 'code': 'abcqejt', 'followedBy': 'cdegnr', 'context': doesNotEndInPunc, 'contextRHS': allowsPuncRHS};
|
|
127
127
|
const addX00dComma = {'name': 'X00$d ending in "-" does not get comma', 'add': ',', 'code': 'd', 'followedBy': 'cdeg', 'context': /[^-,.!]$/u, 'contextRHS': allowsPuncRHS};
|
|
128
128
|
const addX00aComma2 = {'add': ',', 'code': 'abcdej', 'followedBy': 'cdeg', 'context': /(?:[A-Z]|Å|Ä|Ö)\.$/u, 'contextRHS': allowsPuncRHS};
|
|
129
129
|
const addX00Dot = {'add': '.', 'code': 'abcdetv', 'followedBy': 'fklptu', 'context': needsPuncAfterAlphanumeric};
|
|
130
130
|
const addEntryFieldFinalDot = {'name': 'X00 final dot', 'add': '.', 'code': 'abcdefghijklmnopqrstuvwxyz', 'followedBy': '#', 'context': /[^.)!?-]$/u};
|
|
131
131
|
|
|
132
132
|
|
|
133
|
-
const
|
|
133
|
+
const addXX0iColon = {name: 'Punctuate relationship information', add: ':', code: 'i', context: defaultNeedsPuncAfter2}; // Not explicitly checking it, but this should always be followed by 'a' or 't'
|
|
134
134
|
const addX10bDot = {'name': 'Add X10 pre-$b dot', 'add': '.', 'code': 'ab', 'followedBy': 'b', 'context': defaultNeedsPuncAfter2};
|
|
135
|
-
const
|
|
135
|
+
const addX10Comma = {'add': ',', 'code': 'abet', 'followedBy': 'en', 'context': defaultNeedsPuncAfter2};
|
|
136
136
|
const addX10Dot = {'name': 'Add X10 final dot', 'add': '.', 'code': 'abet', 'followedBy': 'tu#', 'context': needsPuncAfterAlphanumeric};
|
|
137
137
|
const addColonToRelationshipInformation = {'name': 'Add \':\' to 7X0 $i relationship info', 'add': ':', 'code': 'i', 'context': defaultNeedsPuncAfter2};
|
|
138
138
|
|
|
@@ -223,11 +223,11 @@ const cleanCrappyPunctuationRules = {
|
|
|
223
223
|
'946': crappy24X
|
|
224
224
|
};
|
|
225
225
|
|
|
226
|
-
const cleanLegalX00Comma = {'code': '
|
|
226
|
+
const cleanLegalX00Comma = {'code': 'abcdetn', 'followedBy': 'cdegjnr', 'context': /.,$/u, 'remove': /,$/u};
|
|
227
227
|
// Accept upper case letters in X00$b, since they are probably Roman numerals.
|
|
228
228
|
const cleanLegalX00bDot = {'code': 'b', 'followedBy': 't#', context: /^[IVXLCDM]+\.$/u, 'remove': /\.$/u};
|
|
229
229
|
const cleanLegalX00iColon = {'code': 'i', 'followedBy': 'a', 'remove': / *:$/u}; // NB! context is not needed
|
|
230
|
-
const cleanLegalX00Dot = {'code': '
|
|
230
|
+
const cleanLegalX00Dot = {'code': 'abcdetkvl', 'followedBy': 'tklu#', 'context': /(?:[a-z0-9)]|å|ä|ö)\.$/u, 'remove': /\.$/u};
|
|
231
231
|
const cleanDotBeforeLanguageSubfieldL = {'name': 'pre-language-$l dot', 'followedBy': 'l', 'context': /.\.$/u, 'remove': /\.$/u};
|
|
232
232
|
|
|
233
233
|
const legalEntryField = [cleanDotBeforeLanguageSubfieldL];
|
|
@@ -313,8 +313,8 @@ const cleanValidPunctuationRules = {
|
|
|
313
313
|
const addToAllEntryFields = [addDotBeforeLanguageSubfieldL, addSemicolonBeforeVolumeDesignation, addColonToRelationshipInformation, addEntryFieldFinalDot];
|
|
314
314
|
|
|
315
315
|
|
|
316
|
-
const addX00 = [addX00aComma, addX00aComma2, addX00Dot, addX00dComma, ...addToAllEntryFields];
|
|
317
|
-
const addX10 = [
|
|
316
|
+
const addX00 = [addXX0iColon, addX00aComma, addX00aComma2, addX00Dot, addX00dComma, ...addToAllEntryFields];
|
|
317
|
+
const addX10 = [addXX0iColon, addX10bDot, addX10Comma, addX10Dot, ...addToAllEntryFields];
|
|
318
318
|
const addX11 = [...addToAllEntryFields, addX11Spacecolon];
|
|
319
319
|
const addX30 = [...addToAllEntryFields];
|
|
320
320
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import createDebugLogger from 'debug';
|
|
2
|
-
import {
|
|
2
|
+
import {fieldToString, nvdebug} from './utils.js';
|
|
3
3
|
import {fieldHasValidSubfield6, fieldsGetOccurrenceNumbers, fieldsToNormalizedString, fieldToNormalizedString, get6s} from './subfield6Utils.js';
|
|
4
4
|
import {add8s, fieldHasLinkingNumber, fieldHasValidSubfield8, fieldsGetAllSubfield8LinkingNumbers, getSubfield8LinkingNumber, recordGetAllSubfield8LinkingNumbers, recordGetFieldsWithSubfield8LinkingNumber} from './subfield8Utils.js';
|
|
5
5
|
|
|
@@ -139,21 +139,21 @@ export function removeDuplicateSubfield8Chains(record, fix = true) {
|
|
|
139
139
|
|
|
140
140
|
let removables = []; // for validation
|
|
141
141
|
|
|
142
|
-
nvdebug("CHAIN-8");
|
|
142
|
+
//nvdebug("CHAIN-8");
|
|
143
143
|
const seenLinkingNumbers = recordGetAllSubfield8LinkingNumbers(record);
|
|
144
144
|
if (seenLinkingNumbers.length === 0) {
|
|
145
145
|
return removables;
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
nvdebug(`seen linking numbers ($8): ${seenLinkingNumbers.join(', ')}`, debug);
|
|
148
|
+
//nvdebug(`seen linking numbers ($8): ${seenLinkingNumbers.join(', ')}`, debug);
|
|
149
149
|
|
|
150
150
|
seenLinkingNumbers.forEach(currLinkingNumber => {
|
|
151
151
|
const linkedFields = recordGetFieldsWithSubfield8LinkingNumber(record, currLinkingNumber) //getFieldsWithSubfield8Index(base, baseIndex);
|
|
152
152
|
// As/If there's just one occurrence number it should be fine to use normalizeOccurrenceNumber = true
|
|
153
153
|
const normalizeOccurrenceNumber = true;
|
|
154
154
|
const linkedFieldsAsString = fieldsToNormalizedString(linkedFields, currLinkingNumber, normalizeOccurrenceNumber, true);
|
|
155
|
-
nvdebug(`Results for LINKING NUMBER ${currLinkingNumber}:`, debug);
|
|
156
|
-
nvdebug(`${linkedFieldsAsString}`, debug);
|
|
155
|
+
//nvdebug(`Results for LINKING NUMBER ${currLinkingNumber}:`, debug);
|
|
156
|
+
//nvdebug(`${linkedFieldsAsString}`, debug);
|
|
157
157
|
|
|
158
158
|
if (linkedFieldsAsString in seen) {
|
|
159
159
|
if (!removables.includes(linkedFieldsAsString)) {
|
|
@@ -161,15 +161,15 @@ export function removeDuplicateSubfield8Chains(record, fix = true) {
|
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
if (fix) {
|
|
164
|
-
nvdebug(`$8 CHAIN FIX: REMOVE $8 GROUP: ${fieldsToString(linkedFields)}`, debug);
|
|
164
|
+
//nvdebug(`$8 CHAIN FIX: REMOVE $8 GROUP: ${fieldsToString(linkedFields)}`, debug);
|
|
165
165
|
linkedFields.forEach(field => recordRemoveFieldOrSubfield8(record, field, currLinkingNumber));
|
|
166
166
|
return;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
nvdebug(`$8 VALIDATION: DUPLICATE DETECTED ${linkedFieldsAsString}`, debug);
|
|
169
|
+
//nvdebug(`$8 VALIDATION: DUPLICATE DETECTED ${linkedFieldsAsString}`, debug);
|
|
170
170
|
return;
|
|
171
171
|
}
|
|
172
|
-
nvdebug(`$8 DOUBLE REMOVAL OR VALIDATION: ADD2SEEN ${linkedFieldsAsString}`, debug);
|
|
172
|
+
//nvdebug(`$8 DOUBLE REMOVAL OR VALIDATION: ADD2SEEN ${linkedFieldsAsString}`, debug);
|
|
173
173
|
seen[linkedFieldsAsString] = 1;
|
|
174
174
|
return;
|
|
175
175
|
});
|
|
@@ -190,28 +190,28 @@ export function handleDuplicateSubfield8Chains(record, fix) {
|
|
|
190
190
|
|
|
191
191
|
let seen = {};
|
|
192
192
|
|
|
193
|
-
nvdebug("CHAIN-8");
|
|
193
|
+
//nvdebug("CHAIN-8");
|
|
194
194
|
const seenLinkingNumbers = recordGetAllSubfield8LinkingNumbers(record);
|
|
195
195
|
if (seenLinkingNumbers.length === 0) {
|
|
196
196
|
return;
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
-
nvdebug(`seen linking numbers ($8): ${seenLinkingNumbers.join(', ')}`, debug);
|
|
199
|
+
//nvdebug(`seen linking numbers ($8): ${seenLinkingNumbers.join(', ')}`, debug);
|
|
200
200
|
|
|
201
201
|
seenLinkingNumbers.forEach(currLinkingNumber => {
|
|
202
202
|
const linkedFields = recordGetFieldsWithSubfield8LinkingNumber(record, currLinkingNumber) //getFieldsWithSubfield8Index(base, baseIndex);
|
|
203
203
|
// As/If there's just one occurrence number it should be fine to use normalizeOccurrenceNumber = true
|
|
204
204
|
const normalizeOccurrenceNumber = false; //true;
|
|
205
205
|
const linkedFieldsAsString = fieldsToNormalizedString(linkedFields, currLinkingNumber, normalizeOccurrenceNumber, true);
|
|
206
|
-
nvdebug(`Results for LINKING NUMBER ${currLinkingNumber}:`, debug);
|
|
207
|
-
nvdebug(`${linkedFieldsAsString}`, debug);
|
|
206
|
+
//nvdebug(`Results for LINKING NUMBER ${currLinkingNumber}:`, debug);
|
|
207
|
+
//nvdebug(`${linkedFieldsAsString}`, debug);
|
|
208
208
|
|
|
209
209
|
if (linkedFieldsAsString in seen) {
|
|
210
|
-
nvdebug(`$8 CHAIN FIX: REMOVE $8 GROUP: ${fieldsToString(linkedFields)}`, debug);
|
|
210
|
+
//nvdebug(`$8 CHAIN FIX: REMOVE $8 GROUP: ${fieldsToString(linkedFields)}`, debug);
|
|
211
211
|
linkedFields.forEach(field => newRecordRemoveFieldOrSubfield8(record, field, currLinkingNumber, fix));
|
|
212
212
|
return;
|
|
213
213
|
}
|
|
214
|
-
nvdebug(`$8 DOUBLE REMOVAL OR VALIDATION: ADD2SEEN ${linkedFieldsAsString}`, debug);
|
|
214
|
+
//nvdebug(`$8 DOUBLE REMOVAL OR VALIDATION: ADD2SEEN ${linkedFieldsAsString}`, debug);
|
|
215
215
|
seen[linkedFieldsAsString] = 1;
|
|
216
216
|
return;
|
|
217
217
|
});
|
|
@@ -223,12 +223,12 @@ function markIdenticalSubfield6Chains(chain, record) {
|
|
|
223
223
|
const normalizeTag = chain.some(field => field.tag.substring(0, 1) === '1'); // 1XX can delete 7XX as well!
|
|
224
224
|
const chainAsString = fieldsToNormalizedString(chain, 0, normalizeOccurrenceNumber, normalizeTag);
|
|
225
225
|
|
|
226
|
-
nvdebug(`markIdenticalSubfield6Chains: ${chainAsString}`);
|
|
226
|
+
//nvdebug(`markIdenticalSubfield6Chains: ${chainAsString}`);
|
|
227
227
|
record.fields.forEach(f => compareWithChain(f));
|
|
228
228
|
|
|
229
229
|
|
|
230
230
|
function compareWithChain(f) {
|
|
231
|
-
nvdebug(`FIELD2CHAIN ${fieldToString(f)}`);
|
|
231
|
+
//nvdebug(`FIELD2CHAIN ${fieldToString(f)}`);
|
|
232
232
|
const otherChain = fieldToChain(f, record);
|
|
233
233
|
// Not a lone field or chain (head) or ... or is-same-chain
|
|
234
234
|
if (otherChain.length === 0 || sameField(chain[0], otherChain[0])) {
|
|
@@ -239,7 +239,7 @@ function markIdenticalSubfield6Chains(chain, record) {
|
|
|
239
239
|
// Mark other chain as deleted:
|
|
240
240
|
if (chainAsString === otherChainAsString) {
|
|
241
241
|
otherChain.forEach(f => {
|
|
242
|
-
nvdebug(` mark ${fieldToString(f)} as deleted ($6-chain)...`);
|
|
242
|
+
//nvdebug(` mark ${fieldToString(f)} as deleted ($6-chain)...`);
|
|
243
243
|
f.deleted = 1;
|
|
244
244
|
});
|
|
245
245
|
return;
|
|
@@ -260,7 +260,7 @@ function markIdenticalLoneFieldsAsDeletable(field, record) {
|
|
|
260
260
|
|
|
261
261
|
// Mark fields as deleted:
|
|
262
262
|
identicalLoneFields.forEach(f => {
|
|
263
|
-
nvdebug(` mark ${fieldToString(f)} as deleted (lone field)...`);
|
|
263
|
+
//nvdebug(` mark ${fieldToString(f)} as deleted (lone field)...`);
|
|
264
264
|
f.deleted = 1;
|
|
265
265
|
});
|
|
266
266
|
|
|
@@ -300,7 +300,7 @@ function acceptFieldsWithSubfield8(fieldsWithSubfield8, requireSingleTag = false
|
|
|
300
300
|
|
|
301
301
|
// If linking number
|
|
302
302
|
function anomaly8(linkingNumber) {
|
|
303
|
-
nvdebug(` Looking for anomalies in linkin number ${linkingNumber}`);
|
|
303
|
+
//nvdebug(` Looking for anomalies in linkin number ${linkingNumber}`);
|
|
304
304
|
const relevantFields = fieldsWithSubfield8.filter(f => fieldHasLinkingNumber(f, linkingNumber));
|
|
305
305
|
if (requireSingleTag) {
|
|
306
306
|
return !isSingleTagLinkingNumber(linkingNumber, relevantFields, relevantFields[0].tag);
|
|
@@ -332,7 +332,7 @@ export function fieldToChain(field, record) {
|
|
|
332
332
|
}
|
|
333
333
|
const chain = newGetAllLinkedFields(field, record, true, true);
|
|
334
334
|
|
|
335
|
-
nvdebug(` Chain contains ${chain.length} field(s)`);
|
|
335
|
+
// nvdebug(` Chain contains ${chain.length} field(s)`);
|
|
336
336
|
if (!isChainHead(field, chain)) { // newGetAllLinkedFields() marks relevant record.fields!
|
|
337
337
|
return [];
|
|
338
338
|
}
|
|
@@ -366,7 +366,7 @@ export function fieldToChain(field, record) {
|
|
|
366
366
|
|
|
367
367
|
function fieldHandleDuplicateDatafields(field, record) {
|
|
368
368
|
const chain = fieldToChain(field, record);
|
|
369
|
-
nvdebug(` TRY TO HANDLE DUPLICATES OF '${fieldsToString(chain)}'`);
|
|
369
|
+
//nvdebug(` TRY TO HANDLE DUPLICATES OF '${fieldsToString(chain)}'`);
|
|
370
370
|
|
|
371
371
|
if (chain.length === 0) {
|
|
372
372
|
return;
|
|
@@ -383,7 +383,7 @@ function fieldHandleDuplicateDatafields(field, record) {
|
|
|
383
383
|
if (fieldsWithSubfield6.length === 0) {
|
|
384
384
|
|
|
385
385
|
if (fieldsWithSubfield8.length === 0) { // chain.length === 1?
|
|
386
|
-
nvdebug(` Trying to find duplicates of single field '${fieldToString(chain[0])}'`);
|
|
386
|
+
//nvdebug(` Trying to find duplicates of single field '${fieldToString(chain[0])}'`);
|
|
387
387
|
markIdenticalLoneFieldsAsDeletable(chain[0], record);
|
|
388
388
|
return;
|
|
389
389
|
}
|
|
@@ -401,8 +401,8 @@ function fieldHandleDuplicateDatafields(field, record) {
|
|
|
401
401
|
}
|
|
402
402
|
|
|
403
403
|
|
|
404
|
-
nvdebug(` NO HANDLER FOUND FOR '${fieldsToString(chain)}'`);
|
|
405
|
-
nvdebug(` N8s: ${fieldsWithSubfield6.length}`);
|
|
404
|
+
//nvdebug(` NO HANDLER FOUND FOR '${fieldsToString(chain)}'`);
|
|
405
|
+
//nvdebug(` N8s: ${fieldsWithSubfield6.length}`);
|
|
406
406
|
|
|
407
407
|
}
|
|
408
408
|
|
|
@@ -359,12 +359,13 @@ function deriveIndividualDeletables(record) {
|
|
|
359
359
|
}
|
|
360
360
|
|
|
361
361
|
function getPrepublicationTerms(fieldAsString) {
|
|
362
|
+
const subfield7Prepub = `${fieldAsString} ‡7 Ennakkotieto`
|
|
362
363
|
if (fieldAsString.match(/^653./u)) {
|
|
363
364
|
// MET-528 (extented by MET-575)
|
|
364
|
-
return [`${fieldAsString} ‡g ENNAKKOTIETO`, `${fieldAsString} ‡g Ennakkotieto`, `${fieldAsString} ‡g ennakkotieto`, `${fieldAsString} ‡g ENNAKKOTIETO.`, `${fieldAsString} ‡g Ennakkotieto.`, `${fieldAsString} ‡g ennakkotieto.`];
|
|
365
|
+
return [subfield7Prepub, `${fieldAsString} ‡g ENNAKKOTIETO`, `${fieldAsString} ‡g Ennakkotieto`, `${fieldAsString} ‡g ennakkotieto`, `${fieldAsString} ‡g ENNAKKOTIETO.`, `${fieldAsString} ‡g Ennakkotieto.`, `${fieldAsString} ‡g ennakkotieto.`];
|
|
365
366
|
}
|
|
366
367
|
|
|
367
|
-
return [];
|
|
368
|
+
return [subfield7Prepub];
|
|
368
369
|
}
|
|
369
370
|
|
|
370
371
|
}
|
package/src/sortSubfields.js
CHANGED
|
@@ -8,8 +8,8 @@ const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:sortSu
|
|
|
8
8
|
//const debugData = debug.extend('data');
|
|
9
9
|
const debugDev = debug.extend('dev');
|
|
10
10
|
|
|
11
|
-
const defaultSortOrderStringFinns = '
|
|
12
|
-
const defaultSortOrderStringOthers = '
|
|
11
|
+
const defaultSortOrderStringFinns = '863abcdefghijklmnopqrstuvwxyz4201759'; // NB! We Finns like $2 before $0 in 6XX...
|
|
12
|
+
const defaultSortOrderStringOthers = '863abcdefghijklmnopqrstuvwxyz4021759'; // NB 760-788 have '7' in different position...
|
|
13
13
|
|
|
14
14
|
const defaultSortOrderFinns = defaultSortOrderStringFinns.split('');
|
|
15
15
|
const defaultSortOrderOthers = defaultSortOrderStringOthers.split('');
|
|
@@ -70,7 +70,7 @@ export default function (defaultTagPattern) {
|
|
|
70
70
|
const sortOrderForX00 = ['i', 'a', 'b', 'q', 'c', 'd', 'e', 't', 'u', 'l', 'f', 'x', 'y', 'z', '0', '1', '5', '9']; // skip $g. Can't remember why, though...
|
|
71
71
|
const sortOrderForX10 = ['i', 'a', 'b', 't', 'n', 'c', 'e', 'v', 'w', 'x', 'y', 'z', '0', '1', '5', '9']; // somewhat iffy
|
|
72
72
|
const sortOrderForX11 = ['a', 'n', 'd', 'c', 'e', 'g', 'j', '0', '1', '5', '9'];
|
|
73
|
-
const
|
|
73
|
+
const sortOrderFor7XXLinkingEntries = ['8', '7', 'i', 'a', 's', 't', 'b', 'c', 'd', 'm', 'h', 'k', 'o', 'x', 'z', 'g', 'q', 'w', '0', '1', 'l', '9', '5'];
|
|
74
74
|
const sortOrderFor246 = ['i', 'a', 'b', 'n', 'p', 'f', '5', '9']; // Used by field 946 as well
|
|
75
75
|
|
|
76
76
|
// List *only* exceptional order here. Otherwise default order is used.
|
|
@@ -107,22 +107,22 @@ const subfieldSortOrder = [
|
|
|
107
107
|
{'tag': '700', 'sortOrder': sortOrderForX00},
|
|
108
108
|
{'tag': '710', 'sortOrder': sortOrderForX10},
|
|
109
109
|
{'tag': '711', 'sortOrder': sortOrderForX11},
|
|
110
|
-
{'tag': '760', 'sortOrder':
|
|
111
|
-
{'tag': '762', 'sortOrder':
|
|
112
|
-
{'tag': '765', 'sortOrder':
|
|
113
|
-
{'tag': '767', 'sortOrder':
|
|
114
|
-
{'tag': '770', 'sortOrder':
|
|
115
|
-
{'tag': '772', 'sortOrder':
|
|
116
|
-
{'tag': '773', 'sortOrder':
|
|
117
|
-
{'tag': '774', 'sortOrder':
|
|
118
|
-
{'tag': '775', 'sortOrder':
|
|
119
|
-
{'tag': '776', 'sortOrder':
|
|
120
|
-
{'tag': '777', 'sortOrder':
|
|
121
|
-
{'tag': '780', 'sortOrder':
|
|
122
|
-
{'tag': '785', 'sortOrder':
|
|
123
|
-
{'tag': '786', 'sortOrder':
|
|
124
|
-
{'tag': '787', 'sortOrder':
|
|
125
|
-
{'tag': '788', 'sortOrder':
|
|
110
|
+
{'tag': '760', 'sortOrder': sortOrderFor7XXLinkingEntries},
|
|
111
|
+
{'tag': '762', 'sortOrder': sortOrderFor7XXLinkingEntries},
|
|
112
|
+
{'tag': '765', 'sortOrder': sortOrderFor7XXLinkingEntries},
|
|
113
|
+
{'tag': '767', 'sortOrder': sortOrderFor7XXLinkingEntries},
|
|
114
|
+
{'tag': '770', 'sortOrder': sortOrderFor7XXLinkingEntries},
|
|
115
|
+
{'tag': '772', 'sortOrder': sortOrderFor7XXLinkingEntries},
|
|
116
|
+
{'tag': '773', 'sortOrder': sortOrderFor7XXLinkingEntries},
|
|
117
|
+
{'tag': '774', 'sortOrder': sortOrderFor7XXLinkingEntries},
|
|
118
|
+
{'tag': '775', 'sortOrder': sortOrderFor7XXLinkingEntries},
|
|
119
|
+
{'tag': '776', 'sortOrder': sortOrderFor7XXLinkingEntries},
|
|
120
|
+
{'tag': '777', 'sortOrder': sortOrderFor7XXLinkingEntries},
|
|
121
|
+
{'tag': '780', 'sortOrder': sortOrderFor7XXLinkingEntries},
|
|
122
|
+
{'tag': '785', 'sortOrder': sortOrderFor7XXLinkingEntries},
|
|
123
|
+
{'tag': '786', 'sortOrder': sortOrderFor7XXLinkingEntries},
|
|
124
|
+
{'tag': '787', 'sortOrder': sortOrderFor7XXLinkingEntries},
|
|
125
|
+
{'tag': '788', 'sortOrder': sortOrderFor7XXLinkingEntries},
|
|
126
126
|
{'tag': '800', 'sortOrder': sortOrderForX00},
|
|
127
127
|
{'tag': '810', 'sortOrder': sortOrderForX10},
|
|
128
128
|
{'tag': '811', 'sortOrder': sortOrderForX11},
|
package/src/subfield6Utils.js
CHANGED
|
@@ -219,7 +219,7 @@ export function fieldGetOccurrenceNumberPairs(field, candFields) {
|
|
|
219
219
|
//nvdebug(` Trying to finds pair for ${fieldToString(field)} in ${candFields.length} fields`);
|
|
220
220
|
const pairs = candFields.filter(otherField => isSubfield6Pair(field, otherField));
|
|
221
221
|
if (pairs.length === 0) {
|
|
222
|
-
nvdebug(`NO PAIRS FOUND FOR '${fieldToString(field)}'`);
|
|
222
|
+
//nvdebug(`NO PAIRS FOUND FOR '${fieldToString(field)}'`);
|
|
223
223
|
return pairs;
|
|
224
224
|
}
|
|
225
225
|
//nvdebug(`${pairs.length} PAIR(S) FOUND FOR '${fieldToString(field)}'`);
|
package/src/subfield8Utils.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// import createDebugLogger from 'debug';
|
|
2
2
|
// const debug = createDebugLogger('@natlibfi/marc-record-validator-melinda/subfield8Utils');
|
|
3
3
|
|
|
4
|
-
import {fieldToString, nvdebug} from './utils.js';
|
|
4
|
+
// import {fieldToString, nvdebug} from './utils.js';
|
|
5
5
|
|
|
6
6
|
const sf8Regexp = /^([1-9][0-9]*)(?:\.[0-9]+)?(?:\\[acprux])?$/u;
|
|
7
7
|
|
|
@@ -56,7 +56,7 @@ export function fieldsGetAllSubfield8LinkingNumbers(fields) {
|
|
|
56
56
|
field.subfields.forEach(sf => {
|
|
57
57
|
const linkingNumber = getSubfield8LinkingNumber(sf);
|
|
58
58
|
if (linkingNumber > 0 && !subfield8LinkingNumbers.includes(linkingNumber)) {
|
|
59
|
-
nvdebug(` LINK8: Add subfield \$8 ${linkingNumber} to seen values list`);
|
|
59
|
+
//nvdebug(` LINK8: Add subfield \$8 ${linkingNumber} to seen values list`);
|
|
60
60
|
subfield8LinkingNumbers.push(linkingNumber);
|
|
61
61
|
}
|
|
62
62
|
});
|
|
@@ -76,10 +76,10 @@ export function add8s(fields, record) {
|
|
|
76
76
|
return fields;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
nvdebug(`Linking number(s): ${linkingNumbers.join(', ')}`);
|
|
79
|
+
//nvdebug(`Linking number(s): ${linkingNumbers.join(', ')}`);
|
|
80
80
|
linkingNumbers.forEach(number => collectLinkingNumberFields(number));
|
|
81
81
|
|
|
82
|
-
fields.forEach(f => nvdebug(`AFTER ADDING 8s: '${fieldToString(f)}'`));
|
|
82
|
+
//fields.forEach(f => nvdebug(`AFTER ADDING 8s: '${fieldToString(f)}'`));
|
|
83
83
|
|
|
84
84
|
return fields;
|
|
85
85
|
|
|
@@ -88,7 +88,7 @@ export function add8s(fields, record) {
|
|
|
88
88
|
fields = fields.filter(f => !fieldHasLinkingNumber(f, linkingNumber));
|
|
89
89
|
// Add them and their "sisters" back:
|
|
90
90
|
const addableFields = record.fields.filter(f => fieldHasLinkingNumber(f, linkingNumber));
|
|
91
|
-
addableFields.forEach(f => nvdebug(`(RE-?)ADD ${fieldToString(f)}`));
|
|
91
|
+
//addableFields.forEach(f => nvdebug(`(RE-?)ADD ${fieldToString(f)}`));
|
|
92
92
|
fields = fields.concat(addableFields);
|
|
93
93
|
|
|
94
94
|
}
|
package/src/utils.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import createDebugLogger from 'debug';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
//import path from 'path';
|
|
2
|
+
import {melindaFieldSpecs} from './melindaCustomMergeFields.js';
|
|
3
|
+
import {isDataProvenanceSubfieldCode} from './dataProvenanceUtils.js';
|
|
5
4
|
|
|
6
5
|
const debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers:utils');
|
|
7
6
|
//const debugData = debug.extend('data');
|
|
8
7
|
const debugDev = debug.extend('dev');
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
|
|
11
10
|
|
|
12
11
|
//JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'src', 'melindaCustomMergeFields.json'), 'utf8'));
|
|
13
12
|
|
|
@@ -102,19 +101,38 @@ export function nvdebugFieldArray(fields, prefix = ' ', func = undefined) {
|
|
|
102
101
|
fields.forEach(field => nvdebug(`${prefix}${fieldToString(field)}`, func));
|
|
103
102
|
}
|
|
104
103
|
|
|
105
|
-
|
|
104
|
+
function isControlSubfieldCode(subfieldCode, tag = undefined) {
|
|
106
105
|
// NB! Only $w, $0, $1, $5, $6 and $8 are really control subfields. In Finland $9 is oft a control subfield
|
|
107
|
-
|
|
108
|
-
// $4 means 'relationship' (similar to relator terms at least in X00 and similar)
|
|
109
|
-
// $7 is usually provinance subfield. However, it can be stored in other subfields as well. See merge-fields/dataProvenance.js for details
|
|
110
|
-
// However, change this only if needed. Maybe all provinance subfields should return true?
|
|
111
|
-
// This may become relevant when AI starts to create stuff...
|
|
112
|
-
if (['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'w'].includes(subfieldCode)) {
|
|
106
|
+
if (['0', '1', '2', '5', '6', '8', 'w'].includes(subfieldCode)) {
|
|
113
107
|
return true;
|
|
114
108
|
}
|
|
109
|
+
// Subfield '7' is control subfield for some tags:
|
|
110
|
+
if (tag && subfieldCode === '7') {
|
|
111
|
+
if ( tag.match(/^7[678]/u) || ['800', '810', '811', '830'].includes(tag) ) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
115
|
return false;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
export function isContentSubfieldCode(subfieldCode, tag = undefined) {
|
|
119
|
+
if (isControlSubfieldCode(subfieldCode, tag)) { // 'w', '0', '1', '5', '6' and '8'. (Also '7' for ....)
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
if (tag && isDataProvenanceSubfieldCode(subfieldCode, tag)) { // Note that default '7' is handled below
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
// $7 contains typically data provenance, sometimes it's a control field, and for f533, f856 ja f857 it's something else, but it's never content!
|
|
126
|
+
if (['2', '3', '4', '7', '9'].includes(subfieldCode)) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
118
136
|
export function getCatalogingLanguage(record, defaultCatalogingLanguage = undefined) {
|
|
119
137
|
const [field040] = record.get(/^040$/u);
|
|
120
138
|
if (!field040) {
|
|
@@ -247,4 +265,13 @@ export function subfieldArraysContainSameData(arr1, arr2) {
|
|
|
247
265
|
}
|
|
248
266
|
|
|
249
267
|
return arr2.every(sf2 => arr1.some(sf => subfieldsAreIdentical(sf, sf2)));
|
|
250
|
-
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export function tagIsRepeatable(tag) {
|
|
271
|
+
const fieldSpecs = melindaFieldSpecs.fields.filter(field => field.tag === tag);
|
|
272
|
+
if (fieldSpecs.length !== 1) {
|
|
273
|
+
debugDev(` WARNING! Getting field ${tag} data failed! Default to repeatable field.`);
|
|
274
|
+
return true;
|
|
275
|
+
}
|
|
276
|
+
return fieldSpecs[0].repeatable;
|
|
277
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_validationOptions": {},
|
|
3
|
+
"leader": "12345cam 22123454i 4500",
|
|
4
|
+
"fields": [
|
|
5
|
+
{ "tag": "008", "value": "01234567890123456789012345678901234ukr89"},
|
|
6
|
+
{ "tag": "240", "ind1": " ", "ind2": " ", "subfields": [
|
|
7
|
+
{ "code": "6", "value": "880-01" },
|
|
8
|
+
{ "code": "a", "value": "Hohol." },
|
|
9
|
+
{ "code": "l", "value": "Hohol." },
|
|
10
|
+
{ "code": "9", "value": "SFS4900 <TRANS>" }
|
|
11
|
+
]},
|
|
12
|
+
{ "tag": "776", "ind1": " ", "ind2": " ", "subfields": [
|
|
13
|
+
{ "code": "6", "value": "880-02" },
|
|
14
|
+
{ "code": "t", "value": "Hohol." },
|
|
15
|
+
{ "code": "l", "value": "Гоголь." },
|
|
16
|
+
{ "code": "9", "value": "SFS4900 <TRANS>" }
|
|
17
|
+
]},
|
|
18
|
+
{ "tag": "880", "ind1": " ", "ind2": " ", "subfields": [
|
|
19
|
+
{ "code": "6", "value": "240-01" },
|
|
20
|
+
{ "code": "a", "value": "Гоголь." },
|
|
21
|
+
{ "code": "l", "value": "Гоголь." },
|
|
22
|
+
{ "code": "9", "value": "CYRILLIC <TRANS>" }
|
|
23
|
+
]},
|
|
24
|
+
{ "tag": "880", "ind1": " ", "ind2": " ", "subfields": [
|
|
25
|
+
{ "code": "6", "value": "776-02" },
|
|
26
|
+
{ "code": "t", "value": "Гоголь." },
|
|
27
|
+
{ "code": "l", "value": "Гоголь." },
|
|
28
|
+
{ "code": "9", "value": "CYRILLIC <TRANS>" }
|
|
29
|
+
]}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "14: transliteration(SFS-4900 only) does not apply the provenance subfield $l",
|
|
3
|
+
"comment": "The point in this test is that 776$l is not transliterated as it is \"untouchable\" provenance subfield, while 240$l is transliterated.",
|
|
4
|
+
"only": false,
|
|
5
|
+
"fix": true,
|
|
6
|
+
"config": {
|
|
7
|
+
"doISO9Transliteration": false,
|
|
8
|
+
"doSFS4900Transliteration": true
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"leader": "12345cam 22123454i 4500",
|
|
3
|
+
"fields": [
|
|
4
|
+
{ "tag": "008", "value": "01234567890123456789012345678901234ukr89"},
|
|
5
|
+
{ "tag": "240", "ind1": " ", "ind2": " ", "subfields": [
|
|
6
|
+
{ "code": "a", "value": "Гоголь." },
|
|
7
|
+
{ "code": "l", "value": "Гоголь." }
|
|
8
|
+
]},
|
|
9
|
+
{ "tag": "776", "ind1": " ", "ind2": " ", "subfields": [
|
|
10
|
+
{ "code": "t", "value": "Гоголь." },
|
|
11
|
+
{ "code": "l", "value": "Гоголь." }
|
|
12
|
+
]}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"leader": "01331cam a22003494i 4500",
|
|
3
|
+
"fields": [
|
|
4
|
+
{ "tag": "042", "ind1": " ", "ind2": " ", "subfields": [
|
|
5
|
+
{ "code": "a", "value": "lc" },
|
|
6
|
+
{ "code": "a", "value": "nsdp" },
|
|
7
|
+
{ "code": "a", "value": "lcnuc" }
|
|
8
|
+
]}
|
|
9
|
+
],
|
|
10
|
+
|
|
11
|
+
"_validationOptions": {}
|
|
12
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"leader": "01331cam a22003494i 4500",
|
|
3
|
+
"fields": [
|
|
4
|
+
{ "tag": "042", "ind1": " ", "ind2": " ", "subfields": [
|
|
5
|
+
{ "code": "a", "value": "lc" }
|
|
6
|
+
]},
|
|
7
|
+
{ "tag": "042", "ind1": " ", "ind2": " ", "subfields": [
|
|
8
|
+
{ "code": "a", "value": "nsdp" },
|
|
9
|
+
{ "code": "a", "value": "lcnuc" }
|
|
10
|
+
]}
|
|
11
|
+
],
|
|
12
|
+
"_validationOptions": {}
|
|
13
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_validationOptions": {},
|
|
3
|
+
"fields": [
|
|
4
|
+
{ "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
|
|
5
|
+
{ "code": "a", "value": "Wuolijoki, Hella." },
|
|
6
|
+
{ "code": "t", "value": "Heta Niskavuori." },
|
|
7
|
+
{ "code": "k", "value": "Valikoima." },
|
|
8
|
+
{ "code": "0", "value": "(FIN11)000063570"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
{ "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
|
|
13
|
+
{ "code": "a", "value": "Wuolijoki, Hella." },
|
|
14
|
+
{ "code": "t", "value": "Heta Niskavuori." },
|
|
15
|
+
{ "code": "k", "value": "Valikoima." },
|
|
16
|
+
{ "code": "l", "value": "Ruotsi." },
|
|
17
|
+
{ "code": "0", "value": "(FIN11)000063570"
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
{ "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
|
|
22
|
+
{ "code": "a", "value": "Nuolijoki, Nella." },
|
|
23
|
+
{ "code": "t", "value": "Beta Tiskivuori." },
|
|
24
|
+
{ "code": "l", "value": "Suomi." },
|
|
25
|
+
{ "code": "0", "value": "(FIN11)900063570"
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
{ "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
|
|
30
|
+
{ "code": "a", "value": "Nuolijoki, Nella." },
|
|
31
|
+
{ "code": "t", "value": "Beta Tiskivuori." },
|
|
32
|
+
{ "code": "k", "value": "Valikoima." },
|
|
33
|
+
{ "code": "l", "value": "Ruotsi." },
|
|
34
|
+
{ "code": "0", "value": "(FIN11)900063570"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
],
|
|
40
|
+
"leader": "01331cam a22003498i 4500"
|
|
41
|
+
|
|
42
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_validationOptions": {},
|
|
3
|
+
"fields": [
|
|
4
|
+
{ "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
|
|
5
|
+
{ "code": "a", "value": "Wuolijoki, Hella." },
|
|
6
|
+
{ "code": "t", "value": "Heta Niskavuori." },
|
|
7
|
+
{ "code": "k", "value": "Valikoima." },
|
|
8
|
+
{ "code": "0", "value": "(FIN11)000063570"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
{ "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
|
|
13
|
+
{ "code": "a", "value": "Wuolijoki, Hella." },
|
|
14
|
+
{ "code": "t", "value": "Heta Niskavuori." },
|
|
15
|
+
{ "code": "k", "value": "Valikoima." },
|
|
16
|
+
{ "code": "l", "value": "Ruotsi." },
|
|
17
|
+
{ "code": "0", "value": "(FIN11)000063570"
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
{ "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
|
|
22
|
+
{ "code": "a", "value": "Nuolijoki, Nella." },
|
|
23
|
+
{ "code": "t", "value": "Beta Tiskivuori." },
|
|
24
|
+
{ "code": "l", "value": "Suomi." },
|
|
25
|
+
{ "code": "0", "value": "(FIN11)900063570"
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
{ "tag": "700", "ind1": "1", "ind2": " ", "subfields": [
|
|
30
|
+
{ "code": "a", "value": "Nuolijoki, Nella." },
|
|
31
|
+
{ "code": "t", "value": "Beta Tiskivuori." },
|
|
32
|
+
{ "code": "k", "value": "Valikoima." },
|
|
33
|
+
{ "code": "l", "value": "Ruotsi." },
|
|
34
|
+
{ "code": "0", "value": "(FIN11)900063570"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
],
|
|
39
|
+
"leader": "01331cam a22003498i 4500"
|
|
40
|
+
|
|
41
|
+
}
|