@natlibfi/marc-record-validators-melinda 11.3.8 → 11.4.0
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 +67 -34
- package/dist/cyrillux.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/translate-terms.js +291 -0
- package/dist/translate-terms.js.map +1 -0
- package/dist/translate-terms.spec.js +51 -0
- package/dist/translate-terms.spec.js.map +1 -0
- package/package.json +1 -1
- package/src/cyrillux.js +56 -32
- package/src/index.js +3 -1
- package/src/translate-terms.js +274 -0
- package/src/translate-terms.spec.js +52 -0
- package/test-fixtures/cyrillux/f01/metadata.json +1 -1
- package/test-fixtures/cyrillux/f03/metadata.json +4 -3
- package/test-fixtures/cyrillux/f03b/expectedResult.json +21 -0
- package/test-fixtures/cyrillux/f03b/metadata.json +11 -0
- package/test-fixtures/cyrillux/f03b/record.json +19 -0
- package/test-fixtures/cyrillux/f04/metadata.json +4 -3
- package/test-fixtures/cyrillux/f08/metadata.json +1 -1
- package/test-fixtures/cyrillux/f09/metadata.json +1 -1
- package/test-fixtures/cyrillux/f11/expectedResult.json +18 -0
- package/test-fixtures/cyrillux/f11/metadata.json +9 -0
- package/test-fixtures/cyrillux/f11/record.json +9 -0
- package/test-fixtures/cyrillux/f11b/expectedResult.json +18 -0
- package/test-fixtures/cyrillux/f11b/metadata.json +9 -0
- package/test-fixtures/cyrillux/f11b/record.json +16 -0
- package/test-fixtures/translate-terms/01/expectedResult.json +37 -0
- package/test-fixtures/translate-terms/01/metadata.json +6 -0
- package/test-fixtures/translate-terms/01/record.json +27 -0
- package/test-fixtures/translate-terms/02/expectedResult.json +37 -0
- package/test-fixtures/translate-terms/02/metadata.json +6 -0
- package/test-fixtures/translate-terms/02/record.json +27 -0
- package/test-fixtures/translate-terms/03/expectedResult.json +26 -0
- package/test-fixtures/translate-terms/03/metadata.json +5 -0
- package/test-fixtures/translate-terms/03/record.json +26 -0
- package/test-fixtures/translate-terms/04/expectedResult.json +16 -0
- package/test-fixtures/translate-terms/04/metadata.json +7 -0
- package/test-fixtures/translate-terms/04/record.json +17 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import clone from 'clone';
|
|
2
|
+
import createDebugLogger from 'debug';
|
|
3
|
+
import {fieldHasSubfield, fieldToString, nvdebug} from './utils';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:sortSubfields');
|
|
7
|
+
const defaultTags = ['648', '650', '651', '655'];
|
|
8
|
+
|
|
9
|
+
const swapLanguageCode = {'fin': 'swe', 'fi': 'sv', 'sv': 'fi', 'swe': 'fin'};
|
|
10
|
+
const changeAbbrHash = {'fi': 'fin', 'fin': 'fi', 'sv': 'swe', 'swe': 'sv'};
|
|
11
|
+
|
|
12
|
+
//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/translate-term');
|
|
13
|
+
const termCache = {};
|
|
14
|
+
|
|
15
|
+
// Author(s): Nicholas Volk
|
|
16
|
+
export default function () {
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
description: 'Translate yso (648, 650, 651) and slm (655) terms (FIN <=> SWE)',
|
|
21
|
+
validate, fix
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
async function fix(record) {
|
|
25
|
+
const newFields = await getFields(record, defaultTags, []);
|
|
26
|
+
|
|
27
|
+
newFields.forEach(nf => nvdebug(`Add new field '${fieldToString(nf)}'`, debug));
|
|
28
|
+
|
|
29
|
+
newFields.forEach(nf => record.insertField(nf));
|
|
30
|
+
|
|
31
|
+
const newFieldsAsStrings = newFields.map(f => fieldToString(f));
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
return {message: [], fix: newFieldsAsStrings, valid: true};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function validate(record) {
|
|
38
|
+
const newFields = await getFields(record, defaultTags, []);
|
|
39
|
+
if (newFields.length === 0) {
|
|
40
|
+
return {'message': [], 'valid': true};
|
|
41
|
+
}
|
|
42
|
+
const messages = newFields.map(f => fieldToString(f));
|
|
43
|
+
|
|
44
|
+
return {'message': messages, 'valid': false};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function getFields(record, tags, fieldsToAdd) {
|
|
48
|
+
const [currTag, ...remainingTags] = tags;
|
|
49
|
+
if (!currTag) {
|
|
50
|
+
return fieldsToAdd;
|
|
51
|
+
}
|
|
52
|
+
const missingFields = await deriveMissingFields(record, currTag);
|
|
53
|
+
|
|
54
|
+
const tmp = await getFields(record, remainingTags, [...fieldsToAdd, ...missingFields]);
|
|
55
|
+
return tmp;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function getPairlessFinnishAndSwedishFields(record, tag) {
|
|
59
|
+
const expectedLex = mapTagToLex(tag);
|
|
60
|
+
if (!expectedLex) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
const fields = record.get(tag);
|
|
64
|
+
const finnishFields = fields.filter(f => isRelevantField(f, 'fin'));
|
|
65
|
+
const swedishFields = fields.filter(f => isRelevantField(f, 'swe'));
|
|
66
|
+
const finnishOnly = getMisses(finnishFields, swedishFields);
|
|
67
|
+
const swedishOnly = getMisses(swedishFields, finnishFields);
|
|
68
|
+
|
|
69
|
+
//console.log(` Looking at ${finnishOnly.length} + ${swedishOnly.length} fields`); // eslint-disable-line no-console
|
|
70
|
+
return [...finnishOnly, ...swedishOnly].filter(f => tagAndFieldAgree(f));
|
|
71
|
+
|
|
72
|
+
function tagAndFieldAgree(field) {
|
|
73
|
+
// Check that tag and $2 value are pairable:
|
|
74
|
+
const lexData = getLexiconAndLanguage(field); // $2 data
|
|
75
|
+
return expectedLex === lexData.lex;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function deriveMissingFields(record, tag) {
|
|
80
|
+
const pairlessFields = getPairlessFinnishAndSwedishFields(record, tag);
|
|
81
|
+
|
|
82
|
+
/* eslint-disable */
|
|
83
|
+
// Dunno how to handle loop+promise combo in our normal coding style. Spent half a day trying... (I reckon it takes like 2 minuts to do this properly...)
|
|
84
|
+
let prefLabels = [];
|
|
85
|
+
for (let i=0; i < pairlessFields.length; i += 1) {
|
|
86
|
+
prefLabels[i] = await getPrefLabel(pairlessFields[i]);
|
|
87
|
+
}
|
|
88
|
+
/* eslint-enable */
|
|
89
|
+
|
|
90
|
+
const missingFields = pairlessFields.map((f, i) => pairField(f, prefLabels[i]));
|
|
91
|
+
return missingFields.filter(f => f);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function pairField(field, prefLabels) {
|
|
95
|
+
if (!prefLabels) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
//console.log(`pairField() WP 1: ${fieldToString(field)}`); // eslint-disable-line no-console
|
|
99
|
+
const lexAndLang = getLexiconAndLanguage(field);
|
|
100
|
+
//console.log(`pairField() WP 2: ${JSON.stringify(lexAndLang)}`); // eslint-disable-line no-console
|
|
101
|
+
const twoLetterOtherLang = swapLanguageCodeBetweenLanguages(changeAbbr(lexAndLang.lang));
|
|
102
|
+
const prefLabel = prefLabels.find(l => l.lang === twoLetterOtherLang);
|
|
103
|
+
//console.log(`pairField() WP 4: ${JSON.stringify(prefLabel)}`); // eslint-disable-line no-console
|
|
104
|
+
const sfA = {'code': 'a', 'value': prefLabel.value}; // field.subfields.field(sf => sf.code === 'a');
|
|
105
|
+
const sf0 = clone(field.subfields.find(sf => sf.code === '0'));
|
|
106
|
+
const sf2 = {'code': '2', 'value': `${lexAndLang.lex}/${lexAndLang.lang === 'fin' ? 'swe' : 'fin'}`}; // swap fin <=> swe
|
|
107
|
+
const newField = {tag: field.tag, ind1: field.ind1, ind2: field.ind2, subfields: [sfA, sf2, sf0]};
|
|
108
|
+
return newField;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function getLexiconAndLanguage(field) {
|
|
112
|
+
const subfield2 = field.subfields.find(sf => sf.code === '2');
|
|
113
|
+
if (subfield2.value === 'slm/fin') {
|
|
114
|
+
return {'lex': 'slm', 'lang': 'fin'};
|
|
115
|
+
}
|
|
116
|
+
if (subfield2.value === 'slm/swe') {
|
|
117
|
+
return {'lex': 'slm', 'lang': 'swe'};
|
|
118
|
+
}
|
|
119
|
+
if (subfield2.value === 'yso/fin') {
|
|
120
|
+
return {'lex': 'yso', 'lang': 'fin'};
|
|
121
|
+
}
|
|
122
|
+
if (subfield2.value === 'yso/swe') {
|
|
123
|
+
return {'lex': 'yso', 'lang': 'swe'};
|
|
124
|
+
}
|
|
125
|
+
return {};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function getPrefLabel(field) {
|
|
129
|
+
// Tag vs $2 correlation has already been checked!
|
|
130
|
+
const uri = fieldToUri(field);
|
|
131
|
+
if (!uri) { // $0 is invalid or sumthing
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
const prefLabels = await getTermData(uri);
|
|
135
|
+
if (!prefLabels) { // Sanity check. Miss caused by illegal id etc.
|
|
136
|
+
nvdebug(`No labels found for ${uri}`, debug);
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
const lexData = getLexiconAndLanguage(field); // $2 data
|
|
140
|
+
const lang = changeAbbr(lexData.lang);
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
const subfieldA = field.subfields.find(sf => sf.code === 'a');
|
|
144
|
+
|
|
145
|
+
const prefLabel = prefLabels.find(pl => pl.lang === lang);
|
|
146
|
+
//console.info(`Compare prefLabel '${prefLabel.value}' AND $a '${subfieldA.value}'`); // eslint-disable-line no-console
|
|
147
|
+
if (prefLabel.value === subfieldA.value) {
|
|
148
|
+
nvdebug(`'${fieldToString(field)}' requires translating`, debug);
|
|
149
|
+
return prefLabels;
|
|
150
|
+
}
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function swapLanguageCodeBetweenLanguages(code) {
|
|
155
|
+
if (swapLanguageCode[code]) {
|
|
156
|
+
return swapLanguageCode[code];
|
|
157
|
+
}
|
|
158
|
+
return code;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function changeAbbr(abbr) {
|
|
162
|
+
if (changeAbbrHash[abbr]) {
|
|
163
|
+
return changeAbbrHash[abbr];
|
|
164
|
+
}
|
|
165
|
+
return abbr;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function swaggerQuery(uri) {
|
|
169
|
+
// This would work for only yso, not yso-paikat etc `https://api.finto.fi/rest/v1/yso/data?format=application%2Fjson&uri=${uri}`;
|
|
170
|
+
return `https://api.finto.fi/rest/v1/data?uri=${uri}&format=application%2Fjson`; // This is simpler, but contains more irrelevant data
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async function getTermData(uri) {
|
|
174
|
+
//console.log(`getTermData(${uri})`); // eslint-disable-line no-console
|
|
175
|
+
if (termCache[uri]) { // Don't think current implementation uses the cache any more.
|
|
176
|
+
//console.log(`CACHED ${uri}`); // eslint-disable-line no-console
|
|
177
|
+
return termCache[uri];
|
|
178
|
+
}
|
|
179
|
+
const tmp = await getTermDataFromFinto(uri);
|
|
180
|
+
termCache[uri] = tmp; // eslint-disable-line functional/immutable-data, require-atomic-updates
|
|
181
|
+
return tmp;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async function getTermDataFromFinto(uri) {
|
|
185
|
+
const headers = {'Accept': 'application/json'};
|
|
186
|
+
const uri2 = swaggerQuery(uri);
|
|
187
|
+
|
|
188
|
+
const response = await fetch(uri2, {method: 'GET', headers});
|
|
189
|
+
if (!response.ok) {
|
|
190
|
+
return undefined;
|
|
191
|
+
}
|
|
192
|
+
const json = await response.json();
|
|
193
|
+
|
|
194
|
+
if (!json.graph) {
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
const arr = json.graph;
|
|
198
|
+
const [hit] = arr.filter(row => row.uri === uri);
|
|
199
|
+
//console.log(`NEW JSON: ${JSON.stringify(hit.prefLabel)}`); // eslint-disable-line no-console
|
|
200
|
+
return hit.prefLabel;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
function fieldToUri(field) {
|
|
205
|
+
const lex = mapTagToLex(field.tag);
|
|
206
|
+
|
|
207
|
+
const subfield0 = field.subfields.find(sf => sf.code === '0');
|
|
208
|
+
const id = subfield0.value.replace(/^[^0-9]+/u, '');
|
|
209
|
+
if (lex === 'yso') {
|
|
210
|
+
//return `http%3A%2F%2Fwww.yso.fi%2Fonto%2Fyso%2Fp${id}`;
|
|
211
|
+
return `http://www.yso.fi/onto/yso/p${id}`;
|
|
212
|
+
}
|
|
213
|
+
if (lex === 'slm') {
|
|
214
|
+
return `http://urn.fi/URN:NBN:fi:au:slm:s${id}`;
|
|
215
|
+
}
|
|
216
|
+
return undefined;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function isRelevantField(field, lang) {
|
|
220
|
+
const fieldAsString = fieldToString(field);
|
|
221
|
+
|
|
222
|
+
// We should probably allow an optional $8 as the first subfield.
|
|
223
|
+
if (!fieldAsString.match(/^... #7 ‡a [^‡]+ ‡2 [^‡]+ ‡0 [^‡]+(?: ‡9 [A-Z]+<(?:KEEP|DROP)>)*$/u)) {
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
const lex = mapTagToLex(field.tag);
|
|
227
|
+
const lexLang = `${lex}/${lang}`;
|
|
228
|
+
if (!fieldHasSubfield(field, '2', lexLang)) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
return fieldHasValidSubfield0(field);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function fieldHasValidSubfield0(field) {
|
|
235
|
+
const lex = mapTagToLex(field.tag);
|
|
236
|
+
const subfield0 = field.subfields.find(sf => sf.code === '0');
|
|
237
|
+
if (lex === 'yso' && subfield0.value.match(/^http:\/\/www\.yso\.fi\/onto\/yso\/p[0-9]+$/u)) {
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
if (lex === 'slm' && subfield0.value.match(/^http:\/\/urn\.fi\/URN:NBN:fi:au:slm:s[0-9]+$/u)) {
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function getMisses(fieldList1, fieldList2) {
|
|
247
|
+
return fieldList1.filter(f => !hasSubfield0Match(f, fieldList2));
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function hasSubfield0Match(field, pairFields) {
|
|
251
|
+
const subfield0 = field.subfields.find(sf => sf.code === '0');
|
|
252
|
+
return pairFields.some(f => f.subfields.some(sf => sf.code === '0' && sf.value === subfield0.value));
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
function mapTagToLex(tag) {
|
|
257
|
+
if (tag === '655') {
|
|
258
|
+
return 'slm';
|
|
259
|
+
}
|
|
260
|
+
return 'yso';
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
/*
|
|
265
|
+
function getValidIdentifiers(record, tag, lang) {
|
|
266
|
+
const lex = mapTagToLex(tag);
|
|
267
|
+
const subfield2Value = `${lex}/${lang}`;
|
|
268
|
+
const candFields = record.get(tag).filter(f => f.subfields.some(sf => sf.code === '2' && sf.value === subfield2Value)); // TODO: filter
|
|
269
|
+
return [];
|
|
270
|
+
}
|
|
271
|
+
*/
|
|
272
|
+
|
|
273
|
+
}
|
|
274
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {MarcRecord} from '@natlibfi/marc-record';
|
|
3
|
+
import validatorFactory from './translate-terms';
|
|
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', 'translate-terms'],
|
|
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/translate-terms: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
|
+
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"description": "Fix: just convert field 100 to ISO-9 latinitsa",
|
|
2
|
+
"description": "03 Fix: just convert field 100 to ISO-9 latinitsa, don't retain the original nor do sfs4900",
|
|
3
3
|
"comment": "Tests usage of config and omitting of $6 and $9",
|
|
4
4
|
"only": false,
|
|
5
5
|
"fix": true,
|
|
6
6
|
"config": {
|
|
7
|
-
"doISO9Transliteration":
|
|
8
|
-
"doSFS4900Transliteration": false
|
|
7
|
+
"doISO9Transliteration": true,
|
|
8
|
+
"doSFS4900Transliteration": false,
|
|
9
|
+
"retainCyrillic": false
|
|
9
10
|
}
|
|
10
11
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_validationOptions": {},
|
|
3
|
+
"leader": "12345cam 22123454i 4500",
|
|
4
|
+
"fields": [
|
|
5
|
+
{ "tag": "100", "ind1": "1", "ind2": " ", "subfields": [
|
|
6
|
+
{ "code": "a", "value": "Modin, Ûrij Ivanovič." }
|
|
7
|
+
]},
|
|
8
|
+
{ "tag": "245", "ind1": "1", "ind2": " ", "subfields": [
|
|
9
|
+
{ "code": "a", "value": "Sudʹby razvedčikov." }
|
|
10
|
+
]},
|
|
11
|
+
{"tag": "500", "ind1": " ", "ind2": " ", "subfields": [
|
|
12
|
+
{ "code": "6", "value": "880-01"},
|
|
13
|
+
{ "code": "a", "value": "FOO."}
|
|
14
|
+
]},
|
|
15
|
+
{"tag": "880", "ind1": " ", "ind2": " ", "subfields": [
|
|
16
|
+
{ "code": "6", "value": "500-01"},
|
|
17
|
+
{ "code": "a", "value": "BAR."}
|
|
18
|
+
]}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "03b Fix: just convert field 100 to SFS4900 latinitsa, don't retain the original nor do ISO-9",
|
|
3
|
+
"comment": "Tests usage of config and omitting of $6 and $9",
|
|
4
|
+
"only": false,
|
|
5
|
+
"fix": true,
|
|
6
|
+
"config": {
|
|
7
|
+
"doISO9Transliteration": false,
|
|
8
|
+
"doSFS4900Transliteration": true,
|
|
9
|
+
"retainCyrillic": false
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"leader": "12345cam 22123454i 4500",
|
|
3
|
+
"fields": [
|
|
4
|
+
{ "tag": "100", "ind1": "1", "ind2": " ", "subfields": [
|
|
5
|
+
{ "code": "a", "value": "Модин, Юрий Иванович." }
|
|
6
|
+
]},
|
|
7
|
+
{"tag": "245", "ind1": "1", "ind2": " ", "subfields": [
|
|
8
|
+
{ "code": "a", "value": "Судьбы разведчиков."}
|
|
9
|
+
]},
|
|
10
|
+
{"tag": "500", "ind1": " ", "ind2": " ", "subfields": [
|
|
11
|
+
{ "code": "6", "value": "880-01"},
|
|
12
|
+
{ "code": "a", "value": "FOO."}
|
|
13
|
+
]},
|
|
14
|
+
{"tag": "880", "ind1": " ", "ind2": " ", "subfields": [
|
|
15
|
+
{ "code": "6", "value": "500-01"},
|
|
16
|
+
{ "code": "a", "value": "BAR."}
|
|
17
|
+
]}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"description": "Fix: just convert field 100 to ISO-9 latinitsa",
|
|
2
|
+
"description": "04 Fix: just convert field 100 to ISO-9 latinitsa",
|
|
3
3
|
"comment": "Tests usage of config and omitting of $6 and $9",
|
|
4
4
|
"only": false,
|
|
5
5
|
"fix": true,
|
|
6
6
|
"config": {
|
|
7
|
-
"doISO9Transliteration":
|
|
8
|
-
"doSFS4900Transliteration": false
|
|
7
|
+
"doISO9Transliteration": true,
|
|
8
|
+
"doSFS4900Transliteration": false,
|
|
9
|
+
"retainCyrillic": false
|
|
9
10
|
}
|
|
10
11
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"description": "Fix MELINDA-10330: fields 100 and 245 are already in SFS-4900 and their only 880 pairs are Cyrillic",
|
|
2
|
+
"description": "08 Fix MELINDA-10330: fields 100 and 245 are already in SFS-4900 and their only 880 pairs are Cyrillic",
|
|
3
3
|
"comment": "Use 880 to create 100/245 in ISO-9. Move original SFS-4900 to 880, add $9s",
|
|
4
4
|
"comment #2": "Note that the original punctuation in 100/245 is overwritten with punctuation from paired 880",
|
|
5
5
|
"only": false,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"description": "Fix MELINDA-10330, round 3: big file that had issues",
|
|
2
|
+
"description": "09 Fix MELINDA-10330, round 3: big file that had issues",
|
|
3
3
|
"comment": "Some sorting issues: SIDs are sorted by $c (bug) and LOW precedes SID...",
|
|
4
4
|
"only": false,
|
|
5
5
|
"fix": true,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_validationOptions": {},
|
|
3
|
+
"leader": "12345cam 22123454i 4500",
|
|
4
|
+
"fields": [
|
|
5
|
+
{ "tag": "008", "value": "01234567890123456789012345678901234ukr89"},
|
|
6
|
+
{ "tag": "100", "ind1": "1", "ind2": " ", "subfields": [
|
|
7
|
+
{ "code": "6", "value": "880-01" },
|
|
8
|
+
{ "code": "a", "value": "Gogolʹ." },
|
|
9
|
+
{ "code": "9", "value": "ISO9 <TRANS>" }
|
|
10
|
+
]},
|
|
11
|
+
{ "tag": "880", "ind1": "1", "ind2": " ", "subfields": [
|
|
12
|
+
{ "code": "6", "value": "100-01" },
|
|
13
|
+
{ "code": "a", "value": "Гоголь." },
|
|
14
|
+
{ "code": "9", "value": "CYRILLIC <TRANS>" }
|
|
15
|
+
]}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_validationOptions": {},
|
|
3
|
+
"leader": "12345cam 22123454i 4500",
|
|
4
|
+
"fields": [
|
|
5
|
+
{ "tag": "008", "value": "01234567890123456789012345678901234ukr89"},
|
|
6
|
+
{ "tag": "100", "ind1": "1", "ind2": " ", "subfields": [
|
|
7
|
+
{ "code": "6", "value": "880-01" },
|
|
8
|
+
{ "code": "a", "value": "Gogolʹ." },
|
|
9
|
+
{ "code": "9", "value": "ISO9 <TRANS>" }
|
|
10
|
+
]},
|
|
11
|
+
{ "tag": "880", "ind1": "1", "ind2": " ", "subfields": [
|
|
12
|
+
{ "code": "6", "value": "100-01" },
|
|
13
|
+
{ "code": "a", "value": "Гоголь." },
|
|
14
|
+
{ "code": "9", "value": "CYRILLIC <TRANS>" }
|
|
15
|
+
]}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"leader": "12345cam 22123454i 4500",
|
|
3
|
+
"fields": [
|
|
4
|
+
{ "tag": "008", "value": "01234567890123456789012345678901234ukr89"},
|
|
5
|
+
{ "tag": "100", "ind1": "1", "ind2": " ", "subfields": [
|
|
6
|
+
{ "code": "6", "value": "880-01" },
|
|
7
|
+
{ "code": "a", "value": "Gogolʹ." },
|
|
8
|
+
{ "code": "9", "value": "ISO9 <TRANS>" }
|
|
9
|
+
]},
|
|
10
|
+
{ "tag": "880", "ind1": "1", "ind2": " ", "subfields": [
|
|
11
|
+
{ "code": "6", "value": "100-01" },
|
|
12
|
+
{ "code": "a", "value": "Гоголь." },
|
|
13
|
+
{ "code": "9", "value": "CYRILLIC <TRANS>" }
|
|
14
|
+
]}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_validationOptions": {},
|
|
3
|
+
"fields": [
|
|
4
|
+
{ "tag": "650", "ind1": " ", "ind2": "7", "subfields": [
|
|
5
|
+
{ "code": "a", "value": "laiturit" },
|
|
6
|
+
{ "code": "2", "value": "yso/fin" },
|
|
7
|
+
{ "code": "0", "value": "http://www.yso.fi/onto/yso/p13299" }
|
|
8
|
+
]},
|
|
9
|
+
{ "tag": "650", "ind1": " ", "ind2": "7", "subfields": [
|
|
10
|
+
{ "code": "a", "value": "marxismi" },
|
|
11
|
+
{ "code": "2", "value": "yso/fin" },
|
|
12
|
+
{ "code": "0", "value": "http://www.yso.fi/onto/yso/p444" }
|
|
13
|
+
]},
|
|
14
|
+
{ "tag": "650", "ind1": " ", "ind2": "7", "subfields": [
|
|
15
|
+
{ "code": "a", "value": "marxism" },
|
|
16
|
+
{ "code": "2", "value": "yso/swe" },
|
|
17
|
+
{ "code": "0", "value": "http://www.yso.fi/onto/yso/p444" }
|
|
18
|
+
]},
|
|
19
|
+
{ "tag": "650", "ind1": " ", "ind2": "7", "subfields": [
|
|
20
|
+
{ "code": "a", "value": "bryggor" },
|
|
21
|
+
{ "code": "2", "value": "yso/swe" },
|
|
22
|
+
{ "code": "0", "value": "http://www.yso.fi/onto/yso/p13299" }
|
|
23
|
+
]},
|
|
24
|
+
{ "tag": "651", "ind1": " ", "ind2": "7", "subfields": [
|
|
25
|
+
{ "code": "a", "value": "Ivalo (Enare)" },
|
|
26
|
+
{ "code": "2", "value": "yso/swe" },
|
|
27
|
+
{ "code": "0", "value": "http://www.yso.fi/onto/yso/p111739" }
|
|
28
|
+
]},
|
|
29
|
+
{ "tag": "651", "ind1": " ", "ind2": "7", "subfields": [
|
|
30
|
+
{ "code": "a", "value": "Ivalo (Inari)" },
|
|
31
|
+
{ "code": "2", "value": "yso/fin" },
|
|
32
|
+
{ "code": "0", "value": "http://www.yso.fi/onto/yso/p111739" }
|
|
33
|
+
]}
|
|
34
|
+
|
|
35
|
+
],
|
|
36
|
+
"leader": ""
|
|
37
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_validationOptions": {},
|
|
3
|
+
"leader": "",
|
|
4
|
+
"fields": [
|
|
5
|
+
{ "tag": "650", "ind1": " ", "ind2": "7", "subfields": [
|
|
6
|
+
{ "code": "a", "value": "laiturit" },
|
|
7
|
+
{ "code": "2", "value": "yso/fin" },
|
|
8
|
+
{ "code": "0", "value": "http://www.yso.fi/onto/yso/p13299" }
|
|
9
|
+
]
|
|
10
|
+
},
|
|
11
|
+
{ "tag": "650", "ind1": " ", "ind2": "7", "subfields": [
|
|
12
|
+
{ "code": "a", "value": "marxismi" },
|
|
13
|
+
{ "code": "2", "value": "yso/fin" },
|
|
14
|
+
{ "code": "0", "value": "http://www.yso.fi/onto/yso/p444" }
|
|
15
|
+
]},
|
|
16
|
+
{ "tag": "650", "ind1": " ", "ind2": "7", "subfields": [
|
|
17
|
+
{ "code": "a", "value": "marxism" },
|
|
18
|
+
{ "code": "2", "value": "yso/swe" },
|
|
19
|
+
{ "code": "0", "value": "http://www.yso.fi/onto/yso/p444" }
|
|
20
|
+
]},
|
|
21
|
+
{ "tag": "651", "ind1": " ", "ind2": "7", "subfields": [
|
|
22
|
+
{ "code": "a", "value": "Ivalo (Enare)" },
|
|
23
|
+
{ "code": "2", "value": "yso/swe" },
|
|
24
|
+
{ "code": "0", "value": "http://www.yso.fi/onto/yso/p111739" }
|
|
25
|
+
]}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_validationOptions": {},
|
|
3
|
+
"fields": [
|
|
4
|
+
{ "tag": "648", "ind1": " ", "ind2": "7", "subfields": [
|
|
5
|
+
{ "code": "a", "value": "1960-luku" },
|
|
6
|
+
{ "code": "2", "value": "yso/fin" },
|
|
7
|
+
{ "code": "0", "value": "http://www.yso.fi/onto/yso/p6196061969" }
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
{ "tag": "648", "ind1": " ", "ind2": "7", "subfields": [
|
|
11
|
+
{ "code": "a", "value": "1960-talet" },
|
|
12
|
+
{ "code": "2", "value": "yso/swe" },
|
|
13
|
+
{ "code": "0", "value": "http://www.yso.fi/onto/yso/p6196061969" }
|
|
14
|
+
]},
|
|
15
|
+
{ "tag": "655", "ind1": " ", "ind2": "7", "subfields": [
|
|
16
|
+
{ "code": "a", "value": "damtidningar" },
|
|
17
|
+
{ "code": "2", "value": "slm/swe" },
|
|
18
|
+
{ "code": "0", "value": "http://urn.fi/URN:NBN:fi:au:slm:s161" }
|
|
19
|
+
]},
|
|
20
|
+
{ "tag": "655", "ind1": " ", "ind2": "7", "subfields": [
|
|
21
|
+
{ "code": "a", "value": "nekrologit" },
|
|
22
|
+
{ "code": "2", "value": "slm/fin" },
|
|
23
|
+
{ "code": "0", "value": "http://urn.fi/URN:NBN:fi:au:slm:s1324" }
|
|
24
|
+
]},
|
|
25
|
+
{ "tag": "655", "ind1": " ", "ind2": "7", "subfields": [
|
|
26
|
+
{ "code": "a", "value": "nekrologer" },
|
|
27
|
+
{ "code": "2", "value": "slm/swe" },
|
|
28
|
+
{ "code": "0", "value": "http://urn.fi/URN:NBN:fi:au:slm:s1324" }
|
|
29
|
+
]},
|
|
30
|
+
{ "tag": "655", "ind1": " ", "ind2": "7", "subfields": [
|
|
31
|
+
{ "code": "a", "value": "naistenlehdet" },
|
|
32
|
+
{ "code": "2", "value": "slm/fin" },
|
|
33
|
+
{ "code": "0", "value": "http://urn.fi/URN:NBN:fi:au:slm:s161" }
|
|
34
|
+
]}
|
|
35
|
+
],
|
|
36
|
+
"leader": ""
|
|
37
|
+
}
|