]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/sql/Pg/version-upgrade/3.8.0-3.9.0-upgrade-db.sql
LP2061136 - Stamping 1405 DB upgrade script
[Evergreen.git] / Open-ILS / src / sql / Pg / version-upgrade / 3.8.0-3.9.0-upgrade-db.sql
1 --Upgrade Script for 3.8.0 to 3.9.0
2 \set eg_version '''3.9.0'''
3 BEGIN;
4 INSERT INTO config.upgrade_log (version, applied_to) VALUES ('3.9.0', :eg_version);
5
6 SELECT evergreen.upgrade_deps_block_check('1307', :eg_version);
7
8 DROP FUNCTION search.query_parser_fts (
9     INT,
10     INT,
11     TEXT,
12     INT[],
13     INT[],
14     INT,
15     INT,
16     INT,
17     BOOL,
18     BOOL,
19     BOOL,
20     INT 
21 );
22
23 DROP TABLE asset.opac_visible_copies;
24
25 DROP FUNCTION IF EXISTS asset.refresh_opac_visible_copies_mat_view();
26
27 DROP TYPE search.search_result;
28 DROP TYPE search.search_args;
29
30
31 SELECT evergreen.upgrade_deps_block_check('1308', :eg_version);
32
33 INSERT INTO config.workstation_setting_type (name, grp, datatype, label)
34 VALUES (
35     'eg.grid.admin.local.triggers.atevdef', 'gui', 'object',
36     oils_i18n_gettext(
37         'eg.grid.admin.local.triggers.atevdef',
38         'Grid Config: eg.grid.admin.local.triggers.atevdef',
39         'cwst', 'label'
40     )
41 ), (
42     'eg.grid.admin.local.triggers.atenv', 'gui', 'object',
43     oils_i18n_gettext(
44         'eg.grid.admin.local.triggers.atenv',
45         'Grid Config: eg.grid.admin.local.triggers.atenv',
46         'cwst', 'label'
47     )
48 ), (
49     'eg.grid.admin.local.triggers.atevparam', 'gui', 'object',
50     oils_i18n_gettext(
51         'eg.grid.admin.local.triggers.atevparam',
52         'Grid Config: eg.grid.admin.local.triggers.atevparam',
53         'cwst', 'label'
54     )
55 );
56
57
58 SELECT evergreen.upgrade_deps_block_check('1309', :eg_version);
59
60 ALTER TABLE asset.course_module_term
61         DROP CONSTRAINT course_module_term_name_key;
62
63 ALTER TABLE asset.course_module_term
64         ADD CONSTRAINT cmt_once_per_owning_lib UNIQUE (owning_lib, name);
65
66
67 SELECT evergreen.upgrade_deps_block_check('1311', :eg_version);
68
69 CREATE OR REPLACE FUNCTION biblio.extract_located_uris( bib_id BIGINT, marcxml TEXT, editor_id INT ) RETURNS VOID AS $func$
70 DECLARE
71     uris            TEXT[];
72     uri_xml         TEXT;
73     uri_label       TEXT;
74     uri_href        TEXT;
75     uri_use         TEXT;
76     uri_owner_list  TEXT[];
77     uri_owner       TEXT;
78     uri_owner_id    INT;
79     uri_id          INT;
80     uri_cn_id       INT;
81     uri_map_id      INT;
82     current_uri     INT;
83     current_map     INT;
84     uri_map_count   INT;
85     current_uri_map_list    INT[];
86     current_map_owner_list  INT[];
87
88 BEGIN
89
90     uris := oils_xpath('//*[@tag="856" and (@ind1="4" or @ind1="1") and (@ind2="0" or @ind2="1")]',marcxml);
91     IF ARRAY_UPPER(uris,1) > 0 THEN
92         FOR i IN 1 .. ARRAY_UPPER(uris, 1) LOOP
93             -- First we pull info out of the 856
94             uri_xml     := uris[i];
95
96             uri_href    := (oils_xpath('//*[@code="u"]/text()',uri_xml))[1];
97             uri_label   := (oils_xpath('//*[@code="y"]/text()|//*[@code="3"]/text()',uri_xml))[1];
98             uri_use     := (oils_xpath('//*[@code="z"]/text()|//*[@code="2"]/text()|//*[@code="n"]/text()',uri_xml))[1];
99
100             IF uri_label IS NULL THEN
101                 uri_label := uri_href;
102             END IF;
103             CONTINUE WHEN uri_href IS NULL;
104
105             -- Get the distinct list of libraries wanting to use 
106             SELECT  ARRAY_AGG(
107                         DISTINCT REGEXP_REPLACE(
108                             x,
109                             $re$^.*?\((\w+)\).*$$re$,
110                             E'\\1'
111                         )
112                     ) INTO uri_owner_list
113               FROM  UNNEST(
114                         oils_xpath(
115                             '//*[@code="9"]/text()|//*[@code="w"]/text()|//*[@code="n"]/text()',
116                             uri_xml
117                         )
118                     )x;
119
120             IF ARRAY_UPPER(uri_owner_list,1) > 0 THEN
121
122                 -- look for a matching uri
123                 IF uri_use IS NULL THEN
124                     SELECT id INTO uri_id
125                         FROM asset.uri
126                         WHERE label = uri_label AND href = uri_href AND use_restriction IS NULL AND active
127                         ORDER BY id LIMIT 1;
128                     IF NOT FOUND THEN -- create one
129                         INSERT INTO asset.uri (label, href, use_restriction) VALUES (uri_label, uri_href, uri_use);
130                         SELECT id INTO uri_id
131                             FROM asset.uri
132                             WHERE label = uri_label AND href = uri_href AND use_restriction IS NULL AND active;
133                     END IF;
134                 ELSE
135                     SELECT id INTO uri_id
136                         FROM asset.uri
137                         WHERE label = uri_label AND href = uri_href AND use_restriction = uri_use AND active
138                         ORDER BY id LIMIT 1;
139                     IF NOT FOUND THEN -- create one
140                         INSERT INTO asset.uri (label, href, use_restriction) VALUES (uri_label, uri_href, uri_use);
141                         SELECT id INTO uri_id
142                             FROM asset.uri
143                             WHERE label = uri_label AND href = uri_href AND use_restriction = uri_use AND active;
144                     END IF;
145                 END IF;
146
147                 FOR j IN 1 .. ARRAY_UPPER(uri_owner_list, 1) LOOP
148                     uri_owner := uri_owner_list[j];
149
150                     SELECT id INTO uri_owner_id FROM actor.org_unit WHERE shortname = BTRIM(REPLACE(uri_owner,chr(160),''));
151                     CONTINUE WHEN NOT FOUND;
152
153                     -- we need a call number to link through
154                     SELECT id INTO uri_cn_id FROM asset.call_number WHERE owning_lib = uri_owner_id AND record = bib_id AND label = '##URI##' AND NOT deleted;
155                     IF NOT FOUND THEN
156                         INSERT INTO asset.call_number (owning_lib, record, create_date, edit_date, creator, editor, label)
157                             VALUES (uri_owner_id, bib_id, 'now', 'now', editor_id, editor_id, '##URI##');
158                         SELECT id INTO uri_cn_id FROM asset.call_number WHERE owning_lib = uri_owner_id AND record = bib_id AND label = '##URI##' AND NOT deleted;
159                     END IF;
160
161                     -- now, link them if they're not already
162                     SELECT id INTO uri_map_id FROM asset.uri_call_number_map WHERE call_number = uri_cn_id AND uri = uri_id;
163                     IF NOT FOUND THEN
164                         INSERT INTO asset.uri_call_number_map (call_number, uri) VALUES (uri_cn_id, uri_id);
165                         SELECT id INTO uri_map_id FROM asset.uri_call_number_map WHERE call_number = uri_cn_id AND uri = uri_id;
166                     END IF;
167
168                     current_uri_map_list := current_uri_map_list || uri_map_id;
169                     current_map_owner_list := current_map_owner_list || uri_cn_id;
170
171                 END LOOP;
172
173             END IF;
174
175         END LOOP;
176     END IF;
177
178     -- Clear any orphaned URIs, URI mappings and call
179     -- numbers for this bib that weren't mapped above.
180     FOR current_map IN
181         SELECT  m.id
182           FROM  asset.uri_call_number_map m
183                 LEFT JOIN asset.call_number cn ON (cn.id = m.call_number)
184           WHERE cn.record = bib_id
185                 AND cn.label = '##URI##'
186                 AND (NOT (m.id = ANY (current_uri_map_list))
187                      OR current_uri_map_list is NULL)
188     LOOP
189         SELECT uri INTO current_uri FROM asset.uri_call_number_map WHERE id = current_map;
190         DELETE FROM asset.uri_call_number_map WHERE id = current_map;
191
192         SELECT COUNT(*) INTO uri_map_count FROM asset.uri_call_number_map WHERE uri = current_uri;
193         IF uri_map_count = 0 THEN
194             DELETE FROM asset.uri WHERE id = current_uri;
195         END IF;
196     END LOOP;
197
198     UPDATE asset.call_number
199     SET deleted = TRUE, edit_date = now(), editor = editor_id
200     WHERE id IN (
201         SELECT  id
202           FROM  asset.call_number
203           WHERE record = bib_id
204                 AND label = '##URI##'
205                 AND NOT deleted
206                 AND (NOT (id = ANY (current_map_owner_list))
207                      OR current_map_owner_list is NULL)
208     );
209
210     RETURN;
211 END;
212 $func$ LANGUAGE PLPGSQL;
213
214 -- Remove existing orphaned URIs from the database.
215 DELETE FROM asset.uri
216 WHERE id IN
217 (
218 SELECT uri.id
219 FROM asset.uri
220 LEFT JOIN asset.uri_call_number_map
221 ON uri_call_number_map.uri = uri.id
222 LEFT JOIN serial.item
223 ON item.uri = uri.id
224 WHERE uri_call_number_map IS NULL
225 AND item IS NULL
226 );
227
228
229
230 SELECT evergreen.upgrade_deps_block_check('1312', :eg_version);
231
232 CREATE INDEX aum_editor ON actor.usr_message (editor);
233
234
235 SELECT evergreen.upgrade_deps_block_check('1313', :eg_version); -- alynn26
236
237 INSERT INTO config.workstation_setting_type (name, grp, datatype, label)
238 VALUES (
239     'eg.grid.cat.bucket.batch_hold.view', 'gui', 'object',
240     oils_i18n_gettext(
241         'eg.grid.cat.bucket.batch_hold.view',
242         'Grid Config: eg.grid.cat.bucket.batch_hold.view',
243         'cwst', 'label'
244     )
245 ), (
246     'eg.grid.cat.bucket.batch_hold.pending', 'gui', 'object',
247     oils_i18n_gettext(
248         'eg.grid.cat.bucket.batch_hold.pending',
249         'Grid Config: eg.grid.cat.bucket.batch_hold.pending',
250         'cwst', 'label'
251     )
252 ), (
253     'eg.grid.cat.bucket.batch_hold.events', 'gui', 'object',
254     oils_i18n_gettext(
255         'eg.grid.cat.bucket.batch_hold.events',
256         'Grid Config: eg.grid.cat.bucket.batch_hold.events',
257         'cwst', 'label'
258     )
259 ), (
260     'eg.grid.cat.bucket.batch_hold.list', 'gui', 'object',
261     oils_i18n_gettext(
262         'eg.grid.cat.bucket.batch_hold.list',
263         'Grid Config: eg.grid.cat.bucket.batch_hold.list',
264         'cwst', 'label'
265     )
266 );
267
268
269 SELECT evergreen.upgrade_deps_block_check('1314', :eg_version);
270
271 CREATE OR REPLACE FUNCTION authority.generate_overlay_template (source_xml TEXT) RETURNS TEXT AS $f$
272 DECLARE
273     cset                INT;
274     main_entry          authority.control_set_authority_field%ROWTYPE;
275     bib_field           authority.control_set_bib_field%ROWTYPE;
276     auth_id             INT DEFAULT oils_xpath_string('//*[@tag="901"]/*[local-name()="subfield" and @code="c"]', source_xml)::INT;
277     tmp_data            XML;
278     replace_data        XML[] DEFAULT '{}'::XML[];
279     replace_rules       TEXT[] DEFAULT '{}'::TEXT[];
280     auth_field          XML[];
281     auth_i1             TEXT;
282     auth_i2             TEXT;
283 BEGIN
284     IF auth_id IS NULL THEN
285         RETURN NULL;
286     END IF;
287
288     -- Default to the LoC controll set
289     SELECT control_set INTO cset FROM authority.record_entry WHERE id = auth_id;
290
291     -- if none, make a best guess
292     IF cset IS NULL THEN
293         SELECT  control_set INTO cset
294           FROM  authority.control_set_authority_field
295           WHERE tag IN (
296                     SELECT  UNNEST(XPATH('//*[local-name()="datafield" and starts-with(@tag,"1")]/@tag',marc::XML)::TEXT[])
297                       FROM  authority.record_entry
298                       WHERE id = auth_id
299                 )
300           LIMIT 1;
301     END IF;
302
303     -- if STILL none, no-op change
304     IF cset IS NULL THEN
305         RETURN XMLELEMENT(
306             name record,
307             XMLATTRIBUTES('http://www.loc.gov/MARC21/slim' AS xmlns),
308             XMLELEMENT( name leader, '00881nam a2200193   4500'),
309             XMLELEMENT(
310                 name datafield,
311                 XMLATTRIBUTES( '905' AS tag, ' ' AS ind1, ' ' AS ind2),
312                 XMLELEMENT(
313                     name subfield,
314                     XMLATTRIBUTES('d' AS code),
315                     '901c'
316                 )
317             )
318         )::TEXT;
319     END IF;
320
321     FOR main_entry IN SELECT * FROM authority.control_set_authority_field acsaf WHERE acsaf.control_set = cset AND acsaf.main_entry IS NULL LOOP
322         auth_field := XPATH('//*[local-name()="datafield" and @tag="'||main_entry.tag||'"][1]',source_xml::XML);
323         auth_i1 := (XPATH('//*[local-name()="datafield"]/@ind1',auth_field[1]))[1];
324         auth_i2 := (XPATH('//*[local-name()="datafield"]/@ind2',auth_field[1]))[1];
325         IF ARRAY_LENGTH(auth_field,1) > 0 THEN
326             FOR bib_field IN SELECT * FROM authority.control_set_bib_field WHERE authority_field = main_entry.id LOOP
327                 SELECT XMLELEMENT( -- XMLAGG avoids magical <element> creation, but requires unnest subquery
328                     name datafield,
329                     XMLATTRIBUTES(bib_field.tag AS tag, auth_i1 AS ind1, auth_i2 AS ind2),
330                     XMLAGG(UNNEST)
331                 ) INTO tmp_data FROM UNNEST(XPATH('//*[local-name()="subfield"]', auth_field[1]));
332                 replace_data := replace_data || tmp_data;
333                 replace_rules := replace_rules || ( bib_field.tag || main_entry.sf_list || E'[0~\\)' || auth_id || '$]' );
334                 tmp_data = NULL;
335             END LOOP;
336             EXIT;
337         END IF;
338     END LOOP;
339
340     SELECT XMLAGG(UNNEST) INTO tmp_data FROM UNNEST(replace_data);
341
342     RETURN XMLELEMENT(
343         name record,
344         XMLATTRIBUTES('http://www.loc.gov/MARC21/slim' AS xmlns),
345         XMLELEMENT( name leader, '00881nam a2200193   4500'),
346         tmp_data,
347         XMLELEMENT(
348             name datafield,
349             XMLATTRIBUTES( '905' AS tag, ' ' AS ind1, ' ' AS ind2),
350             XMLELEMENT(
351                 name subfield,
352                 XMLATTRIBUTES('r' AS code),
353                 ARRAY_TO_STRING(replace_rules,',')
354             )
355         )
356     )::TEXT;
357 END;
358 $f$ STABLE LANGUAGE PLPGSQL;
359
360 CREATE OR REPLACE FUNCTION authority.normalize_heading( marcxml TEXT, no_thesaurus BOOL ) RETURNS TEXT AS $func$
361 DECLARE
362     acsaf           authority.control_set_authority_field%ROWTYPE;
363     tag_used        TEXT;
364     nfi_used        TEXT;
365     sf              TEXT;
366     sf_node         TEXT;
367     tag_node        TEXT;
368     thes_code       TEXT;
369     cset            INT;
370     heading_text    TEXT;
371     tmp_text        TEXT;
372     first_sf        BOOL;
373     auth_id         INT DEFAULT COALESCE(NULLIF(oils_xpath_string('//*[@tag="901"]/*[local-name()="subfield" and @code="c"]', marcxml), ''), '0')::INT;
374 BEGIN
375     SELECT control_set INTO cset FROM authority.record_entry WHERE id = auth_id;
376
377     IF cset IS NULL THEN
378         SELECT  control_set INTO cset
379           FROM  authority.control_set_authority_field
380           WHERE tag IN (SELECT UNNEST(XPATH('//*[starts-with(@tag,"1")]/@tag',marcxml::XML)::TEXT[]))
381           LIMIT 1;
382     END IF;
383
384     heading_text := '';
385     FOR acsaf IN SELECT * FROM authority.control_set_authority_field WHERE control_set = cset AND main_entry IS NULL LOOP
386         tag_used := acsaf.tag;
387         nfi_used := acsaf.nfi;
388         first_sf := TRUE;
389
390         FOR tag_node IN SELECT unnest(oils_xpath('//*[@tag="'||tag_used||'"]',marcxml))
391         LOOP
392             FOR sf_node IN SELECT unnest(oils_xpath('//*[local-name() = "subfield" and contains("'||acsaf.sf_list||'",@code)]',tag_node))
393             LOOP
394
395                 tmp_text := oils_xpath_string('.', sf_node);
396                 sf := oils_xpath_string('//*/@code', sf_node);
397
398                 IF first_sf AND tmp_text IS NOT NULL AND nfi_used IS NOT NULL THEN
399
400                     tmp_text := SUBSTRING(
401                         tmp_text FROM
402                         COALESCE(
403                             NULLIF(
404                                 REGEXP_REPLACE(
405                                     oils_xpath_string('//*[local-name() = "datafield"]/@ind'||nfi_used, tag_node),
406                                     $$\D+$$,
407                                     '',
408                                     'g'
409                                 ),
410                                 ''
411                             )::INT,
412                             0
413                         ) + 1
414                     );
415
416                 END IF;
417
418                 first_sf := FALSE;
419
420                 IF tmp_text IS NOT NULL AND tmp_text <> '' THEN
421                     heading_text := heading_text || E'\u2021' || sf || ' ' || tmp_text;
422                 END IF;
423             END LOOP;
424
425             EXIT WHEN heading_text <> '';
426         END LOOP;
427
428         EXIT WHEN heading_text <> '';
429     END LOOP;
430
431     IF heading_text <> '' THEN
432         IF no_thesaurus IS TRUE THEN
433             heading_text := tag_used || ' ' || public.naco_normalize(heading_text);
434         ELSE
435             thes_code := authority.extract_thesaurus(marcxml);
436             heading_text := tag_used || '_' || COALESCE(nfi_used,'-') || '_' || thes_code || ' ' || public.naco_normalize(heading_text);
437         END IF;
438     ELSE
439         heading_text := 'NOHEADING_' || thes_code || ' ' || MD5(marcxml);
440     END IF;
441
442     RETURN heading_text;
443 END;
444 $func$ LANGUAGE PLPGSQL STABLE STRICT;
445
446 CREATE OR REPLACE FUNCTION vandelay.ingest_items ( import_id BIGINT, attr_def_id BIGINT ) RETURNS SETOF vandelay.import_item AS $$
447 DECLARE
448
449     owning_lib      TEXT;
450     circ_lib        TEXT;
451     call_number     TEXT;
452     copy_number     TEXT;
453     status          TEXT;
454     location        TEXT;
455     circulate       TEXT;
456     deposit         TEXT;
457     deposit_amount  TEXT;
458     ref             TEXT;
459     holdable        TEXT;
460     price           TEXT;
461     barcode         TEXT;
462     circ_modifier   TEXT;
463     circ_as_type    TEXT;
464     alert_message   TEXT;
465     opac_visible    TEXT;
466     pub_note        TEXT;
467     priv_note       TEXT;
468     internal_id     TEXT;
469     stat_cat_data   TEXT;
470     parts_data      TEXT;
471
472     attr_def        RECORD;
473     tmp_attr_set    RECORD;
474     attr_set        vandelay.import_item%ROWTYPE;
475
476     xpaths          TEXT[];
477     tmp_str         TEXT;
478
479 BEGIN
480
481     SELECT * INTO attr_def FROM vandelay.import_item_attr_definition WHERE id = attr_def_id;
482
483     IF FOUND THEN
484
485         attr_set.definition := attr_def.id;
486
487         -- Build the combined XPath
488
489         owning_lib :=
490             CASE
491                 WHEN attr_def.owning_lib IS NULL THEN 'null()'
492                 WHEN LENGTH( attr_def.owning_lib ) = 1 THEN '//*[@code="' || attr_def.owning_lib || '"]'
493                 ELSE '//*' || attr_def.owning_lib
494             END;
495
496         circ_lib :=
497             CASE
498                 WHEN attr_def.circ_lib IS NULL THEN 'null()'
499                 WHEN LENGTH( attr_def.circ_lib ) = 1 THEN '//*[@code="' || attr_def.circ_lib || '"]'
500                 ELSE '//*' || attr_def.circ_lib
501             END;
502
503         call_number :=
504             CASE
505                 WHEN attr_def.call_number IS NULL THEN 'null()'
506                 WHEN LENGTH( attr_def.call_number ) = 1 THEN '//*[@code="' || attr_def.call_number || '"]'
507                 ELSE '//*' || attr_def.call_number
508             END;
509
510         copy_number :=
511             CASE
512                 WHEN attr_def.copy_number IS NULL THEN 'null()'
513                 WHEN LENGTH( attr_def.copy_number ) = 1 THEN '//*[@code="' || attr_def.copy_number || '"]'
514                 ELSE '//*' || attr_def.copy_number
515             END;
516
517         status :=
518             CASE
519                 WHEN attr_def.status IS NULL THEN 'null()'
520                 WHEN LENGTH( attr_def.status ) = 1 THEN '//*[@code="' || attr_def.status || '"]'
521                 ELSE '//*' || attr_def.status
522             END;
523
524         location :=
525             CASE
526                 WHEN attr_def.location IS NULL THEN 'null()'
527                 WHEN LENGTH( attr_def.location ) = 1 THEN '//*[@code="' || attr_def.location || '"]'
528                 ELSE '//*' || attr_def.location
529             END;
530
531         circulate :=
532             CASE
533                 WHEN attr_def.circulate IS NULL THEN 'null()'
534                 WHEN LENGTH( attr_def.circulate ) = 1 THEN '//*[@code="' || attr_def.circulate || '"]'
535                 ELSE '//*' || attr_def.circulate
536             END;
537
538         deposit :=
539             CASE
540                 WHEN attr_def.deposit IS NULL THEN 'null()'
541                 WHEN LENGTH( attr_def.deposit ) = 1 THEN '//*[@code="' || attr_def.deposit || '"]'
542                 ELSE '//*' || attr_def.deposit
543             END;
544
545         deposit_amount :=
546             CASE
547                 WHEN attr_def.deposit_amount IS NULL THEN 'null()'
548                 WHEN LENGTH( attr_def.deposit_amount ) = 1 THEN '//*[@code="' || attr_def.deposit_amount || '"]'
549                 ELSE '//*' || attr_def.deposit_amount
550             END;
551
552         ref :=
553             CASE
554                 WHEN attr_def.ref IS NULL THEN 'null()'
555                 WHEN LENGTH( attr_def.ref ) = 1 THEN '//*[@code="' || attr_def.ref || '"]'
556                 ELSE '//*' || attr_def.ref
557             END;
558
559         holdable :=
560             CASE
561                 WHEN attr_def.holdable IS NULL THEN 'null()'
562                 WHEN LENGTH( attr_def.holdable ) = 1 THEN '//*[@code="' || attr_def.holdable || '"]'
563                 ELSE '//*' || attr_def.holdable
564             END;
565
566         price :=
567             CASE
568                 WHEN attr_def.price IS NULL THEN 'null()'
569                 WHEN LENGTH( attr_def.price ) = 1 THEN '//*[@code="' || attr_def.price || '"]'
570                 ELSE '//*' || attr_def.price
571             END;
572
573         barcode :=
574             CASE
575                 WHEN attr_def.barcode IS NULL THEN 'null()'
576                 WHEN LENGTH( attr_def.barcode ) = 1 THEN '//*[@code="' || attr_def.barcode || '"]'
577                 ELSE '//*' || attr_def.barcode
578             END;
579
580         circ_modifier :=
581             CASE
582                 WHEN attr_def.circ_modifier IS NULL THEN 'null()'
583                 WHEN LENGTH( attr_def.circ_modifier ) = 1 THEN '//*[@code="' || attr_def.circ_modifier || '"]'
584                 ELSE '//*' || attr_def.circ_modifier
585             END;
586
587         circ_as_type :=
588             CASE
589                 WHEN attr_def.circ_as_type IS NULL THEN 'null()'
590                 WHEN LENGTH( attr_def.circ_as_type ) = 1 THEN '//*[@code="' || attr_def.circ_as_type || '"]'
591                 ELSE '//*' || attr_def.circ_as_type
592             END;
593
594         alert_message :=
595             CASE
596                 WHEN attr_def.alert_message IS NULL THEN 'null()'
597                 WHEN LENGTH( attr_def.alert_message ) = 1 THEN '//*[@code="' || attr_def.alert_message || '"]'
598                 ELSE '//*' || attr_def.alert_message
599             END;
600
601         opac_visible :=
602             CASE
603                 WHEN attr_def.opac_visible IS NULL THEN 'null()'
604                 WHEN LENGTH( attr_def.opac_visible ) = 1 THEN '//*[@code="' || attr_def.opac_visible || '"]'
605                 ELSE '//*' || attr_def.opac_visible
606             END;
607
608         pub_note :=
609             CASE
610                 WHEN attr_def.pub_note IS NULL THEN 'null()'
611                 WHEN LENGTH( attr_def.pub_note ) = 1 THEN '//*[@code="' || attr_def.pub_note || '"]'
612                 ELSE '//*' || attr_def.pub_note
613             END;
614         priv_note :=
615             CASE
616                 WHEN attr_def.priv_note IS NULL THEN 'null()'
617                 WHEN LENGTH( attr_def.priv_note ) = 1 THEN '//*[@code="' || attr_def.priv_note || '"]'
618                 ELSE '//*' || attr_def.priv_note
619             END;
620
621         internal_id :=
622             CASE
623                 WHEN attr_def.internal_id IS NULL THEN 'null()'
624                 WHEN LENGTH( attr_def.internal_id ) = 1 THEN '//*[@code="' || attr_def.internal_id || '"]'
625                 ELSE '//*' || attr_def.internal_id
626             END;
627
628         stat_cat_data :=
629             CASE
630                 WHEN attr_def.stat_cat_data IS NULL THEN 'null()'
631                 WHEN LENGTH( attr_def.stat_cat_data ) = 1 THEN '//*[@code="' || attr_def.stat_cat_data || '"]'
632                 ELSE '//*' || attr_def.stat_cat_data
633             END;
634
635         parts_data :=
636             CASE
637                 WHEN attr_def.parts_data IS NULL THEN 'null()'
638                 WHEN LENGTH( attr_def.parts_data ) = 1 THEN '//*[@code="' || attr_def.parts_data || '"]'
639                 ELSE '//*' || attr_def.parts_data
640             END;
641
642
643
644         xpaths := ARRAY[owning_lib, circ_lib, call_number, copy_number, status, location, circulate,
645                         deposit, deposit_amount, ref, holdable, price, barcode, circ_modifier, circ_as_type,
646                         alert_message, pub_note, priv_note, internal_id, stat_cat_data, parts_data, opac_visible];
647
648         FOR tmp_attr_set IN
649                 SELECT  *
650                   FROM  oils_xpath_tag_to_table( (SELECT marc FROM vandelay.queued_bib_record WHERE id = import_id), attr_def.tag, xpaths)
651                             AS t( ol TEXT, clib TEXT, cn TEXT, cnum TEXT, cs TEXT, cl TEXT, circ TEXT,
652                                   dep TEXT, dep_amount TEXT, r TEXT, hold TEXT, pr TEXT, bc TEXT, circ_mod TEXT,
653                                   circ_as TEXT, amessage TEXT, note TEXT, pnote TEXT, internal_id TEXT,
654                                   stat_cat_data TEXT, parts_data TEXT, opac_vis TEXT )
655         LOOP
656
657             attr_set.import_error := NULL;
658             attr_set.error_detail := NULL;
659             attr_set.deposit_amount := NULL;
660             attr_set.copy_number := NULL;
661             attr_set.price := NULL;
662             attr_set.circ_modifier := NULL;
663             attr_set.location := NULL;
664             attr_set.barcode := NULL;
665             attr_set.call_number := NULL;
666
667             IF tmp_attr_set.pr != '' THEN
668                 tmp_str = REGEXP_REPLACE(tmp_attr_set.pr, E'[^0-9\\.]', '', 'g');
669                 IF tmp_str = '' THEN
670                     attr_set.import_error := 'import.item.invalid.price';
671                     attr_set.error_detail := tmp_attr_set.pr; -- original value
672                     RETURN NEXT attr_set; CONTINUE;
673                 END IF;
674                 attr_set.price := tmp_str::NUMERIC(8,2);
675             END IF;
676
677             IF tmp_attr_set.dep_amount != '' THEN
678                 tmp_str = REGEXP_REPLACE(tmp_attr_set.dep_amount, E'[^0-9\\.]', '', 'g');
679                 IF tmp_str = '' THEN
680                     attr_set.import_error := 'import.item.invalid.deposit_amount';
681                     attr_set.error_detail := tmp_attr_set.dep_amount;
682                     RETURN NEXT attr_set; CONTINUE;
683                 END IF;
684                 attr_set.deposit_amount := tmp_str::NUMERIC(8,2);
685             END IF;
686
687             IF tmp_attr_set.cnum != '' THEN
688                 tmp_str = REGEXP_REPLACE(tmp_attr_set.cnum, E'[^0-9]', '', 'g');
689                 IF tmp_str = '' THEN
690                     attr_set.import_error := 'import.item.invalid.copy_number';
691                     attr_set.error_detail := tmp_attr_set.cnum;
692                     RETURN NEXT attr_set; CONTINUE;
693                 END IF;
694                 attr_set.copy_number := tmp_str::INT;
695             END IF;
696
697             IF tmp_attr_set.ol != '' THEN
698                 SELECT id INTO attr_set.owning_lib FROM actor.org_unit WHERE shortname = UPPER(tmp_attr_set.ol); -- INT
699                 IF NOT FOUND THEN
700                     attr_set.import_error := 'import.item.invalid.owning_lib';
701                     attr_set.error_detail := tmp_attr_set.ol;
702                     RETURN NEXT attr_set; CONTINUE;
703                 END IF;
704             END IF;
705
706             IF tmp_attr_set.clib != '' THEN
707                 SELECT id INTO attr_set.circ_lib FROM actor.org_unit WHERE shortname = UPPER(tmp_attr_set.clib); -- INT
708                 IF NOT FOUND THEN
709                     attr_set.import_error := 'import.item.invalid.circ_lib';
710                     attr_set.error_detail := tmp_attr_set.clib;
711                     RETURN NEXT attr_set; CONTINUE;
712                 END IF;
713             END IF;
714
715             IF tmp_attr_set.cs != '' THEN
716                 SELECT id INTO attr_set.status FROM config.copy_status WHERE LOWER(name) = LOWER(tmp_attr_set.cs); -- INT
717                 IF NOT FOUND THEN
718                     attr_set.import_error := 'import.item.invalid.status';
719                     attr_set.error_detail := tmp_attr_set.cs;
720                     RETURN NEXT attr_set; CONTINUE;
721                 END IF;
722             END IF;
723
724             IF COALESCE(tmp_attr_set.circ_mod, '') = '' THEN
725
726                 -- no circ mod defined, see if we should apply a default
727                 SELECT INTO attr_set.circ_modifier TRIM(BOTH '"' FROM value)
728                     FROM actor.org_unit_ancestor_setting(
729                         'vandelay.item.circ_modifier.default',
730                         attr_set.owning_lib
731                     );
732
733                 -- make sure the value from the org setting is still valid
734                 PERFORM 1 FROM config.circ_modifier WHERE code = attr_set.circ_modifier;
735                 IF NOT FOUND THEN
736                     attr_set.import_error := 'import.item.invalid.circ_modifier';
737                     attr_set.error_detail := tmp_attr_set.circ_mod;
738                     RETURN NEXT attr_set; CONTINUE;
739                 END IF;
740
741             ELSE
742
743                 SELECT code INTO attr_set.circ_modifier FROM config.circ_modifier WHERE code = tmp_attr_set.circ_mod;
744                 IF NOT FOUND THEN
745                     attr_set.import_error := 'import.item.invalid.circ_modifier';
746                     attr_set.error_detail := tmp_attr_set.circ_mod;
747                     RETURN NEXT attr_set; CONTINUE;
748                 END IF;
749             END IF;
750
751             IF tmp_attr_set.circ_as != '' THEN
752                 SELECT code INTO attr_set.circ_as_type FROM config.coded_value_map WHERE ctype = 'item_type' AND code = tmp_attr_set.circ_as;
753                 IF NOT FOUND THEN
754                     attr_set.import_error := 'import.item.invalid.circ_as_type';
755                     attr_set.error_detail := tmp_attr_set.circ_as;
756                     RETURN NEXT attr_set; CONTINUE;
757                 END IF;
758             END IF;
759
760             IF COALESCE(tmp_attr_set.cl, '') = '' THEN
761                 -- no location specified, see if we should apply a default
762
763                 SELECT INTO attr_set.location TRIM(BOTH '"' FROM value)
764                     FROM actor.org_unit_ancestor_setting(
765                         'vandelay.item.copy_location.default',
766                         attr_set.owning_lib
767                     );
768
769                 -- make sure the value from the org setting is still valid
770                 PERFORM 1 FROM asset.copy_location
771                     WHERE id = attr_set.location AND NOT deleted;
772                 IF NOT FOUND THEN
773                     attr_set.import_error := 'import.item.invalid.location';
774                     attr_set.error_detail := tmp_attr_set.cs;
775                     RETURN NEXT attr_set; CONTINUE;
776                 END IF;
777             ELSE
778
779                 -- search up the org unit tree for a matching copy location
780                 WITH RECURSIVE anscestor_depth AS (
781                     SELECT  ou.id,
782                         out.depth AS depth,
783                         ou.parent_ou
784                     FROM  actor.org_unit ou
785                         JOIN actor.org_unit_type out ON (out.id = ou.ou_type)
786                     WHERE ou.id = COALESCE(attr_set.owning_lib, attr_set.circ_lib)
787                         UNION ALL
788                     SELECT  ou.id,
789                         out.depth,
790                         ou.parent_ou
791                     FROM  actor.org_unit ou
792                         JOIN actor.org_unit_type out ON (out.id = ou.ou_type)
793                         JOIN anscestor_depth ot ON (ot.parent_ou = ou.id)
794                 ) SELECT  cpl.id INTO attr_set.location
795                     FROM  anscestor_depth a
796                         JOIN asset.copy_location cpl ON (cpl.owning_lib = a.id)
797                     WHERE LOWER(cpl.name) = LOWER(tmp_attr_set.cl)
798                         AND NOT cpl.deleted
799                     ORDER BY a.depth DESC
800                     LIMIT 1;
801
802                 IF NOT FOUND THEN
803                     attr_set.import_error := 'import.item.invalid.location';
804                     attr_set.error_detail := tmp_attr_set.cs;
805                     RETURN NEXT attr_set; CONTINUE;
806                 END IF;
807             END IF;
808
809             attr_set.circulate      :=
810                 LOWER( SUBSTRING( tmp_attr_set.circ, 1, 1)) IN ('t','y','1')
811                 OR LOWER(tmp_attr_set.circ) = 'circulating'; -- BOOL
812
813             attr_set.deposit        :=
814                 LOWER( SUBSTRING( tmp_attr_set.dep, 1, 1 ) ) IN ('t','y','1')
815                 OR LOWER(tmp_attr_set.dep) = 'deposit'; -- BOOL
816
817             attr_set.holdable       :=
818                 LOWER( SUBSTRING( tmp_attr_set.hold, 1, 1 ) ) IN ('t','y','1')
819                 OR LOWER(tmp_attr_set.hold) = 'holdable'; -- BOOL
820
821             attr_set.opac_visible   :=
822                 LOWER( SUBSTRING( tmp_attr_set.opac_vis, 1, 1 ) ) IN ('t','y','1')
823                 OR LOWER(tmp_attr_set.opac_vis) = 'visible'; -- BOOL
824
825             attr_set.ref            :=
826                 LOWER( SUBSTRING( tmp_attr_set.r, 1, 1 ) ) IN ('t','y','1')
827                 OR LOWER(tmp_attr_set.r) = 'reference'; -- BOOL
828
829             attr_set.call_number    := tmp_attr_set.cn; -- TEXT
830             attr_set.barcode        := tmp_attr_set.bc; -- TEXT,
831             attr_set.alert_message  := tmp_attr_set.amessage; -- TEXT,
832             attr_set.pub_note       := tmp_attr_set.note; -- TEXT,
833             attr_set.priv_note      := tmp_attr_set.pnote; -- TEXT,
834             attr_set.alert_message  := tmp_attr_set.amessage; -- TEXT,
835             attr_set.internal_id    := tmp_attr_set.internal_id::BIGINT;
836             attr_set.stat_cat_data  := tmp_attr_set.stat_cat_data; -- TEXT,
837             attr_set.parts_data     := tmp_attr_set.parts_data; -- TEXT,
838
839             RETURN NEXT attr_set;
840
841         END LOOP;
842
843     END IF;
844
845     RETURN;
846
847 END;
848 $$ LANGUAGE PLPGSQL;
849
850 CREATE OR REPLACE FUNCTION biblio.extract_quality ( marc TEXT, best_lang TEXT, best_type TEXT ) RETURNS INT AS $func$
851 DECLARE
852     qual        INT;
853     ldr         TEXT;
854     tval        TEXT;
855     tval_rec    RECORD;
856     bval        TEXT;
857     bval_rec    RECORD;
858     type_map    RECORD;
859     ff_pos      RECORD;
860     ff_tag_data TEXT;
861 BEGIN
862
863     IF marc IS NULL OR marc = '' THEN
864         RETURN NULL;
865     END IF;
866
867     -- First, the count of tags
868     qual := ARRAY_UPPER(oils_xpath('//*[local-name()="datafield"]', marc), 1);
869
870     -- now go through a bunch of pain to get the record type
871     IF best_type IS NOT NULL THEN
872         ldr := (oils_xpath('//*[local-name()="leader"]/text()', marc))[1];
873
874         IF ldr IS NOT NULL THEN
875             SELECT * INTO tval_rec FROM config.marc21_ff_pos_map WHERE fixed_field = 'Type' LIMIT 1; -- They're all the same
876             SELECT * INTO bval_rec FROM config.marc21_ff_pos_map WHERE fixed_field = 'BLvl' LIMIT 1; -- They're all the same
877
878
879             tval := SUBSTRING( ldr, tval_rec.start_pos + 1, tval_rec.length );
880             bval := SUBSTRING( ldr, bval_rec.start_pos + 1, bval_rec.length );
881
882             -- RAISE NOTICE 'type %, blvl %, ldr %', tval, bval, ldr;
883
884             SELECT * INTO type_map FROM config.marc21_rec_type_map WHERE type_val LIKE '%' || tval || '%' AND blvl_val LIKE '%' || bval || '%';
885
886             IF type_map.code IS NOT NULL THEN
887                 IF best_type = type_map.code THEN
888                     qual := qual + qual / 2;
889                 END IF;
890
891                 FOR ff_pos IN SELECT * FROM config.marc21_ff_pos_map WHERE fixed_field = 'Lang' AND rec_type = type_map.code ORDER BY tag DESC LOOP
892                     ff_tag_data := SUBSTRING((oils_xpath('//*[@tag="' || ff_pos.tag || '"]/text()',marc))[1], ff_pos.start_pos + 1, ff_pos.length);
893                     IF ff_tag_data = best_lang THEN
894                             qual := qual + 100;
895                     END IF;
896                 END LOOP;
897             END IF;
898         END IF;
899     END IF;
900
901     -- Now look for some quality metrics
902     -- DCL record?
903     IF ARRAY_UPPER(oils_xpath('//*[@tag="040"]/*[@code="a" and contains(.,"DLC")]', marc), 1) = 1 THEN
904         qual := qual + 10;
905     END IF;
906
907     -- From OCLC?
908     IF (oils_xpath('//*[@tag="003"]/text()', marc))[1] ~* E'oclo?c' THEN
909         qual := qual + 10;
910     END IF;
911
912     RETURN qual;
913
914 END;
915 $func$ LANGUAGE PLPGSQL;
916
917 CREATE OR REPLACE FUNCTION authority.simple_heading_set( marcxml TEXT ) RETURNS SETOF authority.simple_heading AS $func$
918 DECLARE
919     res             authority.simple_heading%ROWTYPE;
920     acsaf           authority.control_set_authority_field%ROWTYPE;
921     heading_row     authority.heading%ROWTYPE;
922     tag_used        TEXT;
923     nfi_used        TEXT;
924     sf              TEXT;
925     cset            INT;
926     heading_text    TEXT;
927     joiner_text     TEXT;
928     sort_text       TEXT;
929     tmp_text        TEXT;
930     tmp_xml         TEXT;
931     first_sf        BOOL;
932     auth_id         INT DEFAULT COALESCE(NULLIF(oils_xpath_string('//*[@tag="901"]/*[local-name()="subfield" and @code="c"]', marcxml), ''), '0')::INT;
933 BEGIN
934
935     SELECT control_set INTO cset FROM authority.record_entry WHERE id = auth_id;
936
937     IF cset IS NULL THEN
938         SELECT  control_set INTO cset
939           FROM  authority.control_set_authority_field
940           WHERE tag IN ( SELECT  UNNEST(XPATH('//*[starts-with(@tag,"1")]/@tag',marcxml::XML)::TEXT[]))
941           LIMIT 1;
942     END IF;
943
944     res.record := auth_id;
945     res.thesaurus := authority.extract_thesaurus(marcxml);
946
947     FOR acsaf IN SELECT * FROM authority.control_set_authority_field WHERE control_set = cset LOOP
948         res.atag := acsaf.id;
949
950         IF acsaf.heading_field IS NULL THEN
951             tag_used := acsaf.tag;
952             nfi_used := acsaf.nfi;
953             joiner_text := COALESCE(acsaf.joiner, ' ');
954
955             FOR tmp_xml IN SELECT UNNEST(XPATH('//*[@tag="'||tag_used||'"]', marcxml::XML)::TEXT[]) LOOP
956
957                 heading_text := COALESCE(
958                     oils_xpath_string('//*[local-name()="subfield" and contains("'||acsaf.display_sf_list||'",@code)]', tmp_xml, joiner_text),
959                     ''
960                 );
961
962                 IF nfi_used IS NOT NULL THEN
963
964                     sort_text := SUBSTRING(
965                         heading_text FROM
966                         COALESCE(
967                             NULLIF(
968                                 REGEXP_REPLACE(
969                                     oils_xpath_string('//*[local-name()="datafield"]/@ind'||nfi_used, tmp_xml::TEXT),
970                                     $$\D+$$,
971                                     '',
972                                     'g'
973                                 ),
974                                 ''
975                             )::INT,
976                             0
977                         ) + 1
978                     );
979
980                 ELSE
981                     sort_text := heading_text;
982                 END IF;
983
984                 IF heading_text IS NOT NULL AND heading_text <> '' THEN
985                     res.value := heading_text;
986                     res.sort_value := public.naco_normalize(sort_text);
987                     res.index_vector = to_tsvector('keyword'::regconfig, res.sort_value);
988                     RETURN NEXT res;
989                 END IF;
990
991             END LOOP;
992         ELSE
993             FOR heading_row IN SELECT * FROM authority.extract_headings(marcxml, ARRAY[acsaf.heading_field]) LOOP
994                 res.value := heading_row.heading;
995                 res.sort_value := heading_row.normalized_heading;
996                 res.index_vector = to_tsvector('keyword'::regconfig, res.sort_value);
997                 RETURN NEXT res;
998             END LOOP;
999         END IF;
1000     END LOOP;
1001
1002     RETURN;
1003 END;
1004 $func$ LANGUAGE PLPGSQL STABLE STRICT;
1005
1006 CREATE OR REPLACE FUNCTION metabib.remap_metarecord_for_bib(
1007     bib_id bigint,
1008     fp text,
1009     bib_is_deleted boolean DEFAULT false,
1010     retain_deleted boolean DEFAULT false
1011 ) RETURNS bigint AS $function$
1012 DECLARE
1013     new_mapping     BOOL := TRUE;
1014     source_count    INT;
1015     old_mr          BIGINT;
1016     tmp_mr          metabib.metarecord%ROWTYPE;
1017     deleted_mrs     BIGINT[];
1018 BEGIN
1019
1020     -- We need to make sure we're not a deleted master record of an MR
1021     IF bib_is_deleted THEN
1022         IF NOT retain_deleted THEN -- Go away for any MR that we're master of, unless retained
1023             DELETE FROM metabib.metarecord_source_map WHERE source = bib_id;
1024         END IF;
1025
1026         FOR old_mr IN SELECT id FROM metabib.metarecord WHERE master_record = bib_id LOOP
1027
1028             -- Now, are there any more sources on this MR?
1029             SELECT COUNT(*) INTO source_count FROM metabib.metarecord_source_map WHERE metarecord = old_mr;
1030
1031             IF source_count = 0 AND NOT retain_deleted THEN -- No other records
1032                 deleted_mrs := ARRAY_APPEND(deleted_mrs, old_mr); -- Just in case...
1033                 DELETE FROM metabib.metarecord WHERE id = old_mr;
1034
1035             ELSE -- indeed there are. Update it with a null cache and recalcualated master record
1036                 UPDATE  metabib.metarecord
1037                   SET   mods = NULL,
1038                         master_record = (SELECT id FROM biblio.record_entry WHERE fingerprint = fp AND NOT deleted ORDER BY quality DESC, id ASC LIMIT 1)
1039                   WHERE id = old_mr;
1040             END IF;
1041         END LOOP;
1042
1043     ELSE -- insert or update
1044
1045         FOR tmp_mr IN SELECT m.* FROM metabib.metarecord m JOIN metabib.metarecord_source_map s ON (s.metarecord = m.id) WHERE s.source = bib_id LOOP
1046
1047             -- Find the first fingerprint-matching
1048             IF old_mr IS NULL AND fp = tmp_mr.fingerprint THEN
1049                 old_mr := tmp_mr.id;
1050                 new_mapping := FALSE;
1051
1052             ELSE -- Our fingerprint changed ... maybe remove the old MR
1053                 DELETE FROM metabib.metarecord_source_map WHERE metarecord = tmp_mr.id AND source = bib_id; -- remove the old source mapping
1054                 SELECT COUNT(*) INTO source_count FROM metabib.metarecord_source_map WHERE metarecord = tmp_mr.id;
1055                 IF source_count = 0 THEN -- No other records
1056                     deleted_mrs := ARRAY_APPEND(deleted_mrs, tmp_mr.id);
1057                     DELETE FROM metabib.metarecord WHERE id = tmp_mr.id;
1058                 END IF;
1059             END IF;
1060
1061         END LOOP;
1062
1063         -- we found no suitable, preexisting MR based on old source maps
1064         IF old_mr IS NULL THEN
1065             SELECT id INTO old_mr FROM metabib.metarecord WHERE fingerprint = fp; -- is there one for our current fingerprint?
1066
1067             IF old_mr IS NULL THEN -- nope, create one and grab its id
1068                 INSERT INTO metabib.metarecord ( fingerprint, master_record ) VALUES ( fp, bib_id );
1069                 SELECT id INTO old_mr FROM metabib.metarecord WHERE fingerprint = fp;
1070
1071             ELSE -- indeed there is. update it with a null cache and recalcualated master record
1072                 UPDATE  metabib.metarecord
1073                   SET   mods = NULL,
1074                         master_record = (SELECT id FROM biblio.record_entry WHERE fingerprint = fp AND NOT deleted ORDER BY quality DESC, id ASC LIMIT 1)
1075                   WHERE id = old_mr;
1076             END IF;
1077
1078         ELSE -- there was one we already attached to, update its mods cache and master_record
1079             UPDATE  metabib.metarecord
1080               SET   mods = NULL,
1081                     master_record = (SELECT id FROM biblio.record_entry WHERE fingerprint = fp AND NOT deleted ORDER BY quality DESC, id ASC LIMIT 1)
1082               WHERE id = old_mr;
1083         END IF;
1084
1085         IF new_mapping THEN
1086             INSERT INTO metabib.metarecord_source_map (metarecord, source) VALUES (old_mr, bib_id); -- new source mapping
1087         END IF;
1088
1089     END IF;
1090
1091     IF ARRAY_UPPER(deleted_mrs,1) > 0 THEN
1092         UPDATE action.hold_request SET target = old_mr WHERE target IN ( SELECT unnest(deleted_mrs) ) AND hold_type = 'M'; -- if we had to delete any MRs above, make sure their holds are moved
1093     END IF;
1094
1095     RETURN old_mr;
1096
1097 END;
1098 $function$ LANGUAGE plpgsql;
1099
1100
1101 SELECT evergreen.upgrade_deps_block_check('1315', :eg_version);
1102
1103 CREATE TABLE config.ui_staff_portal_page_entry_type (
1104     code        TEXT PRIMARY KEY,
1105     label       TEXT NOT NULL
1106 );
1107
1108 INSERT INTO config.ui_staff_portal_page_entry_type (code, label)
1109 VALUES
1110     ('link', oils_i18n_gettext('link', 'Link', 'cusppet', 'label')),
1111     ('menuitem', oils_i18n_gettext('menuitem', 'Menu Item', 'cusppet', 'label')),
1112     ('text', oils_i18n_gettext('text', 'Text and/or HTML', 'cusppet', 'label')),
1113     ('header', oils_i18n_gettext('header', 'Header', 'cusppet', 'label')),
1114     ('catalogsearch', oils_i18n_gettext('catalogsearch', 'Catalog Search Box', 'cusppet', 'label'));
1115
1116
1117 CREATE TABLE config.ui_staff_portal_page_entry (
1118     id          SERIAL PRIMARY KEY,
1119     page_col    INTEGER NOT NULL,
1120     col_pos     INTEGER NOT NULL,
1121     entry_type  TEXT NOT NULL, -- REFERENCES config.ui_staff_portal_page_entry_type(code)
1122     label       TEXT,
1123     image_url   TEXT,
1124     target_url  TEXT,
1125     entry_text  TEXT,
1126     owner       INT NOT NULL -- REFERENCES actor.org_unit (id)
1127 );
1128
1129 ALTER TABLE config.ui_staff_portal_page_entry ADD CONSTRAINT cusppe_entry_type_fkey
1130     FOREIGN KEY (entry_type) REFERENCES  config.ui_staff_portal_page_entry_type(code) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
1131 ALTER TABLE config.ui_staff_portal_page_entry ADD CONSTRAINT cusppe_owner_fkey
1132     FOREIGN KEY (owner) REFERENCES  actor.org_unit(id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
1133
1134
1135 SELECT evergreen.upgrade_deps_block_check('1316', :eg_version);
1136
1137 INSERT INTO config.ui_staff_portal_page_entry
1138     (id, page_col, col_pos, entry_type, label, image_url, target_url, owner)
1139 VALUES
1140     ( 1, 1, 0, 'header',        oils_i18n_gettext( 1, 'Circulation and Patrons', 'cusppe', 'label'), NULL, NULL, 1)
1141 ,   ( 2, 1, 1, 'menuitem',      oils_i18n_gettext( 2, 'Check Out Items', 'cusppe', 'label'), '/images/portal/forward.png', '/eg/staff/circ/patron/bcsearch', 1)
1142 ,   ( 3, 1, 2, 'menuitem',      oils_i18n_gettext( 3, 'Check In Items', 'cusppe', 'label'), '/images/portal/back.png', '/eg/staff/circ/checkin/index', 1)
1143 ,   ( 4, 1, 3, 'menuitem',      oils_i18n_gettext( 4, 'Search For Patron By Name', 'cusppe', 'label'), '/images/portal/retreivepatron.png', '/eg/staff/circ/patron/search', 1)
1144 ,   ( 5, 2, 0, 'header',        oils_i18n_gettext( 5, 'Item Search and Cataloging', 'cusppe', 'label'), NULL, NULL, 1)
1145 ,   ( 6, 2, 1, 'catalogsearch', oils_i18n_gettext( 6, 'Search Catalog', 'cusppe', 'label'), NULL, NULL, 1)
1146 ,   ( 7, 2, 2, 'menuitem',      oils_i18n_gettext( 7, 'Record Buckets', 'cusppe', 'label'), '/images/portal/bucket.png', '/eg/staff/cat/bucket/record/', 1)
1147 ,   ( 8, 2, 3, 'menuitem',      oils_i18n_gettext( 8, 'Item Buckets', 'cusppe', 'label'), '/images/portal/bucket.png', '/eg/staff/cat/bucket/copy/', 1)
1148 ,   ( 9, 3, 0, 'header',        oils_i18n_gettext( 9, 'Administration', 'cusppe', 'label'), NULL, NULL, 1)
1149 ,   (10, 3, 1, 'link',          oils_i18n_gettext(10, 'Evergreen Documentation', 'cusppe', 'label'), '/images/portal/helpdesk.png', 'https://docs.evergreen-ils.org', 1)
1150 ,   (11, 3, 2, 'menuitem',      oils_i18n_gettext(11, 'Workstation Administration', 'cusppe', 'label'), '/images/portal/helpdesk.png', '/eg/staff/admin/workstation/index', 1)
1151 ,   (12, 3, 3, 'menuitem',      oils_i18n_gettext(12, 'Reports', 'cusppe', 'label'), '/images/portal/reports.png', '/eg/staff/reporter/legacy/main', 1)
1152 ;
1153
1154 SELECT setval('config.ui_staff_portal_page_entry_id_seq', 100);
1155
1156
1157 INSERT INTO config.workstation_setting_type (name, grp, datatype, label)
1158 VALUES (
1159     'eg.grid.admin.config.ui_staff_portal_page_entry', 'gui', 'object',
1160     oils_i18n_gettext(
1161         'eg.grid.admin.config.ui_staff_portal_page_entry',
1162         'Grid Config: admin.config.ui_staff_portal_page_entry',
1163         'cwst', 'label'
1164     )
1165 );
1166
1167
1168
1169 SELECT evergreen.upgrade_deps_block_check('1317', :eg_version);
1170
1171 INSERT INTO permission.perm_list ( id, code, description ) VALUES
1172 ( 636, 'ADMIN_STAFF_PORTAL_PAGE', oils_i18n_gettext( 636,
1173    'Update the staff client portal page', 'ppl', 'description' ))
1174 ;
1175
1176
1177 -- check whether patch can be applied
1178 SELECT evergreen.upgrade_deps_block_check('1318', :eg_version);
1179
1180 -- 950.data.seed-values.sql
1181
1182 INSERT INTO config.global_flag (name, value, enabled, label)
1183 VALUES (
1184     'opac.cover_upload_compression',
1185     0,
1186     TRUE,
1187     oils_i18n_gettext(
1188         'opac.cover_upload_compression',
1189         'Cover image uploads are converted to PNG files with this compression, on a scale of 0 (no compression) to 9 (maximum compression), or -1 for the zlib default.',
1190         'cgf', 'label'
1191     )
1192 );
1193
1194 INSERT INTO config.org_unit_setting_type (name, label, grp, description, datatype)
1195 VALUES (
1196     'opac.cover_upload_max_file_size',
1197     oils_i18n_gettext('opac.cover_upload_max_file_size',
1198         'Maximum file size for uploaded cover image files (at time of upload, prior to rescaling).',
1199         'coust', 'label'),
1200     'opac',
1201     oils_i18n_gettext('opac.cover_upload_max_file_size',
1202         'The number of bytes to allow for a cover image upload.  If unset, defaults to 10737418240 (roughly 10GB).',
1203         'coust', 'description'),
1204     'integer'
1205 );
1206
1207 INSERT INTO permission.perm_list ( id, code, description ) VALUES
1208  ( 637, 'UPLOAD_COVER_IMAGE', oils_i18n_gettext(637,
1209     'Upload local cover images for added content.', 'ppl', 'description'))
1210 ;
1211
1212
1213 SELECT evergreen.upgrade_deps_block_check('1319', :eg_version);
1214
1215 DO $SQL$
1216 BEGIN
1217     
1218     PERFORM TRUE FROM config.usr_setting_type WHERE name = 'cat.copy.templates';
1219
1220     IF NOT FOUND THEN -- no matching user setting
1221
1222         PERFORM TRUE FROM config.workstation_setting_type WHERE name = 'cat.copy.templates';
1223
1224         IF NOT FOUND THEN
1225             -- no matching workstation setting
1226             -- Migrate the existing user setting and its data to the new name.
1227
1228             UPDATE config.usr_setting_type 
1229             SET name = 'cat.copy.templates' 
1230             WHERE name = 'webstaff.cat.copy.templates';
1231
1232             UPDATE actor.usr_setting
1233             SET name = 'cat.copy.templates' 
1234             WHERE name = 'webstaff.cat.copy.templates';
1235
1236         END IF;
1237     END IF;
1238
1239 END; 
1240 $SQL$;
1241
1242
1243
1244 SELECT evergreen.upgrade_deps_block_check('1320', :eg_version); -- jboyer /  / 
1245
1246 ALTER TABLE reporter.template_folder ADD COLUMN simple_reporter BOOLEAN DEFAULT FALSE;
1247 ALTER TABLE reporter.report_folder ADD COLUMN simple_reporter BOOLEAN DEFAULT FALSE;
1248 ALTER TABLE reporter.output_folder ADD COLUMN simple_reporter BOOLEAN DEFAULT FALSE;
1249
1250 DROP INDEX reporter.rpt_template_folder_once_idx;
1251 DROP INDEX reporter.rpt_report_folder_once_idx;
1252 DROP INDEX reporter.rpt_output_folder_once_idx;
1253
1254 CREATE UNIQUE INDEX rpt_template_folder_once_idx ON reporter.template_folder (name,owner,simple_reporter) WHERE parent IS NULL;
1255 CREATE UNIQUE INDEX rpt_report_folder_once_idx ON reporter.report_folder (name,owner,simple_reporter) WHERE parent IS NULL;
1256 CREATE UNIQUE INDEX rpt_output_folder_once_idx ON reporter.output_folder (name,owner,simple_reporter) WHERE parent IS NULL;
1257
1258 -- Private "transform" to allow for simple report permissions verification
1259 CREATE OR REPLACE FUNCTION reporter.intersect_user_perm_ou(context_ou BIGINT, staff_id BIGINT, perm_code TEXT)
1260 RETURNS BOOLEAN AS $$
1261   SELECT CASE WHEN context_ou IN (SELECT * FROM permission.usr_has_perm_at_all(staff_id::INT, perm_code)) THEN TRUE ELSE FALSE END;
1262 $$ LANGUAGE SQL;
1263
1264 -- Hey committer, make sure this id is good to go and also in 950.data.seed-values.sql
1265 INSERT INTO permission.perm_list (id, code, description) VALUES
1266  ( 638, 'RUN_SIMPLE_REPORTS', oils_i18n_gettext(638,
1267     'Build and run simple reports', 'ppl', 'description'));
1268
1269
1270 INSERT INTO config.workstation_setting_type (name, grp, datatype, label)
1271 VALUES (
1272     'eg.grid.reporter.simple.reports', 'gui', 'object',
1273     oils_i18n_gettext(
1274         'eg.grid.reporter.simple.reports',
1275         'Grid Config: eg.grid.reporter.simple.reports',
1276         'cwst', 'label'
1277     )
1278 ), (
1279     'eg.grid.reporter.simple.outputs', 'gui', 'object',
1280     oils_i18n_gettext(
1281         'eg.grid.reporter.simple.outputs',
1282         'Grid Config: eg.grid.reporter.simple.outputs',
1283         'cwst', 'label'
1284     )
1285 );
1286
1287 -- new view parallel to reporter.currently_running
1288 -- and reporter.overdue_reports
1289 CREATE OR REPLACE VIEW reporter.completed_reports AS
1290   SELECT s.id AS run,
1291          r.id AS report,
1292          t.id AS template,
1293          t.owner AS template_owner,
1294          r.owner AS report_owner,
1295          s.runner AS runner,
1296          t.folder AS template_folder,
1297          r.folder AS report_folder,
1298          s.folder AS output_folder,
1299          r.name AS report_name,
1300          t.name AS template_name,
1301          s.start_time,
1302          s.run_time,
1303          s.complete_time,
1304          s.error_code,
1305          s.error_text
1306   FROM reporter.schedule s
1307     JOIN reporter.report r ON r.id = s.report
1308     JOIN reporter.template t ON t.id = r.template
1309   WHERE s.complete_time IS NOT NULL;
1310
1311
1312
1313 SELECT evergreen.upgrade_deps_block_check('1321', :eg_version);
1314
1315 CREATE TABLE asset.copy_inventory (
1316     id                          SERIAL                      PRIMARY KEY,
1317     inventory_workstation       INTEGER                     REFERENCES actor.workstation (id) DEFERRABLE INITIALLY DEFERRED,
1318     inventory_date              TIMESTAMP WITH TIME ZONE    NOT NULL DEFAULT NOW(),
1319     copy                        BIGINT                      NOT NULL
1320 );
1321 CREATE INDEX copy_inventory_copy_idx ON asset.copy_inventory (copy);
1322 CREATE UNIQUE INDEX asset_copy_inventory_date_once_per_copy ON asset.copy_inventory (inventory_date, copy);
1323
1324 CREATE OR REPLACE FUNCTION evergreen.asset_copy_inventory_copy_inh_fkey() RETURNS TRIGGER AS $f$
1325 BEGIN
1326         PERFORM 1 FROM asset.copy WHERE id = NEW.copy;
1327         IF NOT FOUND THEN
1328                 RAISE foreign_key_violation USING MESSAGE = FORMAT(
1329                         $$Referenced asset.copy id not found, copy:%s$$, NEW.copy
1330                 );
1331         END IF;
1332         RETURN NEW;
1333 END;
1334 $f$ LANGUAGE PLPGSQL VOLATILE COST 50;
1335
1336 CREATE CONSTRAINT TRIGGER inherit_asset_copy_inventory_copy_fkey
1337         AFTER UPDATE OR INSERT ON asset.copy_inventory
1338         DEFERRABLE FOR EACH ROW EXECUTE PROCEDURE evergreen.asset_copy_inventory_copy_inh_fkey();
1339
1340 CREATE OR REPLACE FUNCTION asset.copy_may_float_to_inventory_workstation() RETURNS TRIGGER AS $func$
1341 DECLARE
1342     copy asset.copy%ROWTYPE;
1343     workstation actor.workstation%ROWTYPE;
1344 BEGIN
1345     SELECT * INTO copy FROM asset.copy WHERE id = NEW.copy;
1346     IF FOUND THEN
1347         SELECT * INTO workstation FROM actor.workstation WHERE id = NEW.inventory_workstation;
1348         IF FOUND THEN
1349            IF copy.floating IS NULL THEN
1350               IF copy.circ_lib <> workstation.owning_lib THEN
1351                  RAISE EXCEPTION 'Inventory workstation owning lib (%) does not match copy circ lib (%).',
1352                        workstation.owning_lib, copy.circ_lib;
1353               END IF;
1354            ELSE
1355               IF NOT evergreen.can_float(copy.floating, copy.circ_lib, workstation.owning_lib) THEN
1356                  RAISE EXCEPTION 'Copy (%) cannot float to inventory workstation owning lib (%).',
1357                        copy.id, workstation.owning_lib;
1358               END IF;
1359            END IF;
1360         END IF;
1361     END IF;
1362     RETURN NEW;
1363 END;
1364 $func$ LANGUAGE PLPGSQL VOLATILE COST 50;
1365
1366 CREATE CONSTRAINT TRIGGER asset_copy_inventory_allowed_trig
1367         AFTER UPDATE OR INSERT ON asset.copy_inventory
1368         DEFERRABLE FOR EACH ROW EXECUTE PROCEDURE asset.copy_may_float_to_inventory_workstation();
1369
1370 INSERT INTO asset.copy_inventory
1371 (inventory_workstation, inventory_date, copy)
1372 SELECT DISTINCT ON (inventory_date, copy) inventory_workstation, inventory_date, copy
1373 FROM asset.latest_inventory
1374 JOIN asset.copy acp ON acp.id = latest_inventory.copy
1375 JOIN actor.workstation ON workstation.id = latest_inventory.inventory_workstation
1376 WHERE acp.circ_lib = workstation.owning_lib
1377 UNION
1378 SELECT DISTINCT ON (inventory_date, copy) inventory_workstation, inventory_date, copy
1379 FROM asset.latest_inventory
1380 JOIN asset.copy acp ON acp.id = latest_inventory.copy
1381 JOIN actor.workstation ON workstation.id = latest_inventory.inventory_workstation
1382 WHERE acp.circ_lib <> workstation.owning_lib
1383 AND acp.floating IS NOT NULL
1384 AND evergreen.can_float(acp.floating, acp.circ_lib, workstation.owning_lib)
1385 ORDER by inventory_date;
1386
1387 DROP TABLE asset.latest_inventory;
1388
1389 CREATE VIEW asset.latest_inventory (id, inventory_workstation, inventory_date, copy) AS
1390 SELECT DISTINCT ON (copy) id, inventory_workstation, inventory_date, copy
1391 FROM asset.copy_inventory
1392 ORDER BY copy, inventory_date DESC;
1393
1394 DROP FUNCTION evergreen.asset_latest_inventory_copy_inh_fkey();
1395
1396
1397 SELECT evergreen.upgrade_deps_block_check('1322', :eg_version);
1398
1399 INSERT into config.org_unit_setting_type
1400 ( name, grp, label, description, datatype, fm_class ) VALUES
1401 ( 'opac.patron.custom_jquery', 'opac',
1402     oils_i18n_gettext('opac.patron.custom_jquery',
1403         'Custom jQuery for the OPAC',
1404         'coust', 'label'),
1405     oils_i18n_gettext('opac.patron.custom_jquery',
1406         'Custom jQuery for the OPAC',
1407         'coust', 'description'),
1408     'string', NULL);
1409
1410
1411 SELECT evergreen.upgrade_deps_block_check('1323', :eg_version);
1412
1413 -- VIEWS for the oai service
1414 CREATE SCHEMA oai;
1415
1416 -- The view presents a lean table with unique bre.tc-numbers for oai paging;
1417 CREATE VIEW oai.biblio AS
1418   SELECT
1419     bre.id                             AS rec_id,
1420     bre.edit_date AT TIME ZONE 'UTC'   AS datestamp,
1421     bre.deleted                        AS deleted
1422   FROM
1423     biblio.record_entry bre
1424   ORDER BY
1425     bre.id;
1426
1427 -- The view presents a lean table with unique are.tc-numbers for oai paging;
1428 CREATE VIEW oai.authority AS
1429   SELECT
1430     are.id                           AS rec_id,
1431     are.edit_date AT TIME ZONE 'UTC' AS datestamp,
1432     are.deleted                      AS deleted
1433   FROM
1434     authority.record_entry AS are
1435   ORDER BY
1436     are.id;
1437
1438 CREATE OR REPLACE function oai.bib_is_visible_at_org_by_copy(bib BIGINT, org INT) RETURNS BOOL AS $F$
1439 WITH corgs AS (SELECT array_agg(id) AS list FROM actor.org_unit_descendants(org))
1440   SELECT EXISTS (SELECT 1 FROM asset.copy_vis_attr_cache, corgs WHERE vis_attr_vector @@ search.calculate_visibility_attribute_test('circ_lib', corgs.list)::query_int AND bib=record)
1441 $F$ LANGUAGE SQL STABLE;
1442
1443 CREATE OR REPLACE function oai.bib_is_visible_at_org_by_luri(bib BIGINT, org INT) RETURNS BOOL AS $F$
1444 WITH lorgs AS(SELECT array_agg(id) AS list FROM actor.org_unit_ancestors(org))
1445   SELECT EXISTS (SELECT 1 FROM biblio.record_entry, lorgs WHERE vis_attr_vector @@ search.calculate_visibility_attribute_test('luri_org', lorgs.list)::query_int AND bib=id)
1446 $F$ LANGUAGE SQL STABLE;
1447
1448 CREATE OR REPLACE function oai.bib_is_visible_by_source(bib BIGINT, src TEXT) RETURNS BOOL AS $F$
1449   SELECT EXISTS (SELECT 1 FROM biblio.record_entry b JOIN config.bib_source s ON (b.source = s.id) WHERE transcendant AND s.source = src AND bib=b.id)
1450 $F$ LANGUAGE SQL STABLE;
1451
1452 CREATE OR REPLACE function oai.auth_is_visible_by_axis(auth BIGINT, ax TEXT) RETURNS BOOL AS $F$
1453   SELECT EXISTS (SELECT 1 FROM authority.browse_axis_authority_field_map m JOIN authority.simple_heading r on (r.atag = m.field AND r.record = auth AND m.axis = ax))
1454 $F$ LANGUAGE SQL STABLE;
1455
1456
1457
1458 SELECT evergreen.upgrade_deps_block_check('1324', :eg_version);
1459
1460 CREATE TABLE action_trigger.alternate_template (
1461       id               SERIAL,
1462       event_def        INTEGER REFERENCES action_trigger.event_definition(id) INITIALLY DEFERRED,
1463       template         TEXT,
1464       active           BOOLEAN DEFAULT TRUE,
1465       message_title    TEXT,
1466       message_template TEXT,
1467       locale           TEXT REFERENCES config.i18n_locale(code) INITIALLY DEFERRED,
1468       UNIQUE (event_def,locale)
1469 );
1470
1471 ALTER TABLE actor.usr ADD COLUMN locale TEXT REFERENCES config.i18n_locale(code) INITIALLY DEFERRED;
1472
1473 ALTER TABLE action_trigger.event_output ADD COLUMN locale TEXT;
1474
1475
1476 SELECT evergreen.upgrade_deps_block_check('1325', :eg_version);
1477
1478 UPDATE config.xml_transform SET xslt=$XSLT$<?xml version="1.0" encoding="UTF-8"?>
1479 <xsl:stylesheet version="1.0" xmlns:mads="http://www.loc.gov/mads/v2"
1480         xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:marc="http://www.loc.gov/MARC21/slim"
1481         xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="marc">
1482         <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
1483         <xsl:strip-space elements="*"/>
1484
1485         <xsl:variable name="ascii">
1486                 <xsl:text> !"#$%&amp;'()*+,-./0123456789:;&lt;=&gt;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~</xsl:text>
1487         </xsl:variable>
1488
1489         <xsl:variable name="latin1">
1490                 <xsl:text> ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ</xsl:text>
1491         </xsl:variable>
1492         <!-- Characters that usually don't need to be escaped -->
1493         <xsl:variable name="safe">
1494                 <xsl:text>!'()*-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~</xsl:text>
1495         </xsl:variable>
1496
1497         <xsl:variable name="hex">0123456789ABCDEF</xsl:variable>
1498
1499
1500         <xsl:template name="datafield">
1501                 <xsl:param name="tag"/>
1502                 <xsl:param name="ind1">
1503                         <xsl:text> </xsl:text>
1504                 </xsl:param>
1505                 <xsl:param name="ind2">
1506                         <xsl:text> </xsl:text>
1507                 </xsl:param>
1508                 <xsl:param name="subfields"/>
1509                 <xsl:element name="marc:datafield">
1510                         <xsl:attribute name="tag">
1511                                 <xsl:value-of select="$tag"/>
1512                         </xsl:attribute>
1513                         <xsl:attribute name="ind1">
1514                                 <xsl:value-of select="$ind1"/>
1515                         </xsl:attribute>
1516                         <xsl:attribute name="ind2">
1517                                 <xsl:value-of select="$ind2"/>
1518                         </xsl:attribute>
1519                         <xsl:copy-of select="$subfields"/>
1520                 </xsl:element>
1521         </xsl:template>
1522
1523         <xsl:template name="subfieldSelect">
1524                 <xsl:param name="codes">abcdefghijklmnopqrstuvwxyz</xsl:param>
1525                 <xsl:param name="delimeter">
1526                         <xsl:text> </xsl:text>
1527                 </xsl:param>
1528                 <xsl:variable name="str">
1529                         <xsl:for-each select="marc:subfield">
1530                                 <xsl:if test="contains($codes, @code)">
1531                                         <xsl:value-of select="text()"/>
1532                                         <xsl:value-of select="$delimeter"/>
1533                                 </xsl:if>
1534                         </xsl:for-each>
1535                 </xsl:variable>
1536                 <xsl:value-of select="substring($str,1,string-length($str)-string-length($delimeter))"/>
1537         </xsl:template>
1538
1539         <xsl:template name="buildSpaces">
1540                 <xsl:param name="spaces"/>
1541                 <xsl:param name="char">
1542                         <xsl:text> </xsl:text>
1543                 </xsl:param>
1544                 <xsl:if test="$spaces>0">
1545                         <xsl:value-of select="$char"/>
1546                         <xsl:call-template name="buildSpaces">
1547                                 <xsl:with-param name="spaces" select="$spaces - 1"/>
1548                                 <xsl:with-param name="char" select="$char"/>
1549                         </xsl:call-template>
1550                 </xsl:if>
1551         </xsl:template>
1552
1553         <xsl:template name="chopPunctuation">
1554                 <xsl:param name="chopString"/>
1555                 <xsl:param name="punctuation">
1556                         <xsl:text>.:,;/ </xsl:text>
1557                 </xsl:param>
1558                 <xsl:variable name="length" select="string-length($chopString)"/>
1559                 <xsl:choose>
1560                         <xsl:when test="$length=0"/>
1561                         <xsl:when test="contains($punctuation, substring($chopString,$length,1))">
1562                                 <xsl:call-template name="chopPunctuation">
1563                                         <xsl:with-param name="chopString" select="substring($chopString,1,$length - 1)"/>
1564                                         <xsl:with-param name="punctuation" select="$punctuation"/>
1565                                 </xsl:call-template>
1566                         </xsl:when>
1567                         <xsl:when test="not($chopString)"/>
1568                         <xsl:otherwise>
1569                                 <xsl:value-of select="$chopString"/>
1570                         </xsl:otherwise>
1571                 </xsl:choose>
1572         </xsl:template>
1573
1574         <xsl:template name="chopPunctuationFront">
1575                 <xsl:param name="chopString"/>
1576                 <xsl:variable name="length" select="string-length($chopString)"/>
1577                 <xsl:choose>
1578                         <xsl:when test="$length=0"/>
1579                         <xsl:when test="contains('.:,;/[ ', substring($chopString,1,1))">
1580                                 <xsl:call-template name="chopPunctuationFront">
1581                                         <xsl:with-param name="chopString" select="substring($chopString,2,$length - 1)"
1582                                         />
1583                                 </xsl:call-template>
1584                         </xsl:when>
1585                         <xsl:when test="not($chopString)"/>
1586                         <xsl:otherwise>
1587                                 <xsl:value-of select="$chopString"/>
1588                         </xsl:otherwise>
1589                 </xsl:choose>
1590         </xsl:template>
1591
1592         <xsl:template name="chopPunctuationBack">
1593                 <xsl:param name="chopString"/>
1594                 <xsl:param name="punctuation">
1595                         <xsl:text>.:,;/] </xsl:text>
1596                 </xsl:param>
1597                 <xsl:variable name="length" select="string-length($chopString)"/>
1598                 <xsl:choose>
1599                         <xsl:when test="$length=0"/>
1600                         <xsl:when test="contains($punctuation, substring($chopString,$length,1))">
1601                                 <xsl:call-template name="chopPunctuation">
1602                                         <xsl:with-param name="chopString" select="substring($chopString,1,$length - 1)"/>
1603                                         <xsl:with-param name="punctuation" select="$punctuation"/>
1604                                 </xsl:call-template>
1605                         </xsl:when>
1606                         <xsl:when test="not($chopString)"/>
1607                         <xsl:otherwise>
1608                                 <xsl:value-of select="$chopString"/>
1609                         </xsl:otherwise>
1610                 </xsl:choose>
1611         </xsl:template>
1612
1613         <!-- nate added 12/14/2007 for lccn.loc.gov: url encode ampersand, etc. -->
1614         <xsl:template name="url-encode">
1615
1616                 <xsl:param name="str"/>
1617
1618                 <xsl:if test="$str">
1619                         <xsl:variable name="first-char" select="substring($str,1,1)"/>
1620                         <xsl:choose>
1621                                 <xsl:when test="contains($safe,$first-char)">
1622                                         <xsl:value-of select="$first-char"/>
1623                                 </xsl:when>
1624                                 <xsl:otherwise>
1625                                         <xsl:variable name="codepoint">
1626                                                 <xsl:choose>
1627                                                         <xsl:when test="contains($ascii,$first-char)">
1628                                                                 <xsl:value-of
1629                                                                         select="string-length(substring-before($ascii,$first-char)) + 32"
1630                                                                 />
1631                                                         </xsl:when>
1632                                                         <xsl:when test="contains($latin1,$first-char)">
1633                                                                 <xsl:value-of
1634                                                                         select="string-length(substring-before($latin1,$first-char)) + 160"/>
1635                                                                 <!-- was 160 -->
1636                                                         </xsl:when>
1637                                                         <xsl:otherwise>
1638                                                                 <xsl:message terminate="no">Warning: string contains a character
1639                                                                         that is out of range! Substituting "?".</xsl:message>
1640                                                                 <xsl:text>63</xsl:text>
1641                                                         </xsl:otherwise>
1642                                                 </xsl:choose>
1643                                         </xsl:variable>
1644                                         <xsl:variable name="hex-digit1"
1645                                                 select="substring($hex,floor($codepoint div 16) + 1,1)"/>
1646                                         <xsl:variable name="hex-digit2" select="substring($hex,$codepoint mod 16 + 1,1)"/>
1647                                         <!-- <xsl:value-of select="concat('%',$hex-digit2)"/> -->
1648                                         <xsl:value-of select="concat('%',$hex-digit1,$hex-digit2)"/>
1649                                 </xsl:otherwise>
1650                         </xsl:choose>
1651                         <xsl:if test="string-length($str) &gt; 1">
1652                                 <xsl:call-template name="url-encode">
1653                                         <xsl:with-param name="str" select="substring($str,2)"/>
1654                                 </xsl:call-template>
1655                         </xsl:if>
1656                 </xsl:if>
1657         </xsl:template>
1658
1659
1660 <!--
1661 2.15  reversed genre and setAuthority template order under relatedTypeAttribute                       tmee 11/13/2018
1662 2.14    Fixed bug in mads:geographic attributes syntax                                      ws   05/04/2016             
1663 2.13    fixed repeating <geographic>                                                                                                            tmee 01/31/2014
1664 2.12    added $2 authority for <classification>                                                                                         tmee 09/18/2012
1665 2.11    added delimiters between <classification> subfields                                                                     tmee 09/18/2012
1666 2.10    fixed type="other" and type="otherType" for mads:related                                                        tmee 09/16/2011
1667 2.09    fixed professionTerm and genreTerm empty tag error                                                                      tmee 09/16/2011
1668 2.08    fixed marc:subfield @code='i' matching error                                                                            tmee 09/16/2011
1669 2.07    fixed 555 duplication error                                                                                                                     tmee 08/10/2011 
1670 2.06    fixed topic subfield error                                                                                                                      tmee 08/10/2011 
1671 2.05    fixed title subfield error                                                                                                                      tmee 06/20/2011 
1672 2.04    fixed geographicSubdivision mapping for authority element                                                       tmee 06/16/2011
1673 2.03    added classification for 053, 055, 060, 065, 070, 080, 082, 083, 086, 087                       tmee 06/03/2011         
1674 2.02    added descriptionStandard for 008/10                                                                                            tmee 04/27/2011
1675 2.01    added extensions for 046, 336, 370, 374, 375, 376                                                                       tmee 04/08/2011
1676 2.00    redefined imported MODS elements in version 1.0 to MADS elements in version 2.0         tmee 02/08/2011
1677 1.08    added 372 subfields $a $s $t for <fieldOfActivity>                                                                      tmee 06/24/2010
1678 1.07    removed role/roleTerm 100, 110, 111, 400, 410, 411, 500, 510, 511, 700, 710, 711        tmee 06/24/2010
1679 1.06    added strip-space                                                                                                                                       tmee 06/24/2010
1680 1.05    added subfield $a for 130, 430, 530                                                                                                     tmee 06/21/2010
1681 1.04    fixed 550 z omission                                                                                                                            ntra 08/11/2008
1682 1.03    removed duplication of 550 $a text                                                                                                      tmee 11/01/2006
1683 1.02    fixed namespace references between mads and mods                                                                        ntra 10/06/2006
1684 1.01    revised                                                                                                                                                         rgue/jrad 11/29/05
1685 1.00    adapted from MARC21Slim2MODS3.xsl                                                                                                       ntra 07/06/05
1686 -->
1687
1688         <!-- authority attribute defaults to 'naf' if not set using this authority parameter, for <authority> descriptors: name, titleInfo, geographic -->
1689         <xsl:param name="authority"/>
1690         <xsl:variable name="auth">
1691                 <xsl:choose>
1692                         <xsl:when test="$authority">
1693                                 <xsl:value-of select="$authority"/>
1694                         </xsl:when>
1695                         <xsl:otherwise>naf</xsl:otherwise>
1696                 </xsl:choose>
1697         </xsl:variable>
1698         <xsl:variable name="controlField008" select="marc:controlfield[@tag='008']"/>
1699         <xsl:variable name="controlField008-06"
1700                 select="substring(descendant-or-self::marc:controlfield[@tag=008],7,1)"/>
1701         <xsl:variable name="controlField008-11"
1702                 select="substring(descendant-or-self::marc:controlfield[@tag=008],12,1)"/>
1703         <xsl:variable name="controlField008-14"
1704                 select="substring(descendant-or-self::marc:controlfield[@tag=008],15,1)"/>
1705         <xsl:template match="/">
1706                 <xsl:choose>
1707                         <xsl:when test="descendant-or-self::marc:collection">
1708                                 <mads:madsCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1709                                         xsi:schemaLocation="http://www.loc.gov/mads/v2 http://www.loc.gov/standards/mads/v2/mads-2-0.xsd">
1710                                         <xsl:for-each select="descendant-or-self::marc:collection/marc:record">
1711                                                 <mads:mads version="2.0">
1712                                                         <xsl:call-template name="marcRecord"/>
1713                                                 </mads:mads>
1714                                         </xsl:for-each>
1715                                 </mads:madsCollection>
1716                         </xsl:when>
1717                         <xsl:otherwise>
1718                                 <mads:mads version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1719                                         xsi:schemaLocation="http://www.loc.gov/mads/v2 http://www.loc.gov/standards/mads/mads-2-0.xsd">
1720                                         <xsl:for-each select="descendant-or-self::marc:record">
1721                                                 <xsl:call-template name="marcRecord"/>
1722                                         </xsl:for-each>
1723                                 </mads:mads>
1724                         </xsl:otherwise>
1725                 </xsl:choose>
1726         </xsl:template>
1727
1728         <xsl:template name="marcRecord">
1729                 <mads:authority>
1730                         <!-- 2.04 -->
1731                         <xsl:choose>
1732                                 <xsl:when test="$controlField008-06='d'">
1733                                         <xsl:attribute name="geographicSubdivision">
1734                                                 <xsl:text>direct</xsl:text>
1735                                         </xsl:attribute>
1736                                 </xsl:when>
1737                                 <xsl:when test="$controlField008-06='i'">
1738                                         <xsl:attribute name="geographicSubdivision">
1739                                                 <xsl:text>indirect</xsl:text>
1740                                         </xsl:attribute>
1741                                 </xsl:when>
1742                                 <xsl:when test="$controlField008-06='n'">
1743                                         <xsl:attribute name="geographicSubdivision">
1744                                                 <xsl:text>not applicable</xsl:text>
1745                                         </xsl:attribute>
1746                                 </xsl:when>
1747                         </xsl:choose>
1748                         
1749                         <xsl:apply-templates select="marc:datafield[100 &lt;= @tag  and @tag &lt; 200]"/>               
1750                 </mads:authority>
1751
1752                 <!-- related -->
1753                 <xsl:apply-templates
1754                         select="marc:datafield[500 &lt;= @tag and @tag &lt;= 585]|marc:datafield[700 &lt;= @tag and @tag &lt;= 785]"/>
1755
1756                 <!-- variant -->
1757                 <xsl:apply-templates select="marc:datafield[400 &lt;= @tag and @tag &lt;= 485]"/>
1758
1759                 <!-- notes -->
1760                 <xsl:apply-templates select="marc:datafield[667 &lt;= @tag and @tag &lt;= 688]"/>
1761
1762                 <!-- url -->
1763                 <xsl:apply-templates select="marc:datafield[@tag=856]"/>
1764                 <xsl:apply-templates select="marc:datafield[@tag=010]"/>
1765                 <xsl:apply-templates select="marc:datafield[@tag=024]"/>
1766                 <xsl:apply-templates select="marc:datafield[@tag=372]"/>
1767                 
1768                 <!-- classification -->
1769                 <xsl:apply-templates select="marc:datafield[@tag=053]"/>
1770                 <xsl:apply-templates select="marc:datafield[@tag=055]"/>
1771                 <xsl:apply-templates select="marc:datafield[@tag=060]"/>
1772                 <xsl:apply-templates select="marc:datafield[@tag=065]"/>
1773                 <xsl:apply-templates select="marc:datafield[@tag=070]"/>
1774                 <xsl:apply-templates select="marc:datafield[@tag=080]"/>
1775                 <xsl:apply-templates select="marc:datafield[@tag=082]"/>
1776                 <xsl:apply-templates select="marc:datafield[@tag=083]"/>
1777                 <xsl:apply-templates select="marc:datafield[@tag=086]"/>
1778                 <xsl:apply-templates select="marc:datafield[@tag=087]"/>
1779
1780                 <!-- affiliation-->
1781                 <xsl:for-each select="marc:datafield[@tag=373]">
1782                         <mads:affiliation>
1783                                 <mads:position>
1784                                         <xsl:value-of select="marc:subfield[@code='a']"/>
1785                                 </mads:position>
1786                                 <mads:dateValid point="start">
1787                                         <xsl:value-of select="marc:subfield[@code='s']"/>
1788                                 </mads:dateValid>
1789                                 <mads:dateValid point="end">
1790                                         <xsl:value-of select="marc:subfield[@code='t']"/>
1791                                 </mads:dateValid>
1792                         </mads:affiliation>
1793                 </xsl:for-each>
1794                 <xsl:for-each select="marc:datafield[@tag=371]">
1795                         <mads:affiliation>
1796                                 <mads:address>
1797                                         <mads:street>
1798                                                 <xsl:value-of select="marc:subfield[@code='a']"/>
1799                                         </mads:street>
1800                                         <mads:city>
1801                                                 <xsl:value-of select="marc:subfield[@code='b']"/>
1802                                         </mads:city>
1803                                         <mads:state>
1804                                                 <xsl:value-of select="marc:subfield[@code='c']"/>
1805                                         </mads:state>
1806                                         <mads:country>
1807                                                 <xsl:value-of select="marc:subfield[@code='d']"/>
1808                                         </mads:country>
1809                                         <mads:postcode>
1810                                                 <xsl:value-of select="marc:subfield[@code='e']"/>
1811                                         </mads:postcode>
1812                                 </mads:address>
1813                                 <mads:email>
1814                                         <xsl:value-of select="marc:subfield[@code='m']"/>
1815                                 </mads:email>
1816                         </mads:affiliation>
1817                 </xsl:for-each>
1818
1819                 <!-- extension-->
1820                 <xsl:for-each select="marc:datafield[@tag=336]">
1821                         <mads:extension>
1822                                 <mads:contentType>
1823                                         <mads:contentType type="text">
1824                                                 <xsl:value-of select="marc:subfield[@code='a']"/>
1825                                         </mads:contentType>
1826                                         <mads:contentType type="code">
1827                                                 <xsl:value-of select="marc:subfield[@code='b']"/>
1828                                         </mads:contentType>
1829                                 </mads:contentType>
1830                         </mads:extension>
1831                 </xsl:for-each>
1832
1833                 <xsl:for-each select="marc:datafield[@tag=374]">
1834                         <mads:extension>
1835                                 <mads:profession>
1836                                         <xsl:choose>
1837                                                 <xsl:when test="marc:subfield[@code='a']">
1838                                                         <mads:professionTerm>
1839                                                                 <xsl:value-of select="marc:subfield[@code='a']"/>
1840                                                         </mads:professionTerm>
1841                                                 </xsl:when>
1842                                                 <xsl:when test="marc:subfield[@code='s']">
1843                                                         <mads:dateValid point="start">
1844                                                                 <xsl:value-of select="marc:subfield[@code='s']"/>
1845                                                         </mads:dateValid>
1846                                                 </xsl:when>
1847                                                 <xsl:when test="marc:subfield[@code='t']">
1848                                                         <mads:dateValid point="end">
1849                                                                 <xsl:value-of select="marc:subfield[@code='t']"/>
1850                                                         </mads:dateValid>
1851                                                 </xsl:when>
1852                                         </xsl:choose>
1853                                 </mads:profession>
1854                         </mads:extension>
1855                 </xsl:for-each>
1856                 
1857                 <xsl:for-each select="marc:datafield[@tag=375]">
1858                         <mads:extension>
1859                                 <mads:gender>
1860                                         <xsl:choose>
1861                                                 <xsl:when test="marc:subfield[@code='a']">
1862                                                         <mads:genderTerm>
1863                                                                 <xsl:value-of select="marc:subfield[@code='a']"/>
1864                                                         </mads:genderTerm>
1865                                                 </xsl:when>
1866                                                 <xsl:when test="marc:subfield[@code='s']">
1867                                                         <mads:dateValid point="start">
1868                                                                 <xsl:value-of select="marc:subfield[@code='s']"/>
1869                                                         </mads:dateValid>
1870                                                 </xsl:when>
1871                                                 <xsl:when test="marc:subfield[@code='t']">
1872                                                         <mads:dateValid point="end">
1873                                                                 <xsl:value-of select="marc:subfield[@code='t']"/>
1874                                                         </mads:dateValid>
1875                                                 </xsl:when>
1876                                         </xsl:choose>
1877                                 </mads:gender>
1878                         </mads:extension>
1879                 </xsl:for-each>
1880
1881                 <xsl:for-each select="marc:datafield[@tag=376]">
1882                         <mads:extension>
1883                                 <mads:familyInformation>
1884                                         <mads:typeOfFamily>
1885                                                 <xsl:value-of select="marc:subfield[@code='a']"/>
1886                                         </mads:typeOfFamily>
1887                                         <mads:nameOfProminentMember>
1888                                                 <xsl:value-of select="marc:subfield[@code='b']"/>
1889                                         </mads:nameOfProminentMember>
1890                                         <mads:hereditaryTitle>
1891                                                 <xsl:value-of select="marc:subfield[@code='c']"/>
1892                                         </mads:hereditaryTitle>
1893                                         <mads:dateValid point="start">
1894                                                 <xsl:value-of select="marc:subfield[@code='s']"/>
1895                                         </mads:dateValid>
1896                                         <mads:dateValid point="end">
1897                                                 <xsl:value-of select="marc:subfield[@code='t']"/>
1898                                         </mads:dateValid>
1899                                 </mads:familyInformation>
1900                         </mads:extension>
1901                 </xsl:for-each>
1902
1903                 <mads:recordInfo>
1904                         <mads:recordOrigin>Converted from MARCXML to MADS version 2.0 (Revision 2.13)</mads:recordOrigin>
1905                         <!-- <xsl:apply-templates select="marc:datafield[@tag=024]"/> -->
1906
1907                         <xsl:apply-templates select="marc:datafield[@tag=040]/marc:subfield[@code='a']"/>
1908                         <xsl:apply-templates select="marc:controlfield[@tag=005]"/>
1909                         <xsl:apply-templates select="marc:controlfield[@tag=001]"/>
1910                         <xsl:apply-templates select="marc:datafield[@tag=040]/marc:subfield[@code='b']"/>
1911                         <xsl:apply-templates select="marc:datafield[@tag=040]/marc:subfield[@code='e']"/>
1912                         <xsl:for-each select="marc:controlfield[@tag=008]">
1913                                 <xsl:if test="substring(.,11,1)='a'">
1914                                         <mads:descriptionStandard>
1915                                                 <xsl:text>earlier rules</xsl:text>
1916                                         </mads:descriptionStandard>
1917                                 </xsl:if>
1918                                 <xsl:if test="substring(.,11,1)='b'">
1919                                         <mads:descriptionStandard>
1920                                                 <xsl:text>aacr1</xsl:text>
1921                                         </mads:descriptionStandard>
1922                                 </xsl:if>
1923                                 <xsl:if test="substring(.,11,1)='c'">
1924                                         <mads:descriptionStandard>
1925                                                 <xsl:text>aacr2</xsl:text>
1926                                         </mads:descriptionStandard>
1927                                 </xsl:if>
1928                                 <xsl:if test="substring(.,11,1)='d'">
1929                                         <mads:descriptionStandard>
1930                                                 <xsl:text>aacr2 compatible</xsl:text>
1931                                         </mads:descriptionStandard>
1932                                 </xsl:if>
1933                                 <xsl:if test="substring(.,11,1)='z'">
1934                                         <mads:descriptionStandard>
1935                                                 <xsl:text>other rules</xsl:text>
1936                                         </mads:descriptionStandard>
1937                                 </xsl:if>
1938                         </xsl:for-each>
1939                 </mads:recordInfo>
1940         </xsl:template>
1941
1942         <!-- start of secondary templates -->
1943
1944         <!-- ======== xlink ======== -->
1945
1946         <!-- <xsl:template name="uri"> 
1947     <xsl:for-each select="marc:subfield[@code='0']">
1948       <xsl:attribute name="xlink:href">
1949         <xsl:value-of select="."/>
1950       </xsl:attribute>
1951     </xsl:for-each>
1952      </xsl:template> 
1953    -->
1954         <xsl:template match="marc:subfield[@code='i']">
1955                 <xsl:attribute name="otherType">
1956                         <xsl:value-of select="."/>
1957                 </xsl:attribute>
1958         </xsl:template>
1959
1960         <!-- No role/roleTerm mapped in MADS 06/24/2010
1961         <xsl:template name="role">
1962                 <xsl:for-each select="marc:subfield[@code='e']">
1963                         <mads:role>
1964                                 <mads:roleTerm type="text">
1965                                         <xsl:value-of select="."/>
1966                                 </mads:roleTerm>
1967                         </mads:role>
1968                 </xsl:for-each>
1969         </xsl:template>
1970 -->
1971
1972         <xsl:template name="part">
1973                 <xsl:variable name="partNumber">
1974                         <xsl:call-template name="specialSubfieldSelect">
1975                                 <xsl:with-param name="axis">n</xsl:with-param>
1976                                 <xsl:with-param name="anyCodes">n</xsl:with-param>
1977                                 <xsl:with-param name="afterCodes">fghkdlmor</xsl:with-param>
1978                         </xsl:call-template>
1979                 </xsl:variable>
1980                 <xsl:variable name="partName">
1981                         <xsl:call-template name="specialSubfieldSelect">
1982                                 <xsl:with-param name="axis">p</xsl:with-param>
1983                                 <xsl:with-param name="anyCodes">p</xsl:with-param>
1984                                 <xsl:with-param name="afterCodes">fghkdlmor</xsl:with-param>
1985                         </xsl:call-template>
1986                 </xsl:variable>
1987                 <xsl:if test="string-length(normalize-space($partNumber))">
1988                         <mads:partNumber>
1989                                 <xsl:call-template name="chopPunctuation">
1990                                         <xsl:with-param name="chopString" select="$partNumber"/>
1991                                 </xsl:call-template>
1992                         </mads:partNumber>
1993                 </xsl:if>
1994                 <xsl:if test="string-length(normalize-space($partName))">
1995                         <mads:partName>
1996                                 <xsl:call-template name="chopPunctuation">
1997                                         <xsl:with-param name="chopString" select="$partName"/>
1998                                 </xsl:call-template>
1999                         </mads:partName>
2000                 </xsl:if>
2001         </xsl:template>
2002
2003         <xsl:template name="nameABCDN">
2004                 <xsl:for-each select="marc:subfield[@code='a']">
2005                         <mads:namePart>
2006                                 <xsl:call-template name="chopPunctuation">
2007                                         <xsl:with-param name="chopString" select="."/>
2008                                 </xsl:call-template>
2009                         </mads:namePart>
2010                 </xsl:for-each>
2011                 <xsl:for-each select="marc:subfield[@code='b']">
2012                         <mads:namePart>
2013                                 <xsl:value-of select="."/>
2014                         </mads:namePart>
2015                 </xsl:for-each>
2016                 <xsl:if
2017                         test="marc:subfield[@code='c'] or marc:subfield[@code='d'] or marc:subfield[@code='n']">
2018                         <mads:namePart>
2019                                 <xsl:call-template name="subfieldSelect">
2020                                         <xsl:with-param name="codes">cdn</xsl:with-param>
2021                                 </xsl:call-template>
2022                         </mads:namePart>
2023                 </xsl:if>
2024         </xsl:template>
2025
2026         <xsl:template name="nameABCDQ">
2027                 <mads:namePart>
2028                         <xsl:call-template name="chopPunctuation">
2029                                 <xsl:with-param name="chopString">
2030                                         <xsl:call-template name="subfieldSelect">
2031                                                 <xsl:with-param name="codes">aq</xsl:with-param>
2032                                         </xsl:call-template>
2033                                 </xsl:with-param>
2034                         </xsl:call-template>
2035                 </mads:namePart>
2036                 <xsl:call-template name="termsOfAddress"/>
2037                 <xsl:call-template name="nameDate"/>
2038         </xsl:template>
2039
2040         <xsl:template name="nameACDENQ">
2041                 <mads:namePart>
2042                         <xsl:call-template name="subfieldSelect">
2043                                 <xsl:with-param name="codes">acdenq</xsl:with-param>
2044                         </xsl:call-template>
2045                 </mads:namePart>
2046         </xsl:template>
2047
2048         <xsl:template name="nameDate">
2049                 <xsl:for-each select="marc:subfield[@code='d']">
2050                         <mads:namePart type="date">
2051                                 <xsl:call-template name="chopPunctuation">
2052                                         <xsl:with-param name="chopString" select="."/>
2053                                 </xsl:call-template>
2054                         </mads:namePart>
2055                 </xsl:for-each>
2056         </xsl:template>
2057
2058         <xsl:template name="specialSubfieldSelect">
2059                 <xsl:param name="anyCodes"/>
2060                 <xsl:param name="axis"/>
2061                 <xsl:param name="beforeCodes"/>
2062                 <xsl:param name="afterCodes"/>
2063                 <xsl:variable name="str">
2064                         <xsl:for-each select="marc:subfield">
2065                                 <xsl:if
2066                                         test="contains($anyCodes, @code) or (contains($beforeCodes,@code) and following-sibling::marc:subfield[@code=$axis]) or (contains($afterCodes,@code) and preceding-sibling::marc:subfield[@code=$axis])">
2067                                         <xsl:value-of select="text()"/>
2068                                         <xsl:text> </xsl:text>
2069                                 </xsl:if>
2070                         </xsl:for-each>
2071                 </xsl:variable>
2072                 <xsl:value-of select="substring($str,1,string-length($str)-1)"/>
2073         </xsl:template>
2074
2075         <xsl:template name="termsOfAddress">
2076                 <xsl:if test="marc:subfield[@code='b' or @code='c']">
2077                         <mads:namePart type="termsOfAddress">
2078                                 <xsl:call-template name="chopPunctuation">
2079                                         <xsl:with-param name="chopString">
2080                                                 <xsl:call-template name="subfieldSelect">
2081                                                         <xsl:with-param name="codes">bc</xsl:with-param>
2082                                                 </xsl:call-template>
2083                                         </xsl:with-param>
2084                                 </xsl:call-template>
2085                         </mads:namePart>
2086                 </xsl:if>
2087         </xsl:template>
2088
2089         <xsl:template name="displayLabel">
2090                 <xsl:if test="marc:subfield[@code='z']">
2091                         <xsl:attribute name="displayLabel">
2092                                 <xsl:value-of select="marc:subfield[@code='z']"/>
2093                         </xsl:attribute>
2094                 </xsl:if>
2095                 <xsl:if test="marc:subfield[@code='3']">
2096                         <xsl:attribute name="displayLabel">
2097                                 <xsl:value-of select="marc:subfield[@code='3']"/>
2098                         </xsl:attribute>
2099                 </xsl:if>
2100         </xsl:template>
2101
2102         <xsl:template name="isInvalid">
2103                 <xsl:if test="@code='z'">
2104                         <xsl:attribute name="invalid">yes</xsl:attribute>
2105                 </xsl:if>
2106         </xsl:template>
2107
2108         <xsl:template name="sub2Attribute">
2109                 <!-- 024 -->
2110                 <xsl:if test="../marc:subfield[@code='2']">
2111                         <xsl:attribute name="type">
2112                                 <xsl:value-of select="../marc:subfield[@code='2']"/>
2113                         </xsl:attribute>
2114                 </xsl:if>
2115         </xsl:template>
2116
2117         <xsl:template match="marc:controlfield[@tag=001]">
2118                 <mads:recordIdentifier>
2119                         <xsl:if test="../marc:controlfield[@tag=003]">
2120                                 <xsl:attribute name="source">
2121                                         <xsl:value-of select="../marc:controlfield[@tag=003]"/>
2122                                 </xsl:attribute>
2123                         </xsl:if>
2124                         <xsl:value-of select="."/>
2125                 </mads:recordIdentifier>
2126         </xsl:template>
2127
2128         <xsl:template match="marc:controlfield[@tag=005]">
2129                 <mads:recordChangeDate encoding="iso8601">
2130                         <xsl:value-of select="."/>
2131                 </mads:recordChangeDate>
2132         </xsl:template>
2133
2134         <xsl:template match="marc:controlfield[@tag=008]">
2135                 <mads:recordCreationDate encoding="marc">
2136                         <xsl:value-of select="substring(.,1,6)"/>
2137                 </mads:recordCreationDate>
2138         </xsl:template>
2139
2140         <xsl:template match="marc:datafield[@tag=010]">
2141                 <xsl:for-each select="marc:subfield">
2142                         <mads:identifier type="lccn">
2143                                 <xsl:call-template name="isInvalid"/>
2144                                 <xsl:value-of select="."/>
2145                         </mads:identifier>
2146                 </xsl:for-each>
2147         </xsl:template>
2148
2149         <xsl:template match="marc:datafield[@tag=024]">
2150                 <xsl:for-each select="marc:subfield[not(@code=2)]">
2151                         <mads:identifier>
2152                                 <xsl:call-template name="isInvalid"/>
2153                                 <xsl:call-template name="sub2Attribute"/>
2154                                 <xsl:value-of select="."/>
2155                         </mads:identifier>
2156                 </xsl:for-each>
2157         </xsl:template>
2158
2159         <!-- ========== 372 ========== -->
2160         <xsl:template match="marc:datafield[@tag=372]">
2161                 <mads:fieldOfActivity>
2162                         <xsl:call-template name="subfieldSelect">
2163                                 <xsl:with-param name="codes">a</xsl:with-param>
2164                         </xsl:call-template>
2165                         <xsl:text>-</xsl:text>
2166                         <xsl:call-template name="subfieldSelect">
2167                                 <xsl:with-param name="codes">st</xsl:with-param>
2168                         </xsl:call-template>
2169                 </mads:fieldOfActivity>
2170         </xsl:template>
2171
2172
2173         <!-- ========== 040 ========== -->
2174         <xsl:template match="marc:datafield[@tag=040]/marc:subfield[@code='a']">
2175                 <mads:recordContentSource authority="marcorg">
2176                         <xsl:value-of select="."/>
2177                 </mads:recordContentSource>
2178         </xsl:template>
2179
2180         <xsl:template match="marc:datafield[@tag=040]/marc:subfield[@code='b']">
2181                 <mads:languageOfCataloging>
2182                         <mads:languageTerm authority="iso639-2b" type="code">
2183                                 <xsl:value-of select="."/>
2184                         </mads:languageTerm>
2185                 </mads:languageOfCataloging>
2186         </xsl:template>
2187
2188         <xsl:template match="marc:datafield[@tag=040]/marc:subfield[@code='e']">
2189                 <mads:descriptionStandard>
2190                         <xsl:value-of select="."/>
2191                 </mads:descriptionStandard>
2192         </xsl:template>
2193         
2194         <!-- ========== classification 2.03 ========== -->
2195         
2196         <xsl:template match="marc:datafield[@tag=053]">
2197                 <mads:classification>
2198                         <xsl:call-template name="subfieldSelect">
2199                                 <xsl:with-param name="codes">abcdxyz</xsl:with-param>
2200                                 <xsl:with-param name="delimeter">-</xsl:with-param>
2201                         </xsl:call-template>
2202                 </mads:classification>
2203         </xsl:template>
2204         
2205         <xsl:template match="marc:datafield[@tag=055]">
2206                 <mads:classification>
2207                         <xsl:call-template name="subfieldSelect">
2208                                 <xsl:with-param name="codes">abcdxyz</xsl:with-param>
2209                                 <xsl:with-param name="delimeter">-</xsl:with-param>
2210                         </xsl:call-template>
2211                 </mads:classification>
2212         </xsl:template>
2213         
2214         <xsl:template match="marc:datafield[@tag=060]">
2215                 <mads:classification>
2216                         <xsl:call-template name="subfieldSelect">
2217                                 <xsl:with-param name="codes">abcdxyz</xsl:with-param>
2218                                 <xsl:with-param name="delimeter">-</xsl:with-param>
2219                         </xsl:call-template>
2220                 </mads:classification>
2221         </xsl:template>
2222         <xsl:template match="marc:datafield[@tag=065]">
2223                 <mads:classification>
2224                         <xsl:attribute name="authority">
2225                                 <xsl:value-of select="marc:subfield[@code='2']"/>
2226                         </xsl:attribute>
2227                         <xsl:call-template name="subfieldSelect">
2228                                 <xsl:with-param name="codes">abcdxyz</xsl:with-param>
2229                                 <xsl:with-param name="delimeter">-</xsl:with-param>
2230                         </xsl:call-template>
2231                 </mads:classification>
2232         </xsl:template>
2233         <xsl:template match="marc:datafield[@tag=070]">
2234                 <mads:classification>
2235                         <xsl:call-template name="subfieldSelect">
2236                                 <xsl:with-param name="codes">abcdxyz5</xsl:with-param>
2237                                 <xsl:with-param name="delimeter">-</xsl:with-param>
2238                         </xsl:call-template>
2239                 </mads:classification>
2240         </xsl:template>
2241         <xsl:template match="marc:datafield[@tag=080]">
2242                 <mads:classification>
2243                         <xsl:attribute name="authority">
2244                                 <xsl:value-of select="marc:subfield[@code='2']"/>
2245                         </xsl:attribute>
2246                         <xsl:call-template name="subfieldSelect">
2247                                 <xsl:with-param name="codes">abcdxyz5</xsl:with-param>
2248                                 <xsl:with-param name="delimeter">-</xsl:with-param>
2249                         </xsl:call-template>
2250                 </mads:classification>
2251         </xsl:template>
2252         <xsl:template match="marc:datafield[@tag=082]">
2253                 <mads:classification>
2254                         <xsl:attribute name="authority">
2255                                 <xsl:value-of select="marc:subfield[@code='2']"/>
2256                         </xsl:attribute>
2257                         <xsl:call-template name="subfieldSelect">
2258                                 <xsl:with-param name="codes">abcdxyz5</xsl:with-param>
2259                                 <xsl:with-param name="delimeter">-</xsl:with-param>
2260                         </xsl:call-template>
2261                 </mads:classification>
2262         </xsl:template>
2263         <xsl:template match="marc:datafield[@tag=083]">
2264                 <mads:classification>
2265                         <xsl:attribute name="authority">
2266                                 <xsl:value-of select="marc:subfield[@code='2']"/>
2267                         </xsl:attribute>
2268                         <xsl:call-template name="subfieldSelect">
2269                                 <xsl:with-param name="codes">abcdxyz5</xsl:with-param>
2270                                 <xsl:with-param name="delimeter">-</xsl:with-param>
2271                         </xsl:call-template>
2272                 </mads:classification>
2273         </xsl:template>
2274         <xsl:template match="marc:datafield[@tag=086]">
2275                 <mads:classification>
2276                         <xsl:attribute name="authority">
2277                                 <xsl:value-of select="marc:subfield[@code='2']"/>
2278                         </xsl:attribute>
2279                         <xsl:call-template name="subfieldSelect">
2280                                 <xsl:with-param name="codes">abcdxyz5</xsl:with-param>
2281                                 <xsl:with-param name="delimeter">-</xsl:with-param>
2282                         </xsl:call-template>
2283                 </mads:classification>
2284         </xsl:template>
2285         <xsl:template match="marc:datafield[@tag=087]">
2286                 <mads:classification>
2287                         <xsl:attribute name="authority">
2288                                 <xsl:value-of select="marc:subfield[@code='2']"/>
2289                         </xsl:attribute>
2290                         <xsl:call-template name="subfieldSelect">
2291                                 <xsl:with-param name="codes">abcdxyz5</xsl:with-param>
2292                                 <xsl:with-param name="delimeter">-</xsl:with-param>
2293                         </xsl:call-template>
2294                 </mads:classification>
2295         </xsl:template>
2296         
2297
2298         <!-- ========== names  ========== -->
2299         <xsl:template match="marc:datafield[@tag=100]">
2300                 <mads:name type="personal">
2301                         <xsl:call-template name="setAuthority"/>
2302                         <xsl:call-template name="nameABCDQ"/>
2303                 </mads:name>
2304                 <xsl:apply-templates select="*[marc:subfield[not(contains('abcdeq',@code))]]"/>
2305                 <xsl:call-template name="title"/>
2306                 <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2307         </xsl:template>
2308
2309         <xsl:template match="marc:datafield[@tag=110]">
2310                 <mads:name type="corporate">
2311                         <xsl:call-template name="setAuthority"/>
2312                         <xsl:call-template name="nameABCDN"/>
2313                 </mads:name>
2314                 <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2315         </xsl:template>
2316
2317         <xsl:template match="marc:datafield[@tag=111]">
2318                 <mads:name type="conference">
2319                         <xsl:call-template name="setAuthority"/>
2320                         <xsl:call-template name="nameACDENQ"/>
2321                 </mads:name>
2322                 <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2323         </xsl:template>
2324
2325         <xsl:template match="marc:datafield[@tag=400]">
2326                 <mads:variant>
2327                         <xsl:call-template name="variantTypeAttribute"/>
2328                         <mads:name type="personal">
2329                                 <xsl:call-template name="nameABCDQ"/>
2330                         </mads:name>
2331                         <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2332                         <xsl:call-template name="title"/>
2333                 </mads:variant>
2334         </xsl:template>
2335
2336         <xsl:template match="marc:datafield[@tag=410]">
2337                 <mads:variant>
2338                         <xsl:call-template name="variantTypeAttribute"/>
2339                         <mads:name type="corporate">
2340                                 <xsl:call-template name="nameABCDN"/>
2341                         </mads:name>
2342                         <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2343                 </mads:variant>
2344         </xsl:template>
2345
2346         <xsl:template match="marc:datafield[@tag=411]">
2347                 <mads:variant>
2348                         <xsl:call-template name="variantTypeAttribute"/>
2349                         <mads:name type="conference">
2350                                 <xsl:call-template name="nameACDENQ"/>
2351                         </mads:name>
2352                         <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2353                 </mads:variant>
2354         </xsl:template>
2355
2356         <xsl:template match="marc:datafield[@tag=500]|marc:datafield[@tag=700]">
2357                 <mads:related>
2358                         <xsl:call-template name="relatedTypeAttribute"/>
2359                         <!-- <xsl:call-template name="uri"/> -->
2360                         <mads:name type="personal">
2361                                 <xsl:call-template name="setAuthority"/>
2362                                 <xsl:call-template name="nameABCDQ"/>
2363                         </mads:name>
2364                         <xsl:call-template name="title"/>
2365                         <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2366                 </mads:related>
2367         </xsl:template>
2368
2369         <xsl:template match="marc:datafield[@tag=510]|marc:datafield[@tag=710]">
2370                 <mads:related>
2371                         <xsl:call-template name="relatedTypeAttribute"/>
2372                         <!-- <xsl:call-template name="uri"/> -->
2373                         <mads:name type="corporate">
2374                                 <xsl:call-template name="setAuthority"/>
2375                                 <xsl:call-template name="nameABCDN"/>
2376                         </mads:name>
2377                         <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2378                 </mads:related>
2379         </xsl:template>
2380
2381         <xsl:template match="marc:datafield[@tag=511]|marc:datafield[@tag=711]">
2382                 <mads:related>
2383                         <xsl:call-template name="relatedTypeAttribute"/>
2384                         <!-- <xsl:call-template name="uri"/> -->
2385                         <mads:name type="conference">
2386                                 <xsl:call-template name="setAuthority"/>
2387                                 <xsl:call-template name="nameACDENQ"/>
2388                         </mads:name>
2389                         <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2390                 </mads:related>
2391         </xsl:template>
2392
2393         <!-- ========== titles  ========== -->
2394         <xsl:template match="marc:datafield[@tag=130]">
2395                 <xsl:call-template name="uniform-title"/>
2396                 <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2397         </xsl:template>
2398
2399         <xsl:template match="marc:datafield[@tag=430]">
2400                 <mads:variant>
2401                         <xsl:call-template name="variantTypeAttribute"/>
2402                         <xsl:call-template name="uniform-title"/>
2403                         <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2404                 </mads:variant>
2405         </xsl:template>
2406
2407         <xsl:template match="marc:datafield[@tag=530]|marc:datafield[@tag=730]">
2408                 <mads:related>
2409                         <xsl:call-template name="relatedTypeAttribute"/>
2410                         <xsl:call-template name="uniform-title"/>
2411                         <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2412                 </mads:related>
2413         </xsl:template>
2414
2415         <xsl:template name="title">
2416                 <xsl:variable name="hasTitle">
2417                         <xsl:for-each select="marc:subfield">
2418                                 <xsl:if test="(contains('tfghklmors',@code) )">
2419                                         <xsl:value-of select="@code"/>
2420                                 </xsl:if>
2421                         </xsl:for-each>
2422                 </xsl:variable>
2423                 <xsl:if test="string-length($hasTitle) &gt; 0 ">
2424                         <mads:titleInfo>
2425                                 <xsl:call-template name="setAuthority"/>
2426                                 <mads:title>
2427                                         <xsl:variable name="str">
2428                                                 <xsl:for-each select="marc:subfield">
2429                                                         <xsl:if test="(contains('atfghklmors',@code) )">
2430                                                                 <xsl:value-of select="text()"/>
2431                                                                 <xsl:text> </xsl:text>
2432                                                         </xsl:if>
2433                                                 </xsl:for-each>
2434                                         </xsl:variable>
2435                                         <xsl:call-template name="chopPunctuation">
2436                                                 <xsl:with-param name="chopString">
2437                                                         <xsl:value-of select="substring($str,1,string-length($str)-1)"/>
2438                                                 </xsl:with-param>
2439                                         </xsl:call-template>
2440                                 </mads:title>
2441                                 <xsl:call-template name="part"/>
2442                                 <!-- <xsl:call-template name="uri"/> -->
2443                         </mads:titleInfo>
2444                 </xsl:if>
2445         </xsl:template>
2446
2447         <xsl:template name="uniform-title">
2448                 <xsl:variable name="hasTitle">
2449                         <xsl:for-each select="marc:subfield">
2450                                 <xsl:if test="(contains('atfghklmors',@code) )">
2451                                         <xsl:value-of select="@code"/>
2452                                 </xsl:if>
2453                         </xsl:for-each>
2454                 </xsl:variable>
2455                 <xsl:if test="string-length($hasTitle) &gt; 0 ">
2456                         <mads:titleInfo>
2457                                 <xsl:call-template name="setAuthority"/>
2458                                 <mads:title>
2459                                         <xsl:variable name="str">
2460                                                 <xsl:for-each select="marc:subfield">
2461                                                         <xsl:if test="(contains('adfghklmors',@code) )">
2462                                                                 <xsl:value-of select="text()"/>
2463                                                                 <xsl:text> </xsl:text>
2464                                                         </xsl:if>
2465                                                 </xsl:for-each>
2466                                         </xsl:variable>
2467                                         <xsl:call-template name="chopPunctuation">
2468                                                 <xsl:with-param name="chopString">
2469                                                         <xsl:value-of select="substring($str,1,string-length($str)-1)"/>
2470                                                 </xsl:with-param>
2471                                         </xsl:call-template>
2472                                 </mads:title>
2473                                 <xsl:call-template name="part"/>
2474                                 <!-- <xsl:call-template name="uri"/> -->
2475                         </mads:titleInfo>
2476                 </xsl:if>
2477         </xsl:template>
2478
2479
2480         <!-- ========== topics  ========== -->
2481         <xsl:template match="marc:subfield[@code='x']">
2482                 <mads:topic>
2483                         <xsl:call-template name="chopPunctuation">
2484                                 <xsl:with-param name="chopString">
2485                                         <xsl:value-of select="."/>
2486                                 </xsl:with-param>
2487                         </xsl:call-template>
2488                 </mads:topic>
2489         </xsl:template>
2490         
2491         <!-- 2.06 fix -->
2492         <xsl:template
2493                 match="marc:datafield[@tag=150][marc:subfield[@code='a' or @code='b']]|marc:datafield[@tag=180][marc:subfield[@code='x']]">
2494                 <xsl:call-template name="topic"/>
2495                 <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2496         </xsl:template>
2497         <xsl:template
2498                 match="marc:datafield[@tag=450][marc:subfield[@code='a' or @code='b']]|marc:datafield[@tag=480][marc:subfield[@code='x']]">
2499                 <mads:variant>
2500                         <xsl:call-template name="variantTypeAttribute"/>
2501                         <xsl:call-template name="topic"/>
2502                 </mads:variant>
2503         </xsl:template>
2504         <xsl:template
2505                 match="marc:datafield[@tag=550 or @tag=750][marc:subfield[@code='a' or @code='b']]">
2506                 <mads:related>
2507                         <xsl:call-template name="relatedTypeAttribute"/>
2508                         <!-- <xsl:call-template name="uri"/> -->
2509                         <xsl:call-template name="topic"/>
2510                         <xsl:apply-templates select="marc:subfield[@code='z']"/>
2511                 </mads:related>
2512         </xsl:template>
2513         <xsl:template name="topic">
2514                 <mads:topic>
2515                         <xsl:call-template name="setAuthority"/>
2516                         <!-- tmee2006 dedupe 550a
2517                         <xsl:if test="@tag=550 or @tag=750">
2518                                 <xsl:call-template name="subfieldSelect">
2519                                         <xsl:with-param name="codes">ab</xsl:with-param>
2520                                 </xsl:call-template>
2521                         </xsl:if>       
2522                         -->
2523                         <xsl:choose>
2524                                 <xsl:when test="@tag=180 or @tag=480 or @tag=580 or @tag=780">
2525                                         <xsl:call-template name="chopPunctuation">
2526                                                 <xsl:with-param name="chopString">
2527                                                         <xsl:apply-templates select="marc:subfield[@code='x']"/>
2528                                                 </xsl:with-param>
2529                                         </xsl:call-template>
2530                                 </xsl:when>
2531                         </xsl:choose>
2532                         <xsl:call-template name="chopPunctuation">
2533                                 <xsl:with-param name="chopString">
2534                                         <xsl:choose>
2535                                                 <xsl:when test="@tag=180 or @tag=480 or @tag=580 or @tag=780">
2536                                                         <xsl:apply-templates select="marc:subfield[@code='x']"/>
2537                                                 </xsl:when>
2538                                                 <xsl:otherwise>
2539                                                         <xsl:call-template name="subfieldSelect">
2540                                                                 <xsl:with-param name="codes">ab</xsl:with-param>
2541                                                         </xsl:call-template>
2542                                                 </xsl:otherwise>
2543                                         </xsl:choose>
2544                                 </xsl:with-param>
2545                         </xsl:call-template>
2546                 </mads:topic>
2547         </xsl:template>
2548
2549         <!-- ========= temporals  ========== -->
2550         <xsl:template match="marc:subfield[@code='y']">
2551                 <mads:temporal>
2552                         <xsl:call-template name="chopPunctuation">
2553                                 <xsl:with-param name="chopString">
2554                                         <xsl:value-of select="."/>
2555                                 </xsl:with-param>
2556                         </xsl:call-template>
2557                 </mads:temporal>
2558         </xsl:template>
2559         <xsl:template
2560                 match="marc:datafield[@tag=148][marc:subfield[@code='a']]|marc:datafield[@tag=182 ][marc:subfield[@code='y']]">
2561                 <xsl:call-template name="temporal"/>
2562         </xsl:template>
2563         <xsl:template
2564                 match="marc:datafield[@tag=448][marc:subfield[@code='a']]|marc:datafield[@tag=482][marc:subfield[@code='y']]">
2565                 <mads:variant>
2566                         <xsl:call-template name="variantTypeAttribute"/>
2567                         <xsl:call-template name="temporal"/>
2568                 </mads:variant>
2569         </xsl:template>
2570         <xsl:template
2571                 match="marc:datafield[@tag=548 or @tag=748][marc:subfield[@code='a']]|marc:datafield[@tag=582 or @tag=782][marc:subfield[@code='y']]">
2572                 <mads:related>
2573                         <xsl:call-template name="relatedTypeAttribute"/>
2574                         <!-- <xsl:call-template name="uri"/> -->
2575                         <xsl:call-template name="temporal"/>
2576                 </mads:related>
2577         </xsl:template>
2578         <xsl:template name="temporal">
2579                 <mads:temporal>
2580                         <xsl:call-template name="setAuthority"/>
2581                         <xsl:if test="@tag=548 or @tag=748">
2582                                 <xsl:value-of select="marc:subfield[@code='a']"/>
2583                         </xsl:if>
2584                         <xsl:call-template name="chopPunctuation">
2585                                 <xsl:with-param name="chopString">
2586                                         <xsl:choose>
2587                                                 <xsl:when test="@tag=182 or @tag=482 or @tag=582 or @tag=782">
2588                                                         <xsl:apply-templates select="marc:subfield[@code='y']"/>
2589                                                 </xsl:when>
2590                                                 <xsl:otherwise>
2591                                                         <xsl:value-of select="marc:subfield[@code='a']"/>
2592                                                 </xsl:otherwise>
2593                                         </xsl:choose>
2594                                 </xsl:with-param>
2595                         </xsl:call-template>
2596                 </mads:temporal>
2597                 <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2598         </xsl:template>
2599
2600         <!-- ========== genre  ========== -->
2601         <xsl:template match="marc:subfield[@code='v']">
2602                 <mads:genre>
2603                         <xsl:call-template name="chopPunctuation">
2604                                 <xsl:with-param name="chopString">
2605                                         <xsl:value-of select="."/>
2606                                 </xsl:with-param>
2607                         </xsl:call-template>
2608                 </mads:genre>
2609         </xsl:template>
2610         <xsl:template
2611                 match="marc:datafield[@tag=155][marc:subfield[@code='a']]|marc:datafield[@tag=185][marc:subfield[@code='v']]">
2612                 <xsl:call-template name="genre"/>
2613         </xsl:template>
2614         <xsl:template
2615                 match="marc:datafield[@tag=455][marc:subfield[@code='a']]|marc:datafield[@tag=485 ][marc:subfield[@code='v']]">
2616                 <mads:variant>
2617                         <xsl:call-template name="variantTypeAttribute"/>
2618                         <xsl:call-template name="genre"/>
2619                 </mads:variant>
2620         </xsl:template>
2621         <!--
2622         <xsl:template match="marc:datafield[@tag=555]">
2623                 <mads:related>
2624                         <xsl:call-template name="relatedTypeAttribute"/>
2625                         <xsl:call-template name="uri"/>
2626                         <xsl:call-template name="genre"/>
2627                 </mads:related>
2628         </xsl:template>
2629         -->
2630         <xsl:template
2631                 match="marc:datafield[@tag=555 or @tag=755][marc:subfield[@code='a']]|marc:datafield[@tag=585][marc:subfield[@code='v']]">
2632                 <mads:related>
2633                         <xsl:call-template name="relatedTypeAttribute"/>
2634                         <xsl:call-template name="genre"/>
2635                 </mads:related>
2636         </xsl:template>
2637         <xsl:template name="genre">
2638                 <mads:genre>
2639                         <xsl:if test="@tag=555">
2640                                 <xsl:value-of select="marc:subfield[@code='a']"/>
2641                         </xsl:if>
2642                         <xsl:call-template name="setAuthority"/>
2643                         <xsl:call-template name="chopPunctuation">
2644                                 <xsl:with-param name="chopString">
2645                                         <xsl:choose>
2646                                                 <!-- 2.07 fix -->
2647                                                 <xsl:when test="@tag='555'"/>
2648                                                 <xsl:when test="@tag=185 or @tag=485 or @tag=585">
2649                                                         <xsl:apply-templates select="marc:subfield[@code='v']"/>
2650                                                 </xsl:when>
2651                                                 <xsl:otherwise>
2652                                                         <xsl:value-of select="marc:subfield[@code='a']"/>
2653                                                 </xsl:otherwise>
2654                                         </xsl:choose>
2655                                 </xsl:with-param>
2656                         </xsl:call-template>
2657                 </mads:genre>
2658                 <xsl:apply-templates/>
2659         </xsl:template>
2660
2661         <!-- ========= geographic  ========== -->
2662         <xsl:template match="marc:subfield[@code='z']">
2663                 <mads:geographic>
2664                         <xsl:call-template name="chopPunctuation">
2665                                 <xsl:with-param name="chopString">
2666                                         <xsl:value-of select="."/>
2667                                 </xsl:with-param>
2668                         </xsl:call-template>
2669                 </mads:geographic>
2670         </xsl:template>
2671         <xsl:template name="geographic">
2672                 <mads:geographic>
2673                         <!-- 2.14 -->
2674                         <xsl:call-template name="setAuthority"/>
2675                         <!-- 2.13 -->
2676                         <xsl:if test="@tag=151 or @tag=551">
2677                                 <xsl:value-of select="marc:subfield[@code='a']"/>
2678                         </xsl:if>
2679                         <xsl:call-template name="chopPunctuation">
2680                                 <xsl:with-param name="chopString">
2681                                                 <xsl:if test="@tag=181 or @tag=481 or @tag=581">
2682                                                                 <xsl:apply-templates select="marc:subfield[@code='z']"/>
2683                                                 </xsl:if>
2684                                                 <!-- 2.13
2685                                                         <xsl:choose>
2686                                                 <xsl:when test="@tag=181 or @tag=481 or @tag=581">
2687                                                         <xsl:apply-templates select="marc:subfield[@code='z']"/>
2688                                                 </xsl:when>
2689                                         
2690                                                 <xsl:otherwise>
2691                                                         <xsl:value-of select="marc:subfield[@code='a']"/>
2692                                                 </xsl:otherwise>
2693                                                 </xsl:choose>
2694                                                 -->
2695                                 </xsl:with-param>
2696                         </xsl:call-template>
2697                 </mads:geographic>
2698                 <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2699         </xsl:template>
2700         <xsl:template
2701                 match="marc:datafield[@tag=151][marc:subfield[@code='a']]|marc:datafield[@tag=181][marc:subfield[@code='z']]">
2702                 <xsl:call-template name="geographic"/>
2703         </xsl:template>
2704         <xsl:template
2705                 match="marc:datafield[@tag=451][marc:subfield[@code='a']]|marc:datafield[@tag=481][marc:subfield[@code='z']]">
2706                 <mads:variant>
2707                         <xsl:call-template name="variantTypeAttribute"/>
2708                         <xsl:call-template name="geographic"/>
2709                 </mads:variant>
2710         </xsl:template>
2711         <xsl:template
2712                 match="marc:datafield[@tag=551]|marc:datafield[@tag=581][marc:subfield[@code='z']]">
2713                 <mads:related>
2714                         <xsl:call-template name="relatedTypeAttribute"/>
2715                         <!-- <xsl:call-template name="uri"/> -->
2716                         <xsl:call-template name="geographic"/>
2717                 </mads:related>
2718         </xsl:template>
2719         <xsl:template match="marc:datafield[@tag=580]">
2720                 <mads:related>
2721                         <xsl:call-template name="relatedTypeAttribute"/>
2722                         <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2723                 </mads:related>
2724         </xsl:template>
2725         <xsl:template
2726                 match="marc:datafield[@tag=751][marc:subfield[@code='z']]|marc:datafield[@tag=781][marc:subfield[@code='z']]">
2727                 <mads:related>
2728                         <xsl:call-template name="relatedTypeAttribute"/>
2729                         <xsl:call-template name="geographic"/>
2730                 </mads:related>
2731         </xsl:template>
2732         <xsl:template match="marc:datafield[@tag=755]">
2733                 <mads:related>
2734                         <xsl:call-template name="relatedTypeAttribute"/>
2735                         <xsl:call-template name="setAuthority"/>
2736                         <xsl:call-template name="genre"/>
2737                         <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2738                 </mads:related>
2739         </xsl:template>
2740         <xsl:template match="marc:datafield[@tag=780]">
2741                 <mads:related>
2742                         <xsl:call-template name="relatedTypeAttribute"/>
2743                         <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2744                 </mads:related>
2745         </xsl:template>
2746         <xsl:template match="marc:datafield[@tag=785]">
2747                 <mads:related>
2748                         <xsl:call-template name="relatedTypeAttribute"/>
2749                         <xsl:apply-templates select="marc:subfield[@code!='i']"/>
2750                 </mads:related>
2751         </xsl:template>
2752
2753         <!-- ========== notes  ========== -->
2754         <xsl:template match="marc:datafield[667 &lt;= @tag and @tag &lt;= 688]">
2755                 <mads:note>
2756                         <xsl:choose>
2757                                 <xsl:when test="@tag=667">
2758                                         <xsl:attribute name="type">nonpublic</xsl:attribute>
2759                                 </xsl:when>
2760                                 <xsl:when test="@tag=670">
2761                                         <xsl:attribute name="type">source</xsl:attribute>
2762                                 </xsl:when>
2763                                 <xsl:when test="@tag=675">
2764                                         <xsl:attribute name="type">notFound</xsl:attribute>
2765                                 </xsl:when>
2766                                 <xsl:when test="@tag=678">
2767                                         <xsl:attribute name="type">history</xsl:attribute>
2768                                 </xsl:when>
2769                                 <xsl:when test="@tag=681">
2770                                         <xsl:attribute name="type">subject example</xsl:attribute>
2771                                 </xsl:when>
2772                                 <xsl:when test="@tag=682">
2773                                         <xsl:attribute name="type">deleted heading information</xsl:attribute>
2774                                 </xsl:when>
2775                                 <xsl:when test="@tag=688">
2776                                         <xsl:attribute name="type">application history</xsl:attribute>
2777                                 </xsl:when>
2778                         </xsl:choose>
2779                         <xsl:call-template name="chopPunctuation">
2780                                 <xsl:with-param name="chopString">
2781                                         <xsl:choose>
2782                                                 <xsl:when test="@tag=667 or @tag=675">
2783                                                         <xsl:value-of select="marc:subfield[@code='a']"/>
2784                                                 </xsl:when>
2785                                                 <xsl:when test="@tag=670 or @tag=678">
2786                                                         <xsl:call-template name="subfieldSelect">
2787                                                                 <xsl:with-param name="codes">ab</xsl:with-param>
2788                                                         </xsl:call-template>
2789                                                 </xsl:when>
2790                                                 <xsl:when test="680 &lt;= @tag and @tag &lt;=688">
2791                                                         <xsl:call-template name="subfieldSelect">
2792                                                                 <xsl:with-param name="codes">ai</xsl:with-param>
2793                                                         </xsl:call-template>
2794                                                 </xsl:when>
2795                                         </xsl:choose>
2796                                 </xsl:with-param>
2797                         </xsl:call-template>
2798                 </mads:note>
2799         </xsl:template>
2800
2801         <!-- ========== url  ========== -->
2802         <xsl:template match="marc:datafield[@tag=856][marc:subfield[@code='u']]">
2803                 <mads:url>
2804                         <xsl:if test="marc:subfield[@code='z' or @code='3']">
2805                                 <xsl:attribute name="displayLabel">
2806                                         <xsl:call-template name="subfieldSelect">
2807                                                 <xsl:with-param name="codes">z3</xsl:with-param>
2808                                         </xsl:call-template>
2809                                 </xsl:attribute>
2810                         </xsl:if>
2811                         <xsl:value-of select="marc:subfield[@code='u']"/>
2812                 </mads:url>
2813         </xsl:template>
2814
2815         <xsl:template name="relatedTypeAttribute">
2816                 <xsl:choose>
2817                         <xsl:when
2818                                 test="@tag=500 or @tag=510 or @tag=511 or @tag=548 or @tag=550 or @tag=551 or @tag=555 or @tag=580 or @tag=581 or @tag=582 or @tag=585">
2819                                 <xsl:if test="substring(marc:subfield[@code='w'],1,1)='a'">
2820                                         <xsl:attribute name="type">earlier</xsl:attribute>
2821                                 </xsl:if>
2822                                 <xsl:if test="substring(marc:subfield[@code='w'],1,1)='b'">
2823                                         <xsl:attribute name="type">later</xsl:attribute>
2824                                 </xsl:if>
2825                                 <xsl:if test="substring(marc:subfield[@code='w'],1,1)='t'">
2826                                         <xsl:attribute name="type">parentOrg</xsl:attribute>
2827                                 </xsl:if>
2828                                 <xsl:if test="substring(marc:subfield[@code='w'],1,1)='g'">
2829                                         <xsl:attribute name="type">broader</xsl:attribute>
2830                                 </xsl:if>
2831                                 <xsl:if test="substring(marc:subfield[@code='w'],1,1)='h'">
2832                                         <xsl:attribute name="type">narrower</xsl:attribute>
2833                                 </xsl:if>
2834                                 <xsl:if test="substring(marc:subfield[@code='w'],1,1)='r'">
2835                                         <xsl:attribute name="type">other</xsl:attribute>
2836                                 </xsl:if>
2837                                 <xsl:if test="contains('fin|', substring(marc:subfield[@code='w'],1,1))">
2838                                         <xsl:attribute name="type">other</xsl:attribute>
2839                                 </xsl:if>
2840                         </xsl:when>
2841                         <xsl:when test="@tag=530 or @tag=730">
2842                                 <xsl:attribute name="type">other</xsl:attribute>
2843                         </xsl:when>
2844                         <xsl:otherwise>
2845                                 <!-- 7xx -->
2846                                 <xsl:attribute name="type">equivalent</xsl:attribute>
2847                         </xsl:otherwise>
2848                 </xsl:choose>
2849                 <xsl:apply-templates select="marc:subfield[@code='i']"/>
2850         </xsl:template>
2851         
2852
2853
2854         <xsl:template name="variantTypeAttribute">
2855                 <xsl:choose>
2856                         <xsl:when
2857                                 test="@tag=400 or @tag=410 or @tag=411 or @tag=451 or @tag=455 or @tag=480 or @tag=481 or @tag=482 or @tag=485">
2858                                 <xsl:if test="substring(marc:subfield[@code='w'],1,1)='d'">
2859                                         <xsl:attribute name="type">acronym</xsl:attribute>
2860                                 </xsl:if>
2861                                 <xsl:if test="substring(marc:subfield[@code='w'],1,1)='n'">
2862                                         <xsl:attribute name="type">other</xsl:attribute>
2863                                 </xsl:if>
2864                                 <xsl:if test="contains('fit', substring(marc:subfield[@code='w'],1,1))">
2865                                         <xsl:attribute name="type">other</xsl:attribute>
2866                                 </xsl:if>
2867                         </xsl:when>
2868                         <xsl:otherwise>
2869                                 <!-- 430  -->
2870                                 <xsl:attribute name="type">other</xsl:attribute>
2871                         </xsl:otherwise>
2872                 </xsl:choose>
2873                 <xsl:apply-templates select="marc:subfield[@code='i']"/>
2874         </xsl:template>
2875
2876         <xsl:template name="setAuthority">
2877                 <xsl:choose>
2878                         <!-- can be called from the datafield or subfield level, so "..//@tag" means
2879                         the tag can be at the subfield's parent level or at the datafields own level -->
2880
2881                         <xsl:when
2882                                 test="ancestor-or-self::marc:datafield/@tag=100 and (@ind1=0 or @ind1=1) and $controlField008-11='a' and $controlField008-14='a'">
2883                                 <xsl:attribute name="authority">
2884                                         <xsl:text>naf</xsl:text>
2885                                 </xsl:attribute>
2886                         </xsl:when>
2887                         <xsl:when
2888                                 test="ancestor-or-self::marc:datafield/@tag=100 and (@ind1=0 or @ind1=1) and $controlField008-11='a' and $controlField008-14='b'">
2889                                 <xsl:attribute name="authority">
2890                                         <xsl:text>lcsh</xsl:text>
2891                                 </xsl:attribute>
2892                         </xsl:when>
2893                         <xsl:when
2894                                 test="ancestor-or-self::marc:datafield/@tag=100 and (@ind1=0 or @ind1=1) and $controlField008-11='k'">
2895                                 <xsl:attribute name="authority">
2896                                         <xsl:text>lacnaf</xsl:text>
2897                                 </xsl:attribute>
2898                         </xsl:when>
2899                         <xsl:when
2900                                 test="ancestor-or-self::marc:datafield/@tag=100 and @ind1=3 and $controlField008-11='a' and $controlField008-14='b'">
2901                                 <xsl:attribute name="authority">
2902                                         <xsl:text>lcsh</xsl:text>
2903                                 </xsl:attribute>
2904                         </xsl:when>
2905                         <xsl:when
2906                                 test="ancestor-or-self::marc:datafield/@tag=100 and @ind1=3 and $controlField008-11='k' and $controlField008-14='b'">
2907                                 <xsl:attribute name="authority">cash</xsl:attribute>
2908                         </xsl:when>
2909                         <xsl:when
2910                                 test="ancestor-or-self::marc:datafield/@tag=110 and $controlField008-11='a' and $controlField008-14='a'">
2911                                 <xsl:attribute name="authority">naf</xsl:attribute>
2912                         </xsl:when>
2913                         <xsl:when
2914                                 test="ancestor-or-self::marc:datafield/@tag=110 and $controlField008-11='a' and $controlField008-14='b'">
2915                                 <xsl:attribute name="authority">lcsh</xsl:attribute>
2916                         </xsl:when>
2917                         <xsl:when
2918                                 test="ancestor-or-self::marc:datafield/@tag=110 and $controlField008-11='k' and $controlField008-14='a'">
2919                                 <xsl:attribute name="authority">
2920                                         <xsl:text>lacnaf</xsl:text>
2921                                 </xsl:attribute>
2922                         </xsl:when>
2923                         <xsl:when
2924                                 test="ancestor-or-self::marc:datafield/@tag=110 and $controlField008-11='k' and $controlField008-14='b'">
2925                                 <xsl:attribute name="authority">
2926                                         <xsl:text>cash</xsl:text>
2927                                 </xsl:attribute>
2928                         </xsl:when>
2929                         <xsl:when
2930                                 test="100 &lt;= ancestor-or-self::marc:datafield/@tag and ancestor-or-self::marc:datafield/@tag &lt;= 155 and $controlField008-11='b'">
2931                                 <xsl:attribute name="authority">
2932                                         <xsl:text>lcshcl</xsl:text>
2933                                 </xsl:attribute>
2934                         </xsl:when>
2935                         <xsl:when
2936                                 test="(ancestor-or-self::marc:datafield/@tag=100 or ancestor-or-self::marc:datafield/@tag=110 or ancestor-or-self::marc:datafield/@tag=111 or ancestor-or-self::marc:datafield/@tag=130 or ancestor-or-self::marc:datafield/@tag=151) and $controlField008-11='c'">
2937                                 <xsl:attribute name="authority">
2938                                         <xsl:text>nlmnaf</xsl:text>
2939                                 </xsl:attribute>
2940                         </xsl:when>
2941                         <xsl:when
2942                                 test="(ancestor-or-self::marc:datafield/@tag=100 or ancestor-or-self::marc:datafield/@tag=110 or ancestor-or-self::marc:datafield/@tag=111 or ancestor-or-self::marc:datafield/@tag=130 or ancestor-or-self::marc:datafield/@tag=151) and $controlField008-11='d'">
2943                                 <xsl:attribute name="authority">
2944                                         <xsl:text>nalnaf</xsl:text>
2945                                 </xsl:attribute>
2946                         </xsl:when>
2947                         <xsl:when
2948                                 test="100 &lt;= ancestor-or-self::marc:datafield/@tag and ancestor-or-self::marc:datafield/@tag &lt;= 155 and $controlField008-11='r'">
2949                                 <xsl:attribute name="authority">
2950                                         <xsl:text>aat</xsl:text>
2951                                 </xsl:attribute>
2952                         </xsl:when>
2953                         <xsl:when
2954                                 test="100 &lt;= ancestor-or-self::marc:datafield/@tag and ancestor-or-self::marc:datafield/@tag &lt;= 155 and $controlField008-11='s'">
2955                                 <xsl:attribute name="authority">sears</xsl:attribute>
2956                         </xsl:when>
2957                         <xsl:when
2958                                 test="100 &lt;= ancestor-or-self::marc:datafield/@tag and ancestor-or-self::marc:datafield/@tag &lt;= 155 and $controlField008-11='v'">
2959                                 <xsl:attribute name="authority">rvm</xsl:attribute>
2960                         </xsl:when>
2961                         <xsl:when
2962                                 test="100 &lt;= ancestor-or-self::marc:datafield/@tag and ancestor-or-self::marc:datafield/@tag &lt;= 155 and $controlField008-11='z'">
2963                                 <xsl:attribute name="authority">
2964                                         <xsl:value-of
2965                                                 select="../marc:datafield[ancestor-or-self::marc:datafield/@tag=040]/marc:subfield[@code='f']"
2966                                         />
2967                                 </xsl:attribute>
2968                         </xsl:when>
2969                         <xsl:when
2970                                 test="(ancestor-or-self::marc:datafield/@tag=111 or ancestor-or-self::marc:datafield/@tag=130) and $controlField008-11='a' and $controlField008-14='a'">
2971                                 <xsl:attribute name="authority">
2972                                         <xsl:text>naf</xsl:text>
2973                                 </xsl:attribute>
2974                         </xsl:when>
2975                         <xsl:when
2976                                 test="(ancestor-or-self::marc:datafield/@tag=111 or ancestor-or-self::marc:datafield/@tag=130) and $controlField008-11='a' and $controlField008-14='b'">
2977                                 <xsl:attribute name="authority">
2978                                         <xsl:text>lcsh</xsl:text>
2979                                 </xsl:attribute>
2980                         </xsl:when>
2981                         <xsl:when
2982                                 test="(ancestor-or-self::marc:datafield/@tag=111 or ancestor-or-self::marc:datafield/@tag=130) and $controlField008-11='k' ">
2983                                 <xsl:attribute name="authority">
2984                                         <xsl:text>lacnaf</xsl:text>
2985                                 </xsl:attribute>
2986                         </xsl:when>
2987                         <xsl:when
2988                                 test="(ancestor-or-self::marc:datafield/@tag=148 or ancestor-or-self::marc:datafield/@tag=150  or ancestor-or-self::marc:datafield/@tag=155) and $controlField008-11='a' ">
2989                                 <xsl:attribute name="authority">
2990                                         <xsl:text>lcsh</xsl:text>
2991                                 </xsl:attribute>
2992                         </xsl:when>
2993                         <xsl:when
2994                                 test="(ancestor-or-self::marc:datafield/@tag=148 or ancestor-or-self::marc:datafield/@tag=150  or ancestor-or-self::marc:datafield/@tag=155) and $controlField008-11='a' ">
2995                                 <xsl:attribute name="authority">
2996                                         <xsl:text>lcsh</xsl:text>
2997                                 </xsl:attribute>
2998                         </xsl:when>
2999                         <xsl:when
3000                                 test="(ancestor-or-self::marc:datafield/@tag=148 or ancestor-or-self::marc:datafield/@tag=150  or ancestor-or-self::marc:datafield/@tag=155) and $controlField008-11='c' ">
3001                                 <xsl:attribute name="authority">
3002                                         <xsl:text>mesh</xsl:text>
3003                                 </xsl:attribute>
3004                         </xsl:when>
3005                         <xsl:when
3006                                 test="(ancestor-or-self::marc:datafield/@tag=148 or ancestor-or-self::marc:datafield/@tag=150  or ancestor-or-self::marc:datafield/@tag=155) and $controlField008-11='d' ">
3007                                 <xsl:attribute name="authority">
3008                                         <xsl:text>nal</xsl:text>
3009                                 </xsl:attribute>
3010                         </xsl:when>
3011                         <xsl:when
3012                                 test="(ancestor-or-self::marc:datafield/@tag=148 or ancestor-or-self::marc:datafield/@tag=150  or ancestor-or-self::marc:datafield/@tag=155) and $controlField008-11='k' ">
3013                                 <xsl:attribute name="authority">
3014                                         <xsl:text>cash</xsl:text>
3015                                 </xsl:attribute>
3016                         </xsl:when>
3017                         <xsl:when
3018                                 test="ancestor-or-self::marc:datafield/@tag=151 and $controlField008-11='a' and $controlField008-14='a'">
3019                                 <xsl:attribute name="authority">
3020                                         <xsl:text>naf</xsl:text>
3021                                 </xsl:attribute>
3022                         </xsl:when>
3023                         <xsl:when
3024                                 test="ancestor-or-self::marc:datafield/@tag=151 and $controlField008-11='a' and $controlField008-14='b'">
3025                                 <xsl:attribute name="authority">lcsh</xsl:attribute>
3026                         </xsl:when>
3027                         <xsl:when
3028                                 test="ancestor-or-self::marc:datafield/@tag=151 and $controlField008-11='k' and $controlField008-14='a'">
3029                                 <xsl:attribute name="authority">lacnaf</xsl:attribute>
3030                         </xsl:when>
3031                         <xsl:when
3032                                 test="ancestor-or-self::marc:datafield/@tag=151 and $controlField008-11='k' and $controlField008-14='b'">
3033                                 <xsl:attribute name="authority">cash</xsl:attribute>
3034                         </xsl:when>
3035                         <xsl:when
3036                                 test="(..//ancestor-or-self::marc:datafield/@tag=180 or ..//ancestor-or-self::marc:datafield/@tag=181 or ..//ancestor-or-self::marc:datafield/@tag=182 or ..//ancestor-or-self::marc:datafield/@tag=185) and $controlField008-11='a'">
3037                                 <xsl:attribute name="authority">lcsh</xsl:attribute>
3038                         </xsl:when>
3039                         <xsl:when
3040                                 test="ancestor-or-self::marc:datafield/@tag=700 and (@ind1='0' or @ind1='1') and @ind2='0'">
3041                                 <xsl:attribute name="authority">naf</xsl:attribute>
3042                         </xsl:when>
3043                         <xsl:when
3044                                 test="ancestor-or-self::marc:datafield/@tag=700 and (@ind1='0' or @ind1='1') and @ind2='5'">
3045                                 <xsl:attribute name="authority">lacnaf</xsl:attribute>
3046                         </xsl:when>
3047                         <xsl:when test="ancestor-or-self::marc:datafield/@tag=700 and @ind1='3' and @ind2='0'">
3048                                 <xsl:attribute name="authority">lcsh</xsl:attribute>
3049                         </xsl:when>
3050                         <xsl:when test="ancestor-or-self::marc:datafield/@tag=700 and @ind1='3' and @ind2='5'">
3051                                 <xsl:attribute name="authority">cash</xsl:attribute>
3052                         </xsl:when>
3053                         <xsl:when
3054                                 test="(700 &lt;= ancestor-or-self::marc:datafield/@tag and ancestor-or-self::marc:datafield/@tag &lt;= 755 ) and @ind2='1'">
3055                                 <xsl:attribute name="authority">lcshcl</xsl:attribute>
3056                         </xsl:when>
3057                         <xsl:when
3058                                 test="(ancestor-or-self::marc:datafield/@tag=700 or ancestor-or-self::marc:datafield/@tag=710 or ancestor-or-self::marc:datafield/@tag=711 or ancestor-or-self::marc:datafield/@tag=730 or ancestor-or-self::marc:datafield/@tag=751)  and @ind2='2'">
3059                                 <xsl:attribute name="authority">nlmnaf</xsl:attribute>
3060                         </xsl:when>
3061                         <xsl:when
3062                                 test="(ancestor-or-self::marc:datafield/@tag=700 or ancestor-or-self::marc:datafield/@tag=710 or ancestor-or-self::marc:datafield/@tag=711 or ancestor-or-self::marc:datafield/@tag=730 or ancestor-or-self::marc:datafield/@tag=751)  and @ind2='3'">
3063                                 <xsl:attribute name="authority">nalnaf</xsl:attribute>
3064                         </xsl:when>
3065                         <xsl:when
3066                                 test="(700 &lt;= ancestor-or-self::marc:datafield/@tag and ancestor-or-self::marc:datafield/@tag &lt;= 755 ) and @ind2='6'">
3067                                 <xsl:attribute name="authority">rvm</xsl:attribute>
3068                         </xsl:when>
3069                         <xsl:when
3070                                 test="(700 &lt;= ancestor-or-self::marc:datafield/@tag and ancestor-or-self::marc:datafield/@tag &lt;= 755 ) and @ind2='7'">
3071                                 <xsl:attribute name="authority">
3072                                         <xsl:value-of select="marc:subfield[@code='2']"/>
3073                                 </xsl:attribute>
3074                         </xsl:when>
3075                         <xsl:when
3076                                 test="(ancestor-or-self::marc:datafield/@tag=710 or ancestor-or-self::marc:datafield/@tag=711 or ancestor-or-self::marc:datafield/@tag=730 or ancestor-or-self::marc:datafield/@tag=751)  and @ind2='5'">
3077                                 <xsl:attribute name="authority">lacnaf</xsl:attribute>
3078                         </xsl:when>
3079                         <xsl:when
3080                                 test="(ancestor-or-self::marc:datafield/@tag=710 or ancestor-or-self::marc:datafield/@tag=711 or ancestor-or-self::marc:datafield/@tag=730 or ancestor-or-self::marc:datafield/@tag=751)  and @ind2='0'">
3081                                 <xsl:attribute name="authority">naf</xsl:attribute>
3082                         </xsl:when>
3083                         <xsl:when
3084                                 test="(ancestor-or-self::marc:datafield/@tag=748 or ancestor-or-self::marc:datafield/@tag=750 or ancestor-or-self::marc:datafield/@tag=755)  and @ind2='0'">
3085                                 <xsl:attribute name="authority">lcsh</xsl:attribute>
3086                         </xsl:when>
3087                         <xsl:when
3088                                 test="(ancestor-or-self::marc:datafield/@tag=748 or ancestor-or-self::marc:datafield/@tag=750 or ancestor-or-self::marc:datafield/@tag=755)  and @ind2='2'">
3089                                 <xsl:attribute name="authority">mesh</xsl:attribute>
3090                         </xsl:when>
3091                         <xsl:when
3092                                 test="(ancestor-or-self::marc:datafield/@tag=748 or ancestor-or-self::marc:datafield/@tag=750 or ancestor-or-self::marc:datafield/@tag=755)  and @ind2='3'">
3093                                 <xsl:attribute name="authority">nal</xsl:attribute>
3094                         </xsl:when>
3095                         <xsl:when
3096                                 test="(ancestor-or-self::marc:datafield/@tag=748 or ancestor-or-self::marc:datafield/@tag=750 or ancestor-or-self::marc:datafield/@tag=755)  and @ind2='5'">
3097                                 <xsl:attribute name="authority">cash</xsl:attribute>
3098                         </xsl:when>
3099                 </xsl:choose>
3100         </xsl:template>
3101         <xsl:template match="*"/>
3102 </xsl:stylesheet>$XSLT$ WHERE name = 'mads21';
3103
3104
3105 SELECT evergreen.upgrade_deps_block_check('1310', :eg_version);
3106
3107 DROP AGGREGATE IF EXISTS array_accum(anyelement) CASCADE;
3108
3109
3110 COMMIT;
3111
3112 -- Update auditor tables to catch changes to source tables.
3113 --   Can be removed/skipped if there were no schema changes.
3114 SELECT auditor.update_auditors();