@natlibfi/marc-record-validators-melinda 10.2.1 → 10.2.2
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/multiple-subfield-0.js +46 -31
- package/dist/multiple-subfield-0.js.map +1 -1
- package/package.json +1 -1
- package/src/multiple-subfield-0.js +51 -33
- package/test-fixtures/subfield0/f01/metadata.json +1 -1
- package/test-fixtures/subfield0/f02/expectedResult.json +11 -2
- package/test-fixtures/subfield0/f02/metadata.json +1 -1
- package/test-fixtures/subfield0/f02/record.json +12 -1
- package/test-fixtures/subfield0/f03/expectedResult.json +3 -3
- package/test-fixtures/subfield0/f03/metadata.json +2 -1
- package/test-fixtures/subfield0/f03/record.json +5 -3
- package/test-fixtures/subfield0/v01/metadata.json +1 -1
- package/test-fixtures/subfield0/v02/expectedResult.json +4 -3
- package/test-fixtures/subfield0/v02/metadata.json +1 -1
- package/test-fixtures/subfield0/v02/record.json +9 -1
|
@@ -9,7 +9,7 @@ var _utils = require("./utils");
|
|
|
9
9
|
// import clone from 'clone';
|
|
10
10
|
// const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:multiple-subfield-0');
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const asteriNamePrefixes = ['(FI-ASTERI-N)', '(FIN11)', 'http://urn.fi/URN:NBN:fi:au:finaf:', 'https://urn.fi/URN:NBN:fi:au:finaf:'];
|
|
13
13
|
function _default() {
|
|
14
14
|
return {
|
|
15
15
|
description: 'If Asteri subfield $0 is found, remove non-Asteri $0 subfields',
|
|
@@ -17,8 +17,8 @@ function _default() {
|
|
|
17
17
|
fix
|
|
18
18
|
};
|
|
19
19
|
function fix(record) {
|
|
20
|
-
function
|
|
21
|
-
const removableSubfields =
|
|
20
|
+
function fixField(field) {
|
|
21
|
+
const removableSubfields = fieldGetDeletableSubfields(field);
|
|
22
22
|
removableSubfields.forEach(sf => record.removeSubfield(sf, field));
|
|
23
23
|
}
|
|
24
24
|
const res = {
|
|
@@ -27,14 +27,21 @@ function _default() {
|
|
|
27
27
|
valid: true
|
|
28
28
|
};
|
|
29
29
|
const relevantFields = getRelevantFields(record);
|
|
30
|
-
relevantFields.forEach(field =>
|
|
30
|
+
relevantFields.forEach(field => fixField(field));
|
|
31
31
|
|
|
32
32
|
// message.valid = !(message.message.length >= 1); // eslint-disable-line functional/immutable-data
|
|
33
33
|
return res;
|
|
34
34
|
}
|
|
35
35
|
function validate(record) {
|
|
36
|
+
function validateField(field) {
|
|
37
|
+
const relevantSubfields = fieldGetDeletableSubfields(field);
|
|
38
|
+
if (relevantSubfields.length === 0) {
|
|
39
|
+
return 'TROUBLE';
|
|
40
|
+
}
|
|
41
|
+
return `Field '${(0, _utils.fieldToString)(field)}' contains deletable $0 subfield(s): ${relevantSubfields.map(sf => sf.value).join(', ')}`;
|
|
42
|
+
}
|
|
36
43
|
const relevantFields = getRelevantFields(record);
|
|
37
|
-
const messages = relevantFields.map(field =>
|
|
44
|
+
const messages = relevantFields.map(field => validateField(field));
|
|
38
45
|
const res = {
|
|
39
46
|
message: messages
|
|
40
47
|
};
|
|
@@ -44,34 +51,35 @@ function _default() {
|
|
|
44
51
|
function fieldGetSubfields(field, code) {
|
|
45
52
|
return field.subfields.filter(sf => sf.code === code);
|
|
46
53
|
}
|
|
47
|
-
function
|
|
54
|
+
function isDeletableNamePartID(value) {
|
|
55
|
+
// List here $0s that always refer to name part, and to never to title part
|
|
56
|
+
if (value.match(/(?:isni|orcid)/ui)) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
function isAsteriNameId(value) {
|
|
62
|
+
// This is true if have a valid Asteri entry (nine digits etc)
|
|
48
63
|
const nineDigitTail = value.slice(-9);
|
|
49
64
|
if (!/^[0-9]{9}$/u.test(nineDigitTail)) {
|
|
50
65
|
return false;
|
|
51
66
|
}
|
|
52
67
|
// Normalize prefix:
|
|
53
68
|
const currPrefix = value.slice(0, -9);
|
|
54
|
-
if (
|
|
69
|
+
if (asteriNamePrefixes.includes(currPrefix)) {
|
|
55
70
|
return true;
|
|
56
71
|
}
|
|
57
72
|
return false;
|
|
58
73
|
}
|
|
59
|
-
function
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
// Bit lazy here, but it's easy to edit, and this should be good enough for proof-of-concept at least
|
|
69
|
-
if (value.match(/(?:isni|orcid)/ui)) {
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
// Currently default to false, and delete only specified values
|
|
73
|
-
return false;
|
|
74
|
+
function neverDropThisID(value) {
|
|
75
|
+
if (isAsteriNameId(value)) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
const prefixes = ['(FIN', '(FI-'];
|
|
79
|
+
if (prefixes.some(prefix => value.startsWith(prefix))) {
|
|
80
|
+
return true;
|
|
74
81
|
}
|
|
82
|
+
return false;
|
|
75
83
|
}
|
|
76
84
|
function fieldHasTitlePart(field) {
|
|
77
85
|
if (['600', '610', '700', '710', '800', '810'].includes(field.tag)) {
|
|
@@ -81,22 +89,29 @@ function _default() {
|
|
|
81
89
|
}
|
|
82
90
|
return false;
|
|
83
91
|
}
|
|
84
|
-
function
|
|
92
|
+
function fieldGetDeletableSubfields(field) {
|
|
85
93
|
const subfield0s = fieldGetSubfields(field, '0');
|
|
86
94
|
if (subfield0s.length < 2) {
|
|
87
|
-
return
|
|
95
|
+
return []; // We have nothing to delete
|
|
88
96
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
97
|
+
|
|
98
|
+
// Field must contain non-Asteri subfields and Asteri subfiels.
|
|
99
|
+
const nonAsteriNameSubfields = subfield0s.filter(sf => !isAsteriNameId(sf.value));
|
|
100
|
+
if (nonAsteriNameSubfields.length === 0 || nonAsteriNameSubfields.length === subfield0s.length) {
|
|
101
|
+
return [];
|
|
92
102
|
}
|
|
103
|
+
const suspiciousSubfields = nonAsteriNameSubfields.filter(sf => !neverDropThisID(sf.value));
|
|
93
104
|
|
|
94
|
-
//
|
|
105
|
+
// Field has deletable name part $0s:
|
|
106
|
+
const otherKnownNamePartIdentifiers = suspiciousSubfields.filter(sf => isDeletableNamePartID(sf.value));
|
|
95
107
|
if (fieldHasTitlePart(field)) {
|
|
96
|
-
return
|
|
108
|
+
return otherKnownNamePartIdentifiers;
|
|
97
109
|
}
|
|
98
|
-
|
|
99
|
-
|
|
110
|
+
return suspiciousSubfields;
|
|
111
|
+
}
|
|
112
|
+
function fieldIsRelevant(field) {
|
|
113
|
+
const subfields = fieldGetDeletableSubfields(field);
|
|
114
|
+
return subfields.length > 0;
|
|
100
115
|
}
|
|
101
116
|
function getRelevantFields(record) {
|
|
102
117
|
return record.fields.filter(field => field.subfields && fieldIsRelevant(field));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multiple-subfield-0.js","names":["
|
|
1
|
+
{"version":3,"file":"multiple-subfield-0.js","names":["asteriNamePrefixes","description","validate","fix","record","fixField","field","removableSubfields","fieldGetDeletableSubfields","forEach","sf","removeSubfield","res","message","valid","relevantFields","getRelevantFields","validateField","relevantSubfields","length","fieldToString","map","value","join","messages","fieldGetSubfields","code","subfields","filter","isDeletableNamePartID","match","isAsteriNameId","nineDigitTail","slice","test","currPrefix","includes","neverDropThisID","prefixes","some","prefix","startsWith","fieldHasTitlePart","tag","fieldHasSubfield","subfield0s","nonAsteriNameSubfields","suspiciousSubfields","otherKnownNamePartIdentifiers","fieldIsRelevant","fields"],"sources":["../src/multiple-subfield-0.js"],"sourcesContent":["// import createDebugLogger from 'debug';\n// import clone from 'clone';\n// const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:multiple-subfield-0');\n\nimport {fieldHasSubfield, fieldToString} from './utils';\n\nconst asteriNamePrefixes = ['(FI-ASTERI-N)', '(FIN11)', 'http://urn.fi/URN:NBN:fi:au:finaf:', 'https://urn.fi/URN:NBN:fi:au:finaf:'];\n\nexport default function () {\n\n return {\n description: 'If Asteri subfield $0 is found, remove non-Asteri $0 subfields',\n validate, fix\n };\n\n function fix(record) {\n function fixField(field) {\n const removableSubfields = fieldGetDeletableSubfields(field);\n removableSubfields.forEach(sf => record.removeSubfield(sf, field));\n }\n\n const res = {message: [], fix: [], valid: true};\n\n const relevantFields = getRelevantFields(record);\n\n relevantFields.forEach(field => fixField(field));\n\n // message.valid = !(message.message.length >= 1); // eslint-disable-line functional/immutable-data\n return res;\n }\n\n function validate(record) {\n function validateField(field) {\n const relevantSubfields = fieldGetDeletableSubfields(field);\n if (relevantSubfields.length === 0) {\n return 'TROUBLE';\n }\n return `Field '${fieldToString(field)}' contains deletable $0 subfield(s): ${relevantSubfields.map(sf => sf.value).join(', ')}`;\n }\n const relevantFields = getRelevantFields(record);\n const messages = relevantFields.map(field => validateField(field));\n const res = {message: messages};\n res.valid = !(res.message.length >= 1); // eslint-disable-line functional/immutable-data\n return res;\n }\n\n function fieldGetSubfields(field, code) {\n return field.subfields.filter(sf => sf.code === code);\n }\n\n function isDeletableNamePartID(value) {\n // List here $0s that always refer to name part, and to never to title part\n if (value.match(/(?:isni|orcid)/ui)) {\n return true;\n }\n return false;\n }\n\n function isAsteriNameId(value) { // This is true if have a valid Asteri entry (nine digits etc)\n const nineDigitTail = value.slice(-9);\n if (!(/^[0-9]{9}$/u).test(nineDigitTail)) {\n return false;\n }\n // Normalize prefix:\n const currPrefix = value.slice(0, -9);\n\n if (asteriNamePrefixes.includes(currPrefix)) {\n return true;\n }\n return false;\n }\n\n function neverDropThisID(value) {\n if (isAsteriNameId(value)) {\n return true;\n }\n\n const prefixes = ['(FIN', '(FI-'];\n if (prefixes.some(prefix => value.startsWith(prefix))) {\n return true;\n }\n\n return false;\n }\n\n\n function fieldHasTitlePart(field) {\n if (['600', '610', '700', '710', '800', '810'].includes(field.tag)) {\n if (fieldHasSubfield(field, 't')) {\n return true;\n }\n }\n return false;\n }\n\n function fieldGetDeletableSubfields(field) {\n const subfield0s = fieldGetSubfields(field, '0');\n\n if (subfield0s.length < 2) {\n return []; // We have nothing to delete\n }\n\n // Field must contain non-Asteri subfields and Asteri subfiels.\n const nonAsteriNameSubfields = subfield0s.filter(sf => !isAsteriNameId(sf.value));\n if (nonAsteriNameSubfields.length === 0 || nonAsteriNameSubfields.length === subfield0s.length) {\n return [];\n }\n\n const suspiciousSubfields = nonAsteriNameSubfields.filter(sf => !neverDropThisID(sf.value));\n\n // Field has deletable name part $0s:\n const otherKnownNamePartIdentifiers = suspiciousSubfields.filter(sf => isDeletableNamePartID(sf.value));\n\n if (fieldHasTitlePart(field)) {\n return otherKnownNamePartIdentifiers;\n }\n\n return suspiciousSubfields;\n }\n\n function fieldIsRelevant(field) {\n const subfields = fieldGetDeletableSubfields(field);\n return subfields.length > 0;\n }\n\n function getRelevantFields(record) {\n return record.fields.filter(field => field.subfields && fieldIsRelevant(field));\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import {fieldHasSubfield, fieldToString} from './utils';
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const asteriNamePrefixes = ['(FI-ASTERI-N)', '(FIN11)', 'http://urn.fi/URN:NBN:fi:au:finaf:', 'https://urn.fi/URN:NBN:fi:au:finaf:'];
|
|
8
8
|
|
|
9
9
|
export default function () {
|
|
10
10
|
|
|
@@ -14,8 +14,8 @@ export default function () {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
function fix(record) {
|
|
17
|
-
function
|
|
18
|
-
const removableSubfields =
|
|
17
|
+
function fixField(field) {
|
|
18
|
+
const removableSubfields = fieldGetDeletableSubfields(field);
|
|
19
19
|
removableSubfields.forEach(sf => record.removeSubfield(sf, field));
|
|
20
20
|
}
|
|
21
21
|
|
|
@@ -23,15 +23,22 @@ export default function () {
|
|
|
23
23
|
|
|
24
24
|
const relevantFields = getRelevantFields(record);
|
|
25
25
|
|
|
26
|
-
relevantFields.forEach(field =>
|
|
26
|
+
relevantFields.forEach(field => fixField(field));
|
|
27
27
|
|
|
28
28
|
// message.valid = !(message.message.length >= 1); // eslint-disable-line functional/immutable-data
|
|
29
29
|
return res;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
function validate(record) {
|
|
33
|
+
function validateField(field) {
|
|
34
|
+
const relevantSubfields = fieldGetDeletableSubfields(field);
|
|
35
|
+
if (relevantSubfields.length === 0) {
|
|
36
|
+
return 'TROUBLE';
|
|
37
|
+
}
|
|
38
|
+
return `Field '${fieldToString(field)}' contains deletable $0 subfield(s): ${relevantSubfields.map(sf => sf.value).join(', ')}`;
|
|
39
|
+
}
|
|
33
40
|
const relevantFields = getRelevantFields(record);
|
|
34
|
-
const messages = relevantFields.map(field =>
|
|
41
|
+
const messages = relevantFields.map(field => validateField(field));
|
|
35
42
|
const res = {message: messages};
|
|
36
43
|
res.valid = !(res.message.length >= 1); // eslint-disable-line functional/immutable-data
|
|
37
44
|
return res;
|
|
@@ -41,7 +48,15 @@ export default function () {
|
|
|
41
48
|
return field.subfields.filter(sf => sf.code === code);
|
|
42
49
|
}
|
|
43
50
|
|
|
44
|
-
function
|
|
51
|
+
function isDeletableNamePartID(value) {
|
|
52
|
+
// List here $0s that always refer to name part, and to never to title part
|
|
53
|
+
if (value.match(/(?:isni|orcid)/ui)) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function isAsteriNameId(value) { // This is true if have a valid Asteri entry (nine digits etc)
|
|
45
60
|
const nineDigitTail = value.slice(-9);
|
|
46
61
|
if (!(/^[0-9]{9}$/u).test(nineDigitTail)) {
|
|
47
62
|
return false;
|
|
@@ -49,33 +64,26 @@ export default function () {
|
|
|
49
64
|
// Normalize prefix:
|
|
50
65
|
const currPrefix = value.slice(0, -9);
|
|
51
66
|
|
|
52
|
-
if (
|
|
67
|
+
if (asteriNamePrefixes.includes(currPrefix)) {
|
|
53
68
|
return true;
|
|
54
69
|
}
|
|
55
70
|
return false;
|
|
56
71
|
}
|
|
57
72
|
|
|
58
|
-
function
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
function getDeletableSubfields(subfields) {
|
|
64
|
-
return subfields.filter(sf => sf.code === '0' && isDeletableId(sf.value));
|
|
73
|
+
function neverDropThisID(value) {
|
|
74
|
+
if (isAsteriNameId(value)) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
65
77
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
// Bit lazy here, but it's easy to edit, and this should be good enough for proof-of-concept at least
|
|
71
|
-
if (value.match(/(?:isni|orcid)/ui)) {
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
// Currently default to false, and delete only specified values
|
|
75
|
-
return false;
|
|
78
|
+
const prefixes = ['(FIN', '(FI-'];
|
|
79
|
+
if (prefixes.some(prefix => value.startsWith(prefix))) {
|
|
80
|
+
return true;
|
|
76
81
|
}
|
|
82
|
+
|
|
83
|
+
return false;
|
|
77
84
|
}
|
|
78
85
|
|
|
86
|
+
|
|
79
87
|
function fieldHasTitlePart(field) {
|
|
80
88
|
if (['600', '610', '700', '710', '800', '810'].includes(field.tag)) {
|
|
81
89
|
if (fieldHasSubfield(field, 't')) {
|
|
@@ -85,24 +93,34 @@ export default function () {
|
|
|
85
93
|
return false;
|
|
86
94
|
}
|
|
87
95
|
|
|
88
|
-
function
|
|
96
|
+
function fieldGetDeletableSubfields(field) {
|
|
89
97
|
const subfield0s = fieldGetSubfields(field, '0');
|
|
98
|
+
|
|
90
99
|
if (subfield0s.length < 2) {
|
|
91
|
-
return
|
|
100
|
+
return []; // We have nothing to delete
|
|
92
101
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
102
|
+
|
|
103
|
+
// Field must contain non-Asteri subfields and Asteri subfiels.
|
|
104
|
+
const nonAsteriNameSubfields = subfield0s.filter(sf => !isAsteriNameId(sf.value));
|
|
105
|
+
if (nonAsteriNameSubfields.length === 0 || nonAsteriNameSubfields.length === subfield0s.length) {
|
|
106
|
+
return [];
|
|
96
107
|
}
|
|
97
108
|
|
|
98
|
-
|
|
109
|
+
const suspiciousSubfields = nonAsteriNameSubfields.filter(sf => !neverDropThisID(sf.value));
|
|
110
|
+
|
|
111
|
+
// Field has deletable name part $0s:
|
|
112
|
+
const otherKnownNamePartIdentifiers = suspiciousSubfields.filter(sf => isDeletableNamePartID(sf.value));
|
|
113
|
+
|
|
99
114
|
if (fieldHasTitlePart(field)) {
|
|
100
|
-
return
|
|
115
|
+
return otherKnownNamePartIdentifiers;
|
|
101
116
|
}
|
|
102
117
|
|
|
118
|
+
return suspiciousSubfields;
|
|
119
|
+
}
|
|
103
120
|
|
|
104
|
-
|
|
105
|
-
|
|
121
|
+
function fieldIsRelevant(field) {
|
|
122
|
+
const subfields = fieldGetDeletableSubfields(field);
|
|
123
|
+
return subfields.length > 0;
|
|
106
124
|
}
|
|
107
125
|
|
|
108
126
|
function getRelevantFields(record) {
|
|
@@ -16,8 +16,17 @@
|
|
|
16
16
|
]},
|
|
17
17
|
{ "tag": "700", "ind1": " ", "ind2": " ", "subfields": [
|
|
18
18
|
{ "code": "a", "value": "Nimi3" },
|
|
19
|
-
{ "code": "0", "value": "(FI-ASTERI-N)000654323" }
|
|
20
|
-
|
|
19
|
+
{ "code": "0", "value": "(FI-ASTERI-N)000654323" }
|
|
20
|
+
]},
|
|
21
|
+
{ "tag": "700", "ind1": " ", "ind2": " ", "subfields": [
|
|
22
|
+
{ "code": "a", "value": "Keep erronous FIN13, drop orcid" },
|
|
23
|
+
{ "code": "0", "value": "(FI-ASTERI-N)000654324" },
|
|
24
|
+
{ "code": "0", "value": "(FIN13)123" }
|
|
25
|
+
]},
|
|
26
|
+
{ "tag": "700", "ind1": " ", "ind2": " ", "subfields": [
|
|
27
|
+
{ "code": "a", "value": "No FIN11, do nothing" },
|
|
28
|
+
{ "code": "0", "value": "(FIN13)123" },
|
|
29
|
+
{ "code": "0", "value": "(orcid)0000-0002-1355-5633" }
|
|
21
30
|
]}
|
|
22
31
|
|
|
23
32
|
|
|
@@ -20,7 +20,18 @@
|
|
|
20
20
|
{ "code": "a", "value": "Nimi3" },
|
|
21
21
|
{ "code": "0", "value": "(FI-ASTERI-N)000654323" },
|
|
22
22
|
{ "code": "0", "value": "https://isni.org/isni/0000000110485853" },
|
|
23
|
-
{ "code": "0", "value": "(
|
|
23
|
+
{ "code": "0", "value": "(remove-since-no-$t)666" },
|
|
24
|
+
{ "code": "0", "value": "(orcid)0000-0002-1355-5633" }
|
|
25
|
+
]},
|
|
26
|
+
{ "tag": "700", "ind1": " ", "ind2": " ", "subfields": [
|
|
27
|
+
{ "code": "a", "value": "Keep erronous FIN13, drop orcid" },
|
|
28
|
+
{ "code": "0", "value": "(FI-ASTERI-N)000654324" },
|
|
29
|
+
{ "code": "0", "value": "(FIN13)123" },
|
|
30
|
+
{ "code": "0", "value": "(orcid)0000-0002-1355-5633" }
|
|
31
|
+
]},
|
|
32
|
+
{ "tag": "700", "ind1": " ", "ind2": " ", "subfields": [
|
|
33
|
+
{ "code": "a", "value": "No FIN11, do nothing" },
|
|
34
|
+
{ "code": "0", "value": "(FIN13)123" },
|
|
24
35
|
{ "code": "0", "value": "(orcid)0000-0002-1355-5633" }
|
|
25
36
|
]}
|
|
26
37
|
|
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
|
|
9
9
|
{ "tag": "700", "ind1": " ", "ind2": " ", "subfields": [
|
|
10
10
|
{ "code": "a", "value": "Nimi1" },
|
|
11
|
-
{ "code": "0", "value": "(FI-ASTERI-N)
|
|
11
|
+
{ "code": "0", "value": "(FI-ASTERI-N)000654322" }
|
|
12
12
|
]},
|
|
13
13
|
{ "tag": "700", "ind1": " ", "ind2": " ", "subfields": [
|
|
14
14
|
{ "code": "a", "value": "Nimi1" },
|
|
15
|
-
{ "code": "t", "value": "Removal-preventing title" },
|
|
15
|
+
{ "code": "t", "value": "Removal-preventing title, however known authority name IDs are still removed" },
|
|
16
16
|
{ "code": "0", "value": "(FI-ASTERI-N)000654321" },
|
|
17
|
-
{ "code": "0", "value": "(
|
|
17
|
+
{ "code": "0", "value": "(random)000654321" }
|
|
18
18
|
]}
|
|
19
19
|
],
|
|
20
20
|
"leader": ""
|
|
@@ -8,13 +8,15 @@
|
|
|
8
8
|
|
|
9
9
|
{ "tag": "700", "ind1": " ", "ind2": " ", "subfields": [
|
|
10
10
|
{ "code": "a", "value": "Nimi1" },
|
|
11
|
-
{ "code": "0", "value": "(FI-ASTERI-N)
|
|
12
|
-
{ "code": "0", "value": "(orcid)0000-0002-1355-5633" }
|
|
11
|
+
{ "code": "0", "value": "(FI-ASTERI-N)000654322" },
|
|
12
|
+
{ "code": "0", "value": "(orcid)0000-0002-1355-5633" },
|
|
13
|
+
{ "code": "0", "value": "(random)000654321" }
|
|
13
14
|
]},
|
|
14
15
|
{ "tag": "700", "ind1": " ", "ind2": " ", "subfields": [
|
|
15
16
|
{ "code": "a", "value": "Nimi1" },
|
|
16
|
-
{ "code": "t", "value": "Removal-preventing title" },
|
|
17
|
+
{ "code": "t", "value": "Removal-preventing title, however known authority name IDs are still removed" },
|
|
17
18
|
{ "code": "0", "value": "(FI-ASTERI-N)000654321" },
|
|
19
|
+
{ "code": "0", "value": "(random)000654321" },
|
|
18
20
|
{ "code": "0", "value": "(orcid)0000-0002-1355-5633" }
|
|
19
21
|
]}
|
|
20
22
|
],
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"message": [
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"Field '700 ‡a Nimi1 ‡0 (FI-ASTERI-N)000654321 ‡0 (orcid)0000-0002-1355-5633' contains deletable $0 subfield(s): (orcid)0000-0002-1355-5633",
|
|
4
|
+
"Field '700 ‡a Nimi2 ‡0 https://isni.org/isni/0000000110485855 ‡0 (FI-ASTERI-N)000654322' contains deletable $0 subfield(s): https://isni.org/isni/0000000110485855",
|
|
5
|
+
"Field '700 ‡a Nimi3 ‡0 (FI-ASTERI-N)000654323 ‡0 https://isni.org/isni/0000000110485853 ‡0 (keep-only-if-title-part-present)666 ‡0 (orcid)0000-0002-1355-5633' contains deletable $0 subfield(s): https://isni.org/isni/0000000110485853, (keep-only-if-title-part-present)666, (orcid)0000-0002-1355-5633",
|
|
6
|
+
"Field '700 ‡a Nimi3 ‡0 (FI-ASTERI-N)000654323 ‡t Titlepart prevents unknown $0 identifiers from being removed ‡0 https://isni.org/isni/0000000110485853 ‡0 (keep-only-if-title-part-present)666 ‡0 (orcid)0000-0002-1355-5633' contains deletable $0 subfield(s): https://isni.org/isni/0000000110485853, (orcid)0000-0002-1355-5633"
|
|
6
7
|
],
|
|
7
8
|
"valid": false
|
|
8
9
|
}
|
|
@@ -20,7 +20,15 @@
|
|
|
20
20
|
{ "code": "a", "value": "Nimi3" },
|
|
21
21
|
{ "code": "0", "value": "(FI-ASTERI-N)000654323" },
|
|
22
22
|
{ "code": "0", "value": "https://isni.org/isni/0000000110485853" },
|
|
23
|
-
{ "code": "0", "value": "(keep-
|
|
23
|
+
{ "code": "0", "value": "(keep-only-if-title-part-present)666" },
|
|
24
|
+
{ "code": "0", "value": "(orcid)0000-0002-1355-5633" }
|
|
25
|
+
]},
|
|
26
|
+
{ "tag": "700", "ind1": " ", "ind2": " ", "subfields": [
|
|
27
|
+
{ "code": "a", "value": "Nimi3" },
|
|
28
|
+
{ "code": "0", "value": "(FI-ASTERI-N)000654323" },
|
|
29
|
+
{ "code": "t", "value": "Titlepart prevents unknown $0 identifiers from being removed"},
|
|
30
|
+
{ "code": "0", "value": "https://isni.org/isni/0000000110485853" },
|
|
31
|
+
{ "code": "0", "value": "(keep-only-if-title-part-present)666" },
|
|
24
32
|
{ "code": "0", "value": "(orcid)0000-0002-1355-5633" }
|
|
25
33
|
]}
|
|
26
34
|
|