1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Scriptotek\SimpleMarcParser; |
4
|
|
|
|
5
|
|
|
use Carbon\Carbon; |
6
|
|
|
use Danmichaelo\QuiteSimpleXmlElement\QuiteSimpleXmlElement; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* @property int $id Local record identifier |
10
|
|
|
* @property string $material |
11
|
|
|
* @property boolean $electronic |
12
|
|
|
* @property boolean $is_series |
13
|
|
|
* @property boolean $is_multivolume |
14
|
|
|
* @property boolean |
15
|
|
|
* @property string $agency |
16
|
|
|
* @property string $lccn |
17
|
|
|
* @property string $catalogingRules |
18
|
|
|
* @property string $title |
19
|
|
|
* @property string $alternativeTitles |
20
|
|
|
* @property string $part_no |
21
|
|
|
* @property string $part_name |
22
|
|
|
* @property string $part_of |
23
|
|
|
* @property string $medium |
24
|
|
|
* @property string $edition |
25
|
|
|
* @property string $placeOfPublication |
26
|
|
|
* @property string $publisher |
27
|
|
|
* @property string $extent |
28
|
|
|
* @property string $contents |
29
|
|
|
* @property string $summary |
30
|
|
|
* @property string $cover_image |
31
|
|
|
* @property string $description |
32
|
|
|
* @property string $preceding |
33
|
|
|
* @property string $succeeding |
34
|
|
|
* @property string[] $isbns |
35
|
|
|
* @property string[] $issns |
36
|
|
|
* @property string[] $notes |
37
|
|
|
* @property array $series |
38
|
|
|
* @property array $other_form |
39
|
|
|
* @property array $creators |
40
|
|
|
* @property array $meetings |
41
|
|
|
* @property array $subjects |
42
|
|
|
* @property array $genres |
43
|
|
|
* @property array $classifications |
44
|
|
|
* @property array $debug |
45
|
|
|
* @property int $pages |
46
|
|
|
* @property int $year |
47
|
|
|
* @property Carbon $modified |
48
|
|
|
* @property Carbon $created |
49
|
|
|
*/ |
50
|
|
|
class BibliographicRecord extends Record |
51
|
|
|
{ |
52
|
|
|
/** |
53
|
|
|
* @param string $x1 |
54
|
|
|
* @param string $x2 |
55
|
|
|
* @param string $default |
56
|
|
|
* |
57
|
|
|
* @return string |
58
|
|
|
*/ |
59
|
|
|
public function getMaterialSubtypeFrom007($x1, $x2, $default = 'Unknown') |
60
|
|
|
{ |
61
|
|
|
$f007values = array( |
62
|
|
|
'a' => array( |
63
|
|
|
'd' => 'Atlas', |
64
|
|
|
'g' => 'Diagram', |
65
|
|
|
'j' => 'Map', |
66
|
|
|
'k' => 'Profile', |
67
|
|
|
'q' => 'Model', |
68
|
|
|
'r' => 'Remote-sensing image', |
69
|
|
|
'_' => 'Map', |
70
|
|
|
), |
71
|
|
|
'c' => array( |
72
|
|
|
'a' => 'Tape cartridge', |
73
|
|
|
'b' => 'Chip cartridge', |
74
|
|
|
'c' => 'Computer optical disc cartridge', |
75
|
|
|
'd' => 'Computer disc, type unspecified', |
76
|
|
|
'e' => 'Computer disc cartridge, type unspecified', |
77
|
|
|
'f' => 'Tape cassette', |
78
|
|
|
'h' => 'Tape reel', |
79
|
|
|
'j' => 'Magnetic disk', |
80
|
|
|
'k' => 'Computer card', |
81
|
|
|
'm' => 'Magneto-optical disc', |
82
|
|
|
'o' => 'CD-ROM', // Optical disc |
83
|
|
|
'r' => 'Remote resource', // n Nettdokumenter |
84
|
|
|
), |
85
|
|
|
'f' => array( |
86
|
|
|
'a' => 'Moon', // in the Moon writing system |
87
|
|
|
'b' => 'Braille', // in the Braille writing system |
88
|
|
|
'c' => 'Combination ', // in a combination of two or more of the other defined types |
89
|
|
|
'd' => 'No writing system', |
90
|
|
|
), |
91
|
|
|
'h' => array( |
92
|
|
|
'a' => 'Aperture card', |
93
|
|
|
'b' => 'Microfilm cartridge', |
94
|
|
|
'c' => 'Microfilm cassette', |
95
|
|
|
'd' => 'Microfilm reel', |
96
|
|
|
'e' => 'Microfiche', |
97
|
|
|
'f' => 'Microfiche cassette', |
98
|
|
|
'g' => 'Microopaque', |
99
|
|
|
'h' => 'Microfilm slip', |
100
|
|
|
'j' => 'Microfilm roll', |
101
|
|
|
'u' => 'Microform', // Unspecified |
102
|
|
|
'z' => 'Microform', // Other |
103
|
|
|
'|' => 'Microform', // No attempt to code |
104
|
|
|
), |
105
|
|
|
'o' => array( |
106
|
|
|
'u' => 'Kit', |
107
|
|
|
'|' => 'Kit', |
108
|
|
|
), |
109
|
|
|
's' => array( |
110
|
|
|
'd' => 'Music CD', // v CD-er |
111
|
|
|
'e' => 'Cylinder', |
112
|
|
|
'g' => 'Sound cartridge', |
113
|
|
|
'i' => 'Sound-track film', |
114
|
|
|
'q' => 'Roll', |
115
|
|
|
's' => 'Sound cassette', |
116
|
|
|
't' => 'Sound-tape reel', |
117
|
|
|
'u' => 'Unspecified', |
118
|
|
|
'w' => 'Wire recording', |
119
|
|
|
), |
120
|
|
|
'v' => array( |
121
|
|
|
'c' => 'Videocartridge', |
122
|
|
|
'd' => 'Videodisc', // w DVD-er |
123
|
|
|
'f' => 'Videocassette', |
124
|
|
|
'r' => 'Videoreel', |
125
|
|
|
), |
126
|
|
|
); |
127
|
|
|
if (isset($f007values[$x1]) && isset($f007values[$x1][$x2])) { |
128
|
|
|
return $f007values[$x1][$x2]; |
129
|
|
|
} |
130
|
|
|
// TODO: LOG IT! |
131
|
|
|
return $default; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* @param \Danmichaelo\QuiteSimpleXMLElement\QuiteSimpleXMLElement $data |
136
|
|
|
*/ |
137
|
|
|
protected function parseMaterial(QuiteSimpleXmlElement $data) |
138
|
|
|
{ |
139
|
|
|
// See http://www.loc.gov/marc/ldr06guide.html |
140
|
|
|
|
141
|
|
|
// The Leader/06 (Type of record) character position contains a one-character |
142
|
|
|
// alphabetic code that differentiates MARC records created for various types of |
143
|
|
|
// content and materials. |
144
|
|
|
|
145
|
|
|
// The 008 field contains character positions that provide coded information about |
146
|
|
|
// the record as a whole and about special bibliographic aspects of the item cataloged. |
147
|
|
|
|
148
|
|
|
// Field 006 (Fixed-length data elements - Additional material characteristics) |
149
|
|
|
// permits coding for additional aspects of an electronic resource (including any |
150
|
|
|
// computer file aspects) if the 007 and 008 fields do not adequately describe it. |
151
|
|
|
|
152
|
|
|
// leader[6] : Type of record |
153
|
|
|
// leader[7] : Bibliographic level |
154
|
|
|
// Field 008/18-34 Configuration |
155
|
|
|
|
156
|
|
|
// LDR/06 |
157
|
|
|
$recordTypes = array( |
|
|
|
|
158
|
|
|
'a' => 'Language material', |
159
|
|
|
'c' => 'Notated music', |
160
|
|
|
'd' => 'Manuscript notated music', |
161
|
|
|
'e' => 'Cartographic material', |
162
|
|
|
'f' => 'Manuscript cartographic material', |
163
|
|
|
'g' => 'Projected medium', |
164
|
|
|
'i' => 'Nonmusical sound recording', |
165
|
|
|
'j' => 'Musical sound recording', |
166
|
|
|
'k' => 'Two-dimensional nonprojectable graphic', |
167
|
|
|
'm' => 'Computer file', |
168
|
|
|
'o' => 'Kit', |
169
|
|
|
'p' => 'Mixed materials', |
170
|
|
|
'r' => 'Three-dimensional artifact or naturally occurring object', |
171
|
|
|
't' => 'Manuscript language material', |
172
|
|
|
); |
173
|
|
|
|
174
|
|
|
// LDR/07 |
175
|
|
|
$bibliographicLevels = array( |
|
|
|
|
176
|
|
|
'a' => 'Monographic component part', |
177
|
|
|
'b' => 'Serial component part', |
178
|
|
|
'c' => 'Collection', |
179
|
|
|
'd' => 'Subunit', |
180
|
|
|
'i' => 'Integrating resource', |
181
|
|
|
'm' => 'Monograph/Item', |
182
|
|
|
's' => 'Serial', |
183
|
|
|
); |
184
|
|
|
|
185
|
|
|
// 007/00 (Category of material) |
186
|
|
|
$materialCategories = array( |
|
|
|
|
187
|
|
|
'a' => 'Map', |
188
|
|
|
'c' => 'Electronic resource', |
189
|
|
|
'd' => 'Globe', |
190
|
|
|
'f' => 'Tactile material', |
191
|
|
|
'g' => 'Projected graphic', |
192
|
|
|
'h' => 'Microform', |
193
|
|
|
'k' => 'Nonprojected graphic', |
194
|
|
|
'm' => 'Motion picture', |
195
|
|
|
'o' => 'Kit', |
196
|
|
|
'q' => 'Notated music', |
197
|
|
|
'r' => 'Remote-sensing image', |
198
|
|
|
's' => 'Sound recording', |
199
|
|
|
't' => 'Text', // p Trykt materiale |
200
|
|
|
'v' => 'Videorecording', |
201
|
|
|
'z' => 'Unspecified', |
202
|
|
|
); |
203
|
|
|
|
204
|
|
|
// 008/24-27 - Nature of contents (006/07-10) |
205
|
|
|
$natureOfContents = array( |
206
|
|
|
'a' => 'Abstract', |
207
|
|
|
'b' => 'Bibliography', |
208
|
|
|
'c' => 'Catalog', |
209
|
|
|
'd' => 'Dictionary', |
210
|
|
|
'e' => 'Encyclopedia', |
211
|
|
|
'f' => 'Handbook', |
212
|
|
|
'g' => 'Legal article', |
213
|
|
|
'i' => 'Index', |
214
|
|
|
'j' => 'Patent document', |
215
|
|
|
'k' => 'Discography', |
216
|
|
|
'l' => 'Legislation', |
217
|
|
|
'm' => 'Thesis', |
218
|
|
|
'n' => 'Surveys of literature in a subject area', |
219
|
|
|
'o' => 'Review', |
220
|
|
|
'p' => 'Programmed text', |
221
|
|
|
'q' => 'Filmography', |
222
|
|
|
'r' => 'Directory', |
223
|
|
|
's' => 'Statistics', |
224
|
|
|
't' => 'Technical report', |
225
|
|
|
'u' => 'Standards/specification', |
226
|
|
|
'v' => 'Legal cases and case notes', |
227
|
|
|
'w' => 'Law reports and digests', |
228
|
|
|
'y' => 'Yearbook', |
229
|
|
|
'z' => 'Treaty', |
230
|
|
|
'2' => 'Offprint', |
231
|
|
|
'5' => 'Calendar', |
232
|
|
|
'6' => 'Comics/graphic novel', |
233
|
|
|
); |
234
|
|
|
|
235
|
|
|
$videoFormats = array( |
236
|
|
|
'a' => 'Beta (1/2 in., videocassette)', |
237
|
|
|
'b' => 'VHS (1/2 in., videocassette)', |
238
|
|
|
'c' => 'U-matic (3/4 in., videocasstte)', |
239
|
|
|
'd' => 'EIAJ (1/2 in., reel)', |
240
|
|
|
'e' => 'Type C (1 in., reel)', |
241
|
|
|
'f' => 'Quadruplex (1 in. or 2 in., reel)', |
242
|
|
|
'g' => 'Laserdisc', |
243
|
|
|
'h' => 'CED (Capacitance Electronic Disc) videodisc', |
244
|
|
|
'i' => 'Betacam (1/2 in., videocassette)', |
245
|
|
|
'j' => 'Betacam SP (1/2 in., videocassette)', |
246
|
|
|
'k' => 'Super-VHS (1/2 in., videocassette)', |
247
|
|
|
'm' => 'M-II (1/2 in., videocassette)', |
248
|
|
|
'o' => 'D-2 (3/4 in., videocassette)', |
249
|
|
|
'p' => '8 mm.', |
250
|
|
|
'q' => 'Hi-8 mm.', |
251
|
|
|
's' => 'Blu-ray', |
252
|
|
|
'u' => 'Unknown', |
253
|
|
|
'v' => 'DVD', |
254
|
|
|
); |
255
|
|
|
|
256
|
|
|
// If Leader/06 = a and Leader/07 = a, c, d, or m: Books |
257
|
|
|
// If Leader/06 = a and Leader/07 = b, i, or s: Continuing Resources |
258
|
|
|
// If Leader/06 = t: Books |
259
|
|
|
// If Leader/06 = c, d, i, or j: Music |
260
|
|
|
// If Leader/06 = e, or f: Maps |
261
|
|
|
// If Leader/06 = g, k, o, or r: Visual Materials |
262
|
|
|
// If Leader/06 = m: Computer Files |
263
|
|
|
// If Leader/06 = p: Mixed Materials |
264
|
|
|
|
265
|
|
|
$ldr = str_split($data->text('marc:leader')); |
266
|
|
|
$f007 = str_split($data->text('marc:controlfield[@tag="007"]')); |
267
|
|
|
$f008 = str_split($data->text('marc:controlfield[@tag="008"]')); |
268
|
|
|
|
269
|
|
|
$material = 'Unknown'; |
270
|
|
|
$this->material = $material; |
271
|
|
|
$this->electronic = false; |
272
|
|
|
|
273
|
|
|
$this->debug = array( |
274
|
|
|
'ldr06' => array_get($ldr, 6), |
275
|
|
|
'ldr07' => array_get($ldr, 7), |
276
|
|
|
'f7_01' => array_get($f007, 0) ?: null, |
277
|
|
|
'f7_02' => array_get($f007, 1), |
278
|
|
|
); |
279
|
|
|
|
280
|
|
|
if (count($ldr) < 8) { |
281
|
|
|
return; |
282
|
|
|
} |
283
|
|
|
if (count($f007) < 2) { |
284
|
|
|
return; |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
switch ($ldr[6]) { |
288
|
|
|
|
289
|
|
|
case 'a': |
290
|
|
|
if (in_array($ldr[7], array('a', 'c', 'd', 'm'))) { |
291
|
|
|
$material = 'Book'; |
292
|
|
|
} |
293
|
|
|
if (in_array($ldr[7], array('b', 'i', 's'))) { |
294
|
|
|
$material = 'Series'; |
295
|
|
|
} |
296
|
|
|
break; |
297
|
|
|
|
298
|
|
|
case 't': |
299
|
|
|
$material = 'Book'; |
300
|
|
|
break; |
301
|
|
|
|
302
|
|
|
case 'c': |
303
|
|
|
case 'd': |
304
|
|
|
case 'i': |
305
|
|
|
case 'j': |
306
|
|
|
$material = 'Music'; |
307
|
|
|
break; |
308
|
|
|
|
309
|
|
|
case 'e': |
310
|
|
|
case 'f': |
311
|
|
|
$material = 'Map'; |
312
|
|
|
break; |
313
|
|
|
|
314
|
|
|
case 'g': |
315
|
|
|
case 'k': |
316
|
|
|
case 'o': |
317
|
|
|
case 'r': |
318
|
|
|
$material = 'Visual'; |
319
|
|
|
break; |
320
|
|
|
|
321
|
|
|
case 'm': |
322
|
|
|
$material = 'File'; |
323
|
|
|
// used for computer software, numeric data, not for e-books or e-journals! |
324
|
|
|
break; |
325
|
|
|
|
326
|
|
|
case 'p': |
327
|
|
|
$material = 'Mixed'; |
328
|
|
|
break; |
329
|
|
|
|
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
$online = ($f007[0] == 'c' && $f007[1] == 'r'); |
333
|
|
|
|
334
|
|
|
if ($material == 'File') { |
335
|
|
|
$material = $this->getMaterialSubtypeFrom007($f007[0], $f007[1], $material); |
336
|
|
|
} elseif ($material == 'Visual') { |
337
|
|
|
$material = $this->getMaterialSubtypeFrom007($f007[0], $f007[1], $material); |
338
|
|
|
|
339
|
|
|
if (isset($f007[4]) && isset($videoFormats[$f007[4]])) { |
340
|
|
|
$material = $videoFormats[$f007[4]]; // DVD, Blu-ray |
341
|
|
|
} |
342
|
|
|
} elseif ($material == 'Music') { |
343
|
|
|
if ($f007[0] == 't') { |
344
|
|
|
$material = 'Sheet music'; |
345
|
|
|
} else { |
346
|
|
|
$material = $this->getMaterialSubtypeFrom007($f007[0], $f007[1], $material); |
347
|
|
|
if (array_get($ldr, 7) == 'a') { |
348
|
|
|
$material .= ' track'; |
349
|
|
|
} |
350
|
|
|
} |
351
|
|
|
} elseif ($material == 'Series') { |
352
|
|
|
switch ($f008[21]) { |
353
|
|
|
|
354
|
|
|
case 'm': |
355
|
|
|
$material = 'Series'; // Monographic series (merk: skiller ikke mellom 'flerbindsverk' og 'serieinnførsel') |
356
|
|
|
break; |
357
|
|
|
|
358
|
|
|
case 'n': |
359
|
|
|
$material = 'Newspaper'; |
360
|
|
|
if ($f007[0] == 'h') { |
361
|
|
|
$material .= ' on microform'; |
362
|
|
|
} |
363
|
|
|
break; |
364
|
|
|
|
365
|
|
|
case 'p': |
366
|
|
|
$material = 'Periodical'; |
367
|
|
|
break; |
368
|
|
|
|
369
|
|
|
} |
370
|
|
|
if (array_get($ldr, 7) == 'a') { |
371
|
|
|
$material = 'Article'; |
372
|
|
|
} |
373
|
|
|
} elseif ($material == 'Book') { |
374
|
|
|
if (isset($natureOfContents[$f008[24]])) { |
375
|
|
|
// Slight simplification |
376
|
|
|
$material = $natureOfContents[$f008[24]]; |
377
|
|
|
} |
378
|
|
|
if (array_get($ldr, 7) == 'a') { |
379
|
|
|
$material = 'Article'; |
380
|
|
|
// or Article/Chapter ? |
381
|
|
|
} |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
$this->material = $material; |
385
|
|
|
$this->electronic = $online; |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
public function addClassification($node, &$classifications, $fields, $system = null, $edition = null, $assigner = null) |
389
|
|
|
{ |
390
|
|
|
$cl = array('system' => $system, 'edition' => $edition, 'number' => null, 'assigner' => $assigner); |
391
|
|
|
foreach ($fields as $key => $val) { |
392
|
|
|
$t = $node->text('marc:subfield[@code="' . $key . '"]'); |
393
|
|
|
if (!is_array($val)) { |
394
|
|
|
$val = array($val); |
395
|
|
|
} |
396
|
|
|
if (count($val) > 2) { |
397
|
|
|
$t = preg_replace('/' . $val[1] . '/', $val[2], $t); |
398
|
|
|
} |
399
|
|
|
if (!empty($t)) { |
400
|
|
|
$cl[$val[0]] = $t; |
401
|
|
|
} |
402
|
|
|
} |
403
|
|
|
|
404
|
|
|
if (is_null($cl['system'])) { |
405
|
|
|
return; |
406
|
|
|
// Invalid value in $a, should we trigger some event to allow logging? |
407
|
|
|
} |
408
|
|
|
|
409
|
|
|
if (is_null($cl['number'])) { |
410
|
|
|
return; |
411
|
|
|
// Invalid value in $a, should we trigger some event to allow logging? |
412
|
|
|
} |
413
|
|
|
|
414
|
|
|
$classifications[] = $cl; |
415
|
|
|
} |
416
|
|
|
|
417
|
|
|
/** |
418
|
|
|
* Parses common elements in subject added entry fields 600-655. |
419
|
|
|
* |
420
|
|
|
* @param \Danmichaelo\QuiteSimpleXMLElement\QuiteSimpleXMLElement $node |
421
|
|
|
* |
422
|
|
|
* @return array |
423
|
|
|
*/ |
424
|
|
|
public function parseSubjectAddedEntry(QuiteSimpleXmlElement &$node) |
425
|
|
|
{ |
426
|
|
|
$out = array('term' => '', 'vocabulary' => null); |
427
|
|
|
$vocabularies = array( |
428
|
|
|
'0' => 'lcsh', |
429
|
|
|
'1' => 'lccsh', // LC subject headings for children's literature |
430
|
|
|
'2' => 'mesh', // Medical Subject Headings |
431
|
|
|
'3' => 'atg', // National Agricultural Library subject authority file (?) |
432
|
|
|
// 4 : unknown |
433
|
|
|
'5' => 'cash', // Canadian Subject Headings |
434
|
|
|
'6' => 'rvm', // Répertoire de vedettes-matière |
435
|
|
|
// 7: Source specified in subfield $2 |
436
|
|
|
); |
437
|
|
|
$ind2 = $node->attr('ind2'); |
438
|
|
|
|
439
|
|
|
$id = $node->text('marc:subfield[@code="0"]'); |
440
|
|
|
$out['id'] = empty($id) ? null : $id; |
441
|
|
|
|
442
|
|
|
if (isset($vocabularies[$ind2])) { |
443
|
|
|
$out['vocabulary'] = $vocabularies[$ind2]; |
444
|
|
|
} elseif ($ind2 == '7') { |
445
|
|
|
$vocab = $node->text('marc:subfield[@code="2"]'); |
446
|
|
|
if (!empty($vocab)) { |
447
|
|
|
$out['vocabulary'] = $vocab; |
448
|
|
|
} |
449
|
|
|
} elseif ($ind2 == '4') { |
450
|
|
|
$this->parseAuthority($node->text('marc:subfield[@code="0"]'), $out); |
451
|
|
|
} |
452
|
|
|
|
453
|
|
|
$out['parts'] = array(); |
454
|
|
|
$subdivtypes = array( |
455
|
|
|
'v' => 'form', |
456
|
|
|
'x' => 'general', |
457
|
|
|
'y' => 'chronologic', |
458
|
|
|
'z' => 'geographic', |
459
|
|
|
); |
460
|
|
|
foreach ($node->all('marc:subfield') as $subdiv) { |
461
|
|
|
$code = $subdiv->attr('code'); |
462
|
|
|
if (in_array($code, array_keys($subdivtypes))) { |
463
|
|
|
$subdiv = trim($subdiv, '.'); |
464
|
|
|
$out['parts'][] = array('value' => $subdiv, 'type' => $subdivtypes[$code]); |
465
|
|
|
$out['term'] .= self::$subfieldSeparator . $subdiv; |
466
|
|
|
} |
467
|
|
|
} |
468
|
|
|
|
469
|
|
|
return $out; |
470
|
|
|
} |
471
|
|
|
|
472
|
|
|
/** |
473
|
|
|
* @param \Danmichaelo\QuiteSimpleXMLElement\QuiteSimpleXMLElement $data |
474
|
|
|
*/ |
475
|
|
|
public function __construct(QuiteSimpleXmlElement $data = null) |
476
|
|
|
{ |
477
|
|
|
if (is_null($data)) { |
478
|
|
|
return; |
479
|
|
|
} |
480
|
|
|
|
481
|
|
|
$this->parseMaterial($data); |
482
|
|
|
|
483
|
|
|
// Control fields |
484
|
|
|
$this->id = $data->text('marc:controlfield[@tag="001"]'); |
485
|
|
|
|
486
|
|
|
// 003: MARC code for the agency whose system control number is |
487
|
|
|
// contained in field 001 (Control Number) |
488
|
|
|
// See http://www.loc.gov/marc/authority/ecadorg.html |
489
|
|
|
$this->agency = $data->text('marc:controlfield[@tag="003"]'); |
490
|
|
|
|
491
|
|
|
// 005: Modified |
492
|
|
|
$this->modified = $this->parseDateTime($data->text('marc:controlfield[@tag="005"]')); |
493
|
|
|
|
494
|
|
|
// 008: Extract *some* information |
495
|
|
|
$f008 = $data->text('marc:controlfield[@tag="008"]'); |
496
|
|
|
$this->created = $this->parseDateTime(substr($f008, 0, 6)); |
497
|
|
|
$this->language = substr($f008, 35, 3); |
|
|
|
|
498
|
|
|
|
499
|
|
|
$creators = array(); |
500
|
|
|
$meetings = array(); |
501
|
|
|
$subjects = array(); |
502
|
|
|
$genres = array(); |
503
|
|
|
$classifications = array(); |
504
|
|
|
$series = array(); |
505
|
|
|
$notes = array(); |
506
|
|
|
$isbns = array(); |
507
|
|
|
$issns = array(); |
508
|
|
|
$alternativeTitles = array(); |
509
|
|
|
|
510
|
|
|
// Relationships |
511
|
|
|
$preceding = array(); |
512
|
|
|
$succeeding = array(); |
513
|
|
|
$part_of = array(); |
514
|
|
|
$other_form = array(); |
515
|
|
|
|
516
|
|
|
$this->is_series = false; |
517
|
|
|
$this->is_multivolume = false; |
518
|
|
|
|
519
|
|
|
foreach ($data->all('marc:datafield') as $node) { |
520
|
|
|
$marcfield = intval($node->attributes()->tag); |
521
|
|
|
switch ($marcfield) { |
522
|
|
|
|
523
|
|
|
// 010 - Library of Congress Control Number (NR) |
524
|
|
|
case 10: |
525
|
|
|
$this->lccn = $node->text('marc:subfield[@code="a"]'); |
526
|
|
|
break; |
527
|
|
|
|
528
|
|
|
// 020 - International Standard Book Number (R) |
529
|
|
View Code Duplication |
case 20: // Test added |
|
|
|
|
530
|
|
|
$isbn = $node->text('marc:subfield[@code="a"]'); |
531
|
|
|
$isbn = preg_replace('/^([0-9\-xX]+).*$/', '\1', $isbn); |
532
|
|
|
if (empty($isbn)) { |
533
|
|
|
break; |
534
|
|
|
} |
535
|
|
|
array_push($isbns, $isbn); |
536
|
|
|
break; |
537
|
|
|
|
538
|
|
|
// 022 - International Standard Serial Number (R) |
539
|
|
View Code Duplication |
case 22: // Test added |
|
|
|
|
540
|
|
|
$issn = $node->text('marc:subfield[@code="a"]'); |
541
|
|
|
$issn = preg_replace('/^([0-9\-xX]+).*$/', '\1', $issn); |
542
|
|
|
if (empty($issn)) { |
543
|
|
|
break; |
544
|
|
|
} |
545
|
|
|
array_push($issns, $issn); |
546
|
|
|
break; |
547
|
|
|
|
548
|
|
|
// 040 - Cataloging Source (NR) |
549
|
|
|
case 40: // Test added |
550
|
|
|
$x = $node->text('marc:subfield[@code="e"]'); |
551
|
|
|
if ($x) { |
552
|
|
|
$this->catalogingRules = $x; |
553
|
|
|
} |
554
|
|
|
// Value from http://www.loc.gov/standards/sourcelist/descriptive-conventions.html |
555
|
|
|
break; |
556
|
|
|
|
557
|
|
|
// 060 - National Library of Medicine Call Number (R) |
558
|
|
|
case 60: |
559
|
|
|
$this->addClassification( |
560
|
|
|
$node, |
561
|
|
|
$classifications, |
562
|
|
|
array( |
563
|
|
|
'a' => 'number', |
564
|
|
|
), |
565
|
|
|
$system = 'nlm', |
566
|
|
|
$assigner = ($node->attr('ind2') == '0') ? 'DNLM' : null |
567
|
|
|
); |
568
|
|
|
break; |
569
|
|
|
|
570
|
|
|
// 080 - Universal Decimal Classification Number (R) |
571
|
|
View Code Duplication |
case 80: |
|
|
|
|
572
|
|
|
$this->addClassification( |
573
|
|
|
$node, |
574
|
|
|
$classifications, |
575
|
|
|
array( |
576
|
|
|
'a' => array('number', '^.*?([0-9.\/:()]+).*$', '\1'), |
577
|
|
|
'2' => 'edition', |
578
|
|
|
), |
579
|
|
|
$system = 'udc' |
580
|
|
|
); |
581
|
|
|
break; |
582
|
|
|
|
583
|
|
|
// 082 - Dewey Decimal Classification Number (R) |
584
|
|
View Code Duplication |
case 82: |
|
|
|
|
585
|
|
|
$this->addClassification( |
586
|
|
|
$node, |
587
|
|
|
$classifications, |
588
|
|
|
array( |
589
|
|
|
'a' => array('number', '^.*?([0-9.]+)\/?([0-9.]*).*$', '\1\2'), |
590
|
|
|
'2' => 'edition', |
591
|
|
|
'q' => 'assigner', |
592
|
|
|
), |
593
|
|
|
$system = 'ddc' |
594
|
|
|
); |
595
|
|
|
break; |
596
|
|
|
|
597
|
|
|
// 084 - Other Classification Number (R) |
598
|
|
|
case 84: |
599
|
|
|
$this->addClassification( |
600
|
|
|
$node, |
601
|
|
|
$classifications, |
602
|
|
|
array( |
603
|
|
|
'a' => 'number', |
604
|
|
|
'2' => 'system', |
605
|
|
|
'q' => 'assigner', |
606
|
|
|
) |
607
|
|
|
); |
608
|
|
|
break; |
609
|
|
|
|
610
|
|
|
/* |
611
|
|
|
case 89: |
612
|
|
|
if (!isset($this->klass)) $this->klass = array(); |
613
|
|
|
$klass = $node->text('marc:subfield[@code="a"]'); |
614
|
|
|
$klass = preg_replace('/[^0-9.]/', '', $klass); |
615
|
|
|
foreach ($this->klass as $kitem) { |
616
|
|
|
if (($kitem['kode'] == $klass) && ($kitem['system'] == 'dewey')) { |
617
|
|
|
continue 3; |
618
|
|
|
} |
619
|
|
|
} |
620
|
|
|
array_push($this->klass, array('kode' => $klass, 'system' => 'dewey')); |
621
|
|
|
break; |
622
|
|
|
*/ |
623
|
|
|
|
624
|
|
|
case 100: |
625
|
|
|
$author = array( |
626
|
|
|
'name' => $node->text('marc:subfield[@code="a"]'), |
627
|
|
|
); |
628
|
|
|
$author['normalizedName'] = $author['name']; |
629
|
|
|
$spl = explode(', ', $author['name']); |
630
|
|
View Code Duplication |
if (count($spl) == 2) { |
|
|
|
|
631
|
|
|
$author['name'] = $spl[1] . ' ' . $spl[0]; |
632
|
|
|
} |
633
|
|
|
$this->parseRelator($node, $author, 'main'); |
634
|
|
|
$this->parseAuthority($node->text('marc:subfield[@code="0"]'), $author); |
635
|
|
|
|
636
|
|
|
$creators[] = $author; |
637
|
|
|
break; |
638
|
|
|
|
639
|
|
|
case 110: |
640
|
|
|
$author = array( |
641
|
|
|
'name' => $node->text('marc:subfield[@code="a"]'), |
642
|
|
|
); |
643
|
|
|
$author['normalizedName'] = $author['name']; |
644
|
|
|
foreach ($node->all('marc:subfield[@code="b"]') as $subunit) { |
645
|
|
|
$author['name'] .= self::$subfieldSeparator . trim($subunit, ','); |
646
|
|
|
} |
647
|
|
|
$this->parseRelator($node, $author, 'corporate'); |
648
|
|
|
$this->parseAuthority($node->text('marc:subfield[@code="0"]'), $author); |
649
|
|
|
|
650
|
|
|
$creators[] = $author; |
651
|
|
|
break; |
652
|
|
|
|
653
|
|
View Code Duplication |
case 111: |
|
|
|
|
654
|
|
|
$meeting = array( |
655
|
|
|
'name' => $node->text('marc:subfield[@code="a"]'), |
656
|
|
|
); |
657
|
|
|
$meeting['normalizedName'] = $meeting['name']; |
658
|
|
|
$this->parseRelator($node, $meeting, 'meeting'); |
659
|
|
|
$this->parseAuthority($node->text('marc:subfield[@code="0"]'), $meeting); |
660
|
|
|
|
661
|
|
|
$meetings[] = $meeting; |
662
|
|
|
break; |
663
|
|
|
|
664
|
|
|
case 130: |
665
|
|
|
// Uniform title |
666
|
|
|
|
667
|
|
|
// TODO: Need a more robust way to prefer 130 over 245 |
668
|
|
|
// Currently we depend on 130 coming before 245. |
669
|
|
|
$this->title = $node->text('marc:subfield[@code="a"]'); |
670
|
|
|
break; |
671
|
|
|
|
672
|
|
|
// 245 : Title Statement (NR) |
673
|
|
|
case 245: |
674
|
|
|
$title = $node->text('marc:subfield[@code="a"]') . ' ' . $node->text('marc:subfield[@code="b"]'); |
675
|
|
|
$title = rtrim($title, ' /'); |
676
|
|
|
|
677
|
|
|
$titleParts = preg_split('/(:|=)/', $title, -1, PREG_SPLIT_DELIM_CAPTURE); |
678
|
|
|
$isbdCode = ':'; |
679
|
|
|
$title = ''; |
680
|
|
|
foreach ($titleParts as $titlePart) { |
681
|
|
|
$titlePart = trim($titlePart); |
682
|
|
|
if (is_null($isbdCode)) { |
683
|
|
|
$isbdCode = $titlePart; |
684
|
|
|
} else { |
685
|
|
|
if ($isbdCode == '=') { |
686
|
|
|
$alternativeTitles[] = $titlePart; |
687
|
|
|
} else { // isbdCode == ':' or ';' |
688
|
|
|
// TODO: Cover more cases explicitly? |
689
|
|
|
// http://www.loc.gov/marc/bibliographic/bd245.html |
690
|
|
|
$title = empty($title) ? $titlePart : "$title $isbdCode $titlePart"; |
691
|
|
|
} |
692
|
|
|
$isbdCode = null; |
693
|
|
|
} |
694
|
|
|
} |
695
|
|
|
|
696
|
|
|
if (isset($this->title)) { // If not already set by 130 |
697
|
|
|
$alternativeTitles[] = $title; |
698
|
|
|
} else { |
699
|
|
|
$this->title = $title; |
700
|
|
|
} |
701
|
|
|
|
702
|
|
|
// $n : Number of part/section of a work (R) |
703
|
|
|
$part_no = $node->text('marc:subfield[@code="n"]'); |
704
|
|
|
if ($part_no !== '') { |
705
|
|
|
$this->part_no = $part_no; |
706
|
|
|
} |
707
|
|
|
|
708
|
|
|
// $p : Name of part/section of a work (R) |
709
|
|
|
$part_name = $node->text('marc:subfield[@code="p"]'); |
710
|
|
|
if ($part_name !== '') { |
711
|
|
|
$this->part_name = $part_name; |
712
|
|
|
} |
713
|
|
|
|
714
|
|
|
// $h : Medium (NR) |
715
|
|
|
$medium = $node->text('marc:subfield[@code="h"]'); |
716
|
|
|
if ($medium !== '') { |
717
|
|
|
$this->medium = $medium; |
718
|
|
|
} |
719
|
|
|
|
720
|
|
|
break; |
721
|
|
|
|
722
|
|
|
// 246 : Varying Form of Title (R) |
723
|
|
|
case 246: |
724
|
|
|
// Note: The second indicator gives the type of title: |
725
|
|
|
// 0 - Portion of title |
726
|
|
|
// 1 - Parallel title |
727
|
|
|
// 2 - Distinctive title |
728
|
|
|
// 3 - Other title |
729
|
|
|
// 4 - Cover title |
730
|
|
|
// 5 - Added title page title |
731
|
|
|
// 6 - Caption title |
732
|
|
|
// 7 - Running title |
733
|
|
|
// 8 - Spine title |
734
|
|
|
$title = rtrim($node->text('marc:subfield[@code="a"]'), ' :-'); |
735
|
|
|
$subtitle = $node->text('marc:subfield[@code="b"]'); |
736
|
|
|
// TODO: Cover more of the cases on |
737
|
|
|
// http://www.loc.gov/marc/bibliographic/bd246.html |
738
|
|
|
if (!empty($subtitle)) { |
739
|
|
|
$title .= ' : ' . $subtitle; |
740
|
|
|
} |
741
|
|
|
$alternativeTitles[] = $title; |
742
|
|
|
break; |
743
|
|
|
|
744
|
|
|
case 250: |
745
|
|
|
$this->edition = $node->text('marc:subfield[@code="a"]'); |
746
|
|
|
break; |
747
|
|
|
|
748
|
|
|
case 260: |
749
|
|
|
$this->placeOfPublication = $node->text('marc:subfield[@code="a"]'); |
750
|
|
|
$this->publisher = $node->text('marc:subfield[@code="b"]'); |
751
|
|
|
$y = preg_replace('/^.*?([0-9]{4}).*$/', '\1', $node->first('marc:subfield[@code="c"]')); |
752
|
|
|
$this->year = $y ? intval($y) : null; |
753
|
|
|
break; |
754
|
|
|
|
755
|
|
|
case 300: |
756
|
|
|
$this->extent = $node->text('marc:subfield[@code="a"]'); |
757
|
|
|
|
758
|
|
|
# 2.5B2 "327 s.", 2.5B4 "48 [i.e. 96] s.", 2.5B7 "[93] s." |
759
|
|
|
preg_match( |
760
|
|
|
'/\[?([0-9]+)\]? (s.|p.|pp.)/', |
761
|
|
|
$node->text('marc:subfield[@code="a"]'), |
762
|
|
|
$matches |
763
|
|
|
); |
764
|
|
|
if ($matches) { |
|
|
|
|
765
|
|
|
$this->pages = intval($matches[1]); |
766
|
|
|
} |
767
|
|
|
|
768
|
|
|
# 2.5B6 Eks: "s. 327-698" (flerbindsverk) |
769
|
|
|
preg_match( |
770
|
|
|
'/(s.|p.|pp.) ([0-9]+)-([0-9]+)/', |
771
|
|
|
$node->text('marc:subfield[@code="a"]'), |
772
|
|
|
$matches |
773
|
|
|
); |
774
|
|
|
if ($matches) { |
|
|
|
|
775
|
|
|
$this->pages = intval($matches[3]) - intval($matches[2]) + 1; |
776
|
|
|
} |
777
|
|
|
break; |
778
|
|
|
|
779
|
|
|
/* |
780
|
|
|
case 490: |
781
|
|
|
$serie = array( |
782
|
|
|
'title' => $node->text('marc:subfield[@code="a"]'), |
783
|
|
|
'volume' => $node->text('marc:subfield[@code="v"]') |
784
|
|
|
); |
785
|
|
|
$this->series[] = $serie; |
786
|
|
|
break; |
787
|
|
|
*/ |
788
|
|
|
|
789
|
|
|
// 500 : General Note (R) |
790
|
|
|
case 500: |
791
|
|
|
|
792
|
|
|
// $a - General note (NR) |
793
|
|
|
$notes[] = $node->text('marc:subfield[@code="a"]'); |
794
|
|
|
break; |
795
|
|
|
|
796
|
|
|
// 502 : Dissertation Note (R) |
797
|
|
|
case 502: |
798
|
|
|
|
799
|
|
|
// $a - Dissertation note (NR) |
800
|
|
|
$notes[] = $node->text('marc:subfield[@code="a"]'); |
801
|
|
|
break; |
802
|
|
|
|
803
|
|
|
case 505: |
804
|
|
|
|
805
|
|
|
// <datafield tag="520" ind1=" " ind2=" "> |
806
|
|
|
// <subfield code="a">"The conceptual changes brought by modern physics are important, radical and fascinating, yet they are only vaguely understood by people working outside the field. Exploring the four pillars of modern physics - relativity, quantum mechanics, elementary particles and cosmology - this clear and lively account will interest anyone who has wondered what Einstein, Bohr, Schrödinger and Heisenberg were really talking about. The book discusses quarks and leptons, antiparticles and Feynman diagrams, curved space-time, the Big Bang and the expanding Universe. Suitable for undergraduate students in non-science as well as science subjects, it uses problems and worked examples to help readers develop an understanding of what recent advances in physics actually mean"--</subfield> |
807
|
|
|
// <subfield code="c">Provided by publisher.</subfield> |
808
|
|
|
// </datafield> |
809
|
|
|
$this->contents = $node->text('marc:subfield[@code="a"]'); |
810
|
|
|
break; |
811
|
|
|
|
812
|
|
|
case 520: |
813
|
|
|
|
814
|
|
|
// <datafield tag="520" ind1=" " ind2=" "> |
815
|
|
|
// <subfield code="a">"The conceptual changes brought by modern physics are important, radical and fascinating, yet they are only vaguely understood by people working outside the field. Exploring the four pillars of modern physics - relativity, quantum mechanics, elementary particles and cosmology - this clear and lively account will interest anyone who has wondered what Einstein, Bohr, Schrödinger and Heisenberg were really talking about. The book discusses quarks and leptons, antiparticles and Feynman diagrams, curved space-time, the Big Bang and the expanding Universe. Suitable for undergraduate students in non-science as well as science subjects, it uses problems and worked examples to help readers develop an understanding of what recent advances in physics actually mean"--</subfield> |
816
|
|
|
// <subfield code="c">Provided by publisher.</subfield> |
817
|
|
|
// </datafield> |
818
|
|
|
$this->summary = array( |
819
|
|
|
'assigning_source' => $node->text('marc:subfield[@code="c"]'), |
820
|
|
|
'text' => $node->text('marc:subfield[@code="a"]'), |
821
|
|
|
); |
822
|
|
|
break; |
823
|
|
|
|
824
|
|
|
// 580 : Complex Linking Note (R) |
825
|
|
|
case 580: |
826
|
|
|
|
827
|
|
|
if ($data->has('marc:datafield[@tag="780"]')) { |
828
|
|
|
$preceding['note'] = $node->text('marc:subfield[@code="a"]'); |
829
|
|
|
} elseif ($data->has('marc:datafield[@tag="785"]')) { |
830
|
|
|
$succeeding['note'] = $node->text('marc:subfield[@code="a"]'); |
831
|
|
|
} elseif ($data->has('marc:datafield[@tag="773"]')) { |
832
|
|
|
$part_of['note'] = $node->text('marc:subfield[@code="a"]'); |
833
|
|
|
} |
834
|
|
|
break; |
835
|
|
|
|
836
|
|
|
case 600: |
837
|
|
|
$tmp = $this->parseSubjectAddedEntry($node); |
838
|
|
|
|
839
|
|
|
$name = $node->text('marc:subfield[@code="a"]'); |
840
|
|
|
$qualifiers = array(); |
841
|
|
|
$titles = $node->text('marc:subfield[@code="c"]'); |
842
|
|
|
if (!empty($titles)) { |
843
|
|
|
$qualifiers[] = trim($titles, '(),.'); |
844
|
|
|
} |
845
|
|
|
$dates = $node->text('marc:subfield[@code="d"]'); |
846
|
|
|
if (!empty($dates)) { |
847
|
|
|
$qualifiers[] = trim($dates, '(),.'); |
848
|
|
|
} |
849
|
|
|
|
850
|
|
|
// - To concat or not concat… not sure, but in principle |
851
|
|
|
// the $a $c $d $q values should be the same on all |
852
|
|
|
// records, so for filtering purposes it doesn't seem |
853
|
|
|
// necessary to have them separated. For display |
854
|
|
|
// purposes, it can be useful of course. But then again, |
855
|
|
|
// the parts should be available from the authority |
856
|
|
|
// register.. |
857
|
|
|
// - Another question is whether we should do some |
858
|
|
|
// normalizing to try aligning records with different |
859
|
|
|
// punctuation standards (US vs UK) |
860
|
|
|
if (count($qualifiers) != 0) { |
861
|
|
|
$name = "$name (" . implode(', ', $qualifiers) . ')'; |
862
|
|
|
} |
863
|
|
|
$tmp['term'] = $name . $tmp['term']; |
864
|
|
|
$tmp['type'] = 'person'; |
865
|
|
|
|
866
|
|
|
array_push($subjects, $tmp); |
867
|
|
|
break; |
868
|
|
|
|
869
|
|
|
case 610: |
870
|
|
|
$tmp = $this->parseSubjectAddedEntry($node); |
871
|
|
|
|
872
|
|
|
$name = trim($node->text('marc:subfield[@code="a"]'), ','); |
873
|
|
|
foreach ($node->all('marc:subfield[@code="b"]') as $subunit) { |
874
|
|
|
$name .= self::$subfieldSeparator . trim($subunit, ','); |
875
|
|
|
} |
876
|
|
|
$tmp['type'] = 'corporation'; |
877
|
|
|
$tmp['term'] = $name . $tmp['term']; |
878
|
|
|
array_push($subjects, $tmp); |
879
|
|
|
break; |
880
|
|
|
|
881
|
|
|
case 611: |
882
|
|
|
$tmp = $this->parseSubjectAddedEntry($node); |
883
|
|
|
$dates = $node->text('marc:subfield[@code="d"]'); |
884
|
|
|
if (!empty($dates)) { |
885
|
|
|
$tmp['time'] = trim($dates, ' :,.()'); |
886
|
|
|
} |
887
|
|
|
$location = $node->text('marc:subfield[@code="c"]'); |
888
|
|
|
if (!empty($location)) { |
889
|
|
|
$tmp['place'] = trim($location, ' :,.()'); |
890
|
|
|
} |
891
|
|
|
$misc = $node->text('marc:subfield[@code="g"]'); |
892
|
|
|
if (!empty($misc)) { |
893
|
|
|
$tmp['misc'] = trim($misc, ' :,.()'); |
894
|
|
|
} |
895
|
|
|
$number = $node->text('marc:subfield[@code="n"]'); |
896
|
|
|
if (!empty($number)) { |
897
|
|
|
$tmp['number'] = trim($number, ' :,.()'); |
898
|
|
|
} |
899
|
|
|
|
900
|
|
|
$name = trim($node->text('marc:subfield[@code="a"]'), ','); |
901
|
|
|
$tmp['type'] = 'meeting'; |
902
|
|
|
$tmp['term'] = $name . $tmp['term']; |
903
|
|
|
array_push($subjects, $tmp); |
904
|
|
|
break; |
905
|
|
|
|
906
|
|
View Code Duplication |
case 648: |
|
|
|
|
907
|
|
|
$tmp = $this->parseSubjectAddedEntry($node); |
908
|
|
|
|
909
|
|
|
$emne = $node->text('marc:subfield[@code="a"]'); |
910
|
|
|
$tmp['type'] = 'chronologic'; |
911
|
|
|
$tmp['term'] = trim($emne, '.') . $tmp['term']; |
912
|
|
|
|
913
|
|
|
array_push($subjects, $tmp); |
914
|
|
|
break; |
915
|
|
|
|
916
|
|
View Code Duplication |
case 650: |
|
|
|
|
917
|
|
|
$tmp = $this->parseSubjectAddedEntry($node); |
918
|
|
|
|
919
|
|
|
$emne = $node->text('marc:subfield[@code="a"]'); |
920
|
|
|
$tmp['term'] = trim($emne, '.') . $tmp['term']; |
921
|
|
|
$tmp['type'] = 'topic'; |
922
|
|
|
|
923
|
|
|
array_push($subjects, $tmp); |
924
|
|
|
break; |
925
|
|
|
|
926
|
|
View Code Duplication |
case 651: |
|
|
|
|
927
|
|
|
$tmp = $this->parseSubjectAddedEntry($node); |
928
|
|
|
|
929
|
|
|
$emne = $node->text('marc:subfield[@code="a"]'); |
930
|
|
|
$tmp['type'] = 'geographic'; |
931
|
|
|
$tmp['term'] = trim($emne, '.') . $tmp['term']; |
932
|
|
|
|
933
|
|
|
array_push($subjects, $tmp); |
934
|
|
|
break; |
935
|
|
|
|
936
|
|
|
case 653: |
937
|
|
|
$tmp = array('type' => null, 'vocabulary' => null); |
938
|
|
|
|
939
|
|
|
$ind2 = $node->attr('ind2'); |
940
|
|
|
$types = array( |
941
|
|
|
'0' => 'topic', |
942
|
|
|
'1' => 'person', |
943
|
|
|
'2' => 'corporate', |
944
|
|
|
'3' => 'meeting', |
945
|
|
|
'4' => 'chronologic', |
946
|
|
|
'5' => 'geographic', |
947
|
|
|
'6' => 'genre', |
948
|
|
|
); |
949
|
|
|
if (isset($types[$ind2])) { |
950
|
|
|
$tmp['type'] = $types[$ind2]; |
951
|
|
|
} |
952
|
|
|
|
953
|
|
|
foreach ($node->all('marc:subfield[@code="a"]') as $emne) { |
954
|
|
|
$tmp['term'] = trim($emne, '.'); |
955
|
|
|
if ($tmp['type'] == 'genre') { |
956
|
|
|
unset($tmp['type']); |
957
|
|
|
array_push($genres, $tmp); |
958
|
|
|
} else { |
959
|
|
|
array_push($subjects, $tmp); |
960
|
|
|
} |
961
|
|
|
} |
962
|
|
|
|
963
|
|
|
break; |
964
|
|
|
|
965
|
|
|
case 655: |
966
|
|
|
|
967
|
|
|
$tmp = $this->parseSubjectAddedEntry($node); |
968
|
|
|
$tmp['term'] = trim($node->text('marc:subfield[@code="a"]'), '.') . $tmp['term']; |
969
|
|
|
|
970
|
|
|
array_push($genres, $tmp); |
971
|
|
|
break; |
972
|
|
|
|
973
|
|
|
case 700: |
974
|
|
|
$author = array( |
975
|
|
|
'name' => $node->text('marc:subfield[@code="a"]'), |
976
|
|
|
); |
977
|
|
|
$author['normalizedName'] = $author['name']; |
978
|
|
|
$spl = explode(', ', $author['name']); |
979
|
|
View Code Duplication |
if (count($spl) == 2) { |
|
|
|
|
980
|
|
|
$author['name'] = $spl[1] . ' ' . $spl[0]; |
981
|
|
|
} |
982
|
|
|
|
983
|
|
|
$this->parseRelator($node, $author, 'added'); |
984
|
|
|
$this->parseAuthority($node->text('marc:subfield[@code="0"]'), $author); |
985
|
|
|
|
986
|
|
|
$dates = $node->text('marc:subfield[@code="d"]'); |
987
|
|
|
if (!empty($dates)) { |
988
|
|
|
$author['dates'] = $dates; |
989
|
|
|
} |
990
|
|
|
|
991
|
|
|
$creators[] = $author; |
992
|
|
|
break; |
993
|
|
|
|
994
|
|
View Code Duplication |
case 710: |
|
|
|
|
995
|
|
|
$author = array( |
996
|
|
|
'name' => $node->text('marc:subfield[@code="a"]'), |
997
|
|
|
); |
998
|
|
|
$author['normalizedName'] = $author['name']; |
999
|
|
|
|
1000
|
|
|
$this->parseRelator($node, $author, 'added_corporate'); |
1001
|
|
|
$this->parseAuthority($node->text('marc:subfield[@code="0"]'), $author); |
1002
|
|
|
|
1003
|
|
|
$creators[] = $author; |
1004
|
|
|
break; |
1005
|
|
|
|
1006
|
|
|
// 773 : Host Item Entry (R) |
1007
|
|
|
// See also: 580 |
1008
|
|
|
case 773: |
1009
|
|
|
$part_of = isset($part_of) ? $part_of : array(); |
1010
|
|
|
$part_of['relationship'] = $node->text('marc:subfield[@code="i"]'); |
1011
|
|
|
$part_of['title'] = $node->text('marc:subfield[@code="t"]'); |
1012
|
|
|
$part_of['issn'] = $node->text('marc:subfield[@code="x"]') ?: null; |
1013
|
|
|
$part_of['isbn'] = $node->text('marc:subfield[@code="z"]') ?: null; |
1014
|
|
|
$part_of['volume'] = $node->text('marc:subfield[@code="v"]') ?: null; |
1015
|
|
|
$this->parseAuthority($node->text('marc:subfield[@code="w"]'), $part_of); |
1016
|
|
|
|
1017
|
|
|
break; |
1018
|
|
|
|
1019
|
|
|
// 776 : Additional Physical Form Entry (R) |
1020
|
|
|
case 776: |
1021
|
|
|
// <marc:datafield tag="776" ind1="0" ind2=" "> |
1022
|
|
|
// <marc:subfield code="z">9781107602175</marc:subfield> |
1023
|
|
|
// <marc:subfield code="w">(NO-TrBIB)132191512</marc:subfield> |
1024
|
|
|
// </marc:datafield> |
1025
|
|
|
$other_form = $this->parseRelationship($node); |
1026
|
|
|
break; |
1027
|
|
|
|
1028
|
|
|
// 780 : Preceding Entry (R) |
1029
|
|
|
// Information concerning the immediate predecessor of the target item |
1030
|
|
|
case 780: |
1031
|
|
|
// <marc:datafield tag="780" ind1="0" ind2="0"> |
1032
|
|
|
// <marc:subfield code="w">(NO-TrBIB)920713874</marc:subfield> |
1033
|
|
|
// <marc:subfield code="g">nr 80(1961)</marc:subfield> |
1034
|
|
|
// </marc:datafield> |
1035
|
|
|
|
1036
|
|
|
if (!isset($preceding['items'])) { |
1037
|
|
|
$preceding['items'] = array(); |
1038
|
|
|
} |
1039
|
|
|
$preceding['items'][] = $this->parseRelationship($node); |
1040
|
|
|
|
1041
|
|
|
$ind2 = $node->attr('ind2'); |
1042
|
|
|
$relationship_types = array( |
1043
|
|
|
'0' => 'Continues', |
1044
|
|
|
'1' => 'Continues in part', |
1045
|
|
|
'2' => 'Supersedes', |
1046
|
|
|
'3' => 'Supersedes in part', |
1047
|
|
|
'4' => 'Formed by the union of', // ... and ...', |
1048
|
|
|
'5' => 'Absorbed', |
1049
|
|
|
'6' => 'Absorbed in part', |
1050
|
|
|
'7' => 'Separated from', |
1051
|
|
|
); |
1052
|
|
|
if (isset($relationship_types[$ind2])) { |
1053
|
|
|
$preceding['relationship_type'] = $relationship_types[$ind2]; |
1054
|
|
|
} |
1055
|
|
|
|
1056
|
|
|
break; |
1057
|
|
|
|
1058
|
|
|
// 785 : Succeeding Entry (R) |
1059
|
|
|
// Information concerning the immediate successor to the target item |
1060
|
|
|
case 785: |
1061
|
|
|
// <marc:datafield tag="785" ind1="0" ind2="0"> |
1062
|
|
|
// <marc:subfield code="w">(NO-TrBIB)920713874</marc:subfield> |
1063
|
|
|
// <marc:subfield code="g">nr 80(1961)</marc:subfield> |
1064
|
|
|
// </marc:datafield> |
1065
|
|
|
|
1066
|
|
|
if (!isset($succeeding['items'])) { |
1067
|
|
|
$succeeding['items'] = array(); |
1068
|
|
|
} |
1069
|
|
|
$succeeding['items'][] = $this->parseRelationship($node); |
1070
|
|
|
|
1071
|
|
|
$ind2 = $node->attr('ind2'); |
1072
|
|
|
$relationship_types = array( |
1073
|
|
|
'0' => 'Continued by', |
1074
|
|
|
'1' => 'Continued in part by', |
1075
|
|
|
'2' => 'Superseded by', |
1076
|
|
|
'3' => 'Superseded in part by', |
1077
|
|
|
'4' => 'Absorbed by', |
1078
|
|
|
'5' => 'Absorbed in part by', |
1079
|
|
|
'6' => 'Split into', // ... and ...', |
1080
|
|
|
'7' => 'Continued by', // more precisely 'Merged with ... to form ...', but we simplify slightly |
1081
|
|
|
'8' => 'Changed back to', |
1082
|
|
|
); |
1083
|
|
|
|
1084
|
|
|
if ($ind2 == '7') { |
1085
|
|
|
// The first elements are the documents that go into the merge, |
1086
|
|
|
// we are not interested in those due to our slight simplification. |
1087
|
|
|
$succeeding['items'] = array(array_pop($succeeding['items'])); |
1088
|
|
|
} |
1089
|
|
|
|
1090
|
|
|
if (isset($relationship_types[$ind2])) { |
1091
|
|
|
$succeeding['relationship_type'] = $relationship_types[$ind2]; |
1092
|
|
|
} |
1093
|
|
|
break; |
1094
|
|
|
|
1095
|
|
|
// 830 : Series Added Entry – Uniform Title (R) |
1096
|
|
|
case 830: |
1097
|
|
|
$serie = array( |
1098
|
|
|
'title' => $node->text('marc:subfield[@code="a"]'), |
1099
|
|
|
'id' => preg_replace('/\(NO-TrBIB\)/', '', $node->text('marc:subfield[@code="w"]')) ?: null, |
1100
|
|
|
'volume' => $node->text('marc:subfield[@code="v"]') ?: null, |
1101
|
|
|
); |
1102
|
|
|
$series[] = $serie; |
1103
|
|
|
break; |
1104
|
|
|
|
1105
|
|
|
case 856: |
1106
|
|
|
case 956: |
1107
|
|
|
# MARC 21 uses field 856 for electronic "links", where you can have URLs for example covers images and/or blurbs. |
1108
|
|
|
# 956 ? |
1109
|
|
|
|
1110
|
|
|
// <marc:datafield tag="856" ind1="4" ind2="2"> |
1111
|
|
|
// <marc:subfield code="3">Beskrivelse fra forlaget (kort)</marc:subfield> |
1112
|
|
|
// <marc:subfield code="u">http://content.bibsys.no/content/?type=descr_publ_brief&isbn=0521176832</marc:subfield> |
1113
|
|
|
// </marc:datafield> |
1114
|
|
|
// <marc:datafield tag="956" ind1="4" ind2="2"> |
1115
|
|
|
// <marc:subfield code="3">Omslagsbilde</marc:subfield> |
1116
|
|
|
// <marc:subfield code="u">http://innhold.bibsys.no/bilde/forside/?size=mini&id=9780521176835.jpg</marc:subfield> |
1117
|
|
|
// <marc:subfield code="q">image/jpeg</marc:subfield> |
1118
|
|
|
// </marc:datafield> |
1119
|
|
|
$description = $node->text('marc:subfield[@code="3"]'); |
1120
|
|
|
if (in_array($description, array('Cover image', 'Omslagsbilde'))) { |
1121
|
|
|
$this->cover_image = $node->text('marc:subfield[@code="u"]'); |
1122
|
|
|
|
1123
|
|
|
// Silly hack to get larger images from Bibsys: |
1124
|
|
|
$this->cover_image = str_replace('mini', 'stor', $this->cover_image); |
1125
|
|
|
$this->cover_image = str_replace('LITE', 'STOR', $this->cover_image); |
1126
|
|
|
} |
1127
|
|
|
if (in_array($description, array('Beskrivelse fra forlaget (kort)', 'Beskrivelse fra forlaget (lang)'))) { |
1128
|
|
|
$this->description = $node->text('marc:subfield[@code="u"]'); |
1129
|
|
|
} |
1130
|
|
|
break; |
1131
|
|
|
|
1132
|
|
|
// 991 Kriterium für Sekundärsortierung (R) ??? |
1133
|
|
|
// Ref: http://ead.nb.admin.ch/web/marc21/dmarcb991.pdf |
1134
|
|
|
// Hvor i BIBSYSMARC kommer dette fra? |
1135
|
|
|
case 991: |
1136
|
|
|
|
1137
|
|
|
// Multi-volume work (flerbindsverk), parts linked through 773 w |
1138
|
|
|
if ($node->text('marc:subfield[@code="a"]') == 'volumes') { |
1139
|
|
|
$this->is_multivolume = true; |
1140
|
|
|
} |
1141
|
|
|
|
1142
|
|
|
// Series (serier), parts linked through 830 w |
1143
|
|
|
if ($node->text('marc:subfield[@code="a"]') == 'parts') { |
1144
|
|
|
$this->is_series = true; |
1145
|
|
|
} |
1146
|
|
|
|
1147
|
|
|
break; |
1148
|
|
|
|
1149
|
|
|
} |
1150
|
|
|
} |
1151
|
|
|
|
1152
|
|
|
if (!empty($preceding)) { |
1153
|
|
|
$this->preceding = $preceding; |
1154
|
|
|
} |
1155
|
|
|
if (!empty($succeeding)) { |
1156
|
|
|
$this->succeeding = $succeeding; |
1157
|
|
|
} |
1158
|
|
|
if (count($part_of)) { |
1159
|
|
|
$this->part_of = $part_of; |
1160
|
|
|
} |
1161
|
|
|
if (!empty($other_form)) { |
1162
|
|
|
$this->other_form = $other_form; |
1163
|
|
|
} |
1164
|
|
|
|
1165
|
|
|
$this->alternativeTitles = array_unique($alternativeTitles); |
1166
|
|
|
$this->isbns = $isbns; |
1167
|
|
|
$this->issns = $issns; |
1168
|
|
|
$this->series = $series; |
1169
|
|
|
$this->creators = $creators; |
1170
|
|
|
$this->meetings = $meetings; |
1171
|
|
|
$this->subjects = $subjects; |
1172
|
|
|
$this->genres = $genres; |
1173
|
|
|
$this->classifications = $classifications; |
1174
|
|
|
$this->notes = $notes; |
1175
|
|
|
} |
1176
|
|
|
} |
1177
|
|
|
|
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVar
assignment in line 1 and the$higher
assignment in line 2 are dead. The first because$myVar
is never used and the second because$higher
is always overwritten for every possible time line.