View | Details | Raw Unified | Return to bug 7284
Collapse All | Expand All

(-)a/C4/AuthoritiesMarc.pm (-102 / +83 lines)
Lines 17-25 package C4::AuthoritiesMarc; Link Here
17
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
18
19
use strict;
19
use strict;
20
#use warnings; FIXME - Bug 2505
20
use warnings;
21
use C4::Context;
21
use C4::Context;
22
use C4::Koha;
23
use MARC::Record;
22
use MARC::Record;
24
use C4::Biblio;
23
use C4::Biblio;
25
use C4::Search;
24
use C4::Search;
Lines 41-47 BEGIN { Link Here
41
	    &GetAuthType
40
	    &GetAuthType
42
	    &GetAuthTypeCode
41
	    &GetAuthTypeCode
43
    	&GetAuthMARCFromKohaField 
42
    	&GetAuthMARCFromKohaField 
44
    	&AUTHhtml2marc
45
43
46
    	&AddAuthority
44
    	&AddAuthority
47
    	&ModAuthority
45
    	&ModAuthority
Lines 98-112 sub GetAuthMARCFromKohaField { Link Here
98
=head2 SearchAuthorities 
96
=head2 SearchAuthorities 
99
97
100
  (\@finalresult, $nbresults)= &SearchAuthorities($tags, $and_or, 
98
  (\@finalresult, $nbresults)= &SearchAuthorities($tags, $and_or, 
101
     $excluding, $operator, $value, $offset,$length,$authtypecode,$sortby)
99
     $excluding, $operator, $value, $offset,$length,$authtypecode,
100
     $sortby[, $skipmetadata])
102
101
103
returns ref to array result and count of results returned
102
returns ref to array result and count of results returned
104
103
105
=cut
104
=cut
106
105
107
sub SearchAuthorities {
106
sub SearchAuthorities {
108
    my ($tags, $and_or, $excluding, $operator, $value, $offset,$length,$authtypecode,$sortby) = @_;
107
    my ($tags, $and_or, $excluding, $operator, $value, $offset,$length,$authtypecode,$sortby,$skipmetadata) = @_;
109
#     warn "CALL : $tags, $and_or, $excluding, $operator, $value, $offset,$length,$authtypecode,$sortby";
108
    # warn Dumper($tags, $and_or, $excluding, $operator, $value, $offset,$length,$authtypecode,$sortby);
110
    my $dbh=C4::Context->dbh;
109
    my $dbh=C4::Context->dbh;
111
    if (C4::Context->preference('NoZebra')) {
110
    if (C4::Context->preference('NoZebra')) {
112
    
111
    
Lines 225-247 sub SearchAuthorities { Link Here
225
        for(my $i = 0 ; $i <= $#{$value} ; $i++)
224
        for(my $i = 0 ; $i <= $#{$value} ; $i++)
226
        {
225
        {
227
            if (@$value[$i]){
226
            if (@$value[$i]){
228
                if (@$tags[$i] eq "mainmainentry") {
227
                if ( @$tags[$i] eq "mainmainentry" ) {
229
228
                    $attr = " \@attr 1=Heading-Main ";
230
                $attr =" \@attr 1=Heading-Main ";
231
232
                }elsif (@$tags[$i] eq "mainentry") {
233
                $attr =" \@attr 1=Heading ";
234
                }else{
235
                $attr =" \@attr 1=Any ";
236
                }
229
                }
237
                if (@$operator[$i] eq 'is') {
230
                elsif ( @$tags[$i] eq "mainentry" ) {
238
                    $attr.=" \@attr 4=1  \@attr 5=100 ";##Phrase, No truncation,all of subfield field must match
231
                    $attr = " \@attr 1=Heading ";
239
                }elsif (@$operator[$i] eq "="){
232
                }
240
                    $attr.=" \@attr 4=107 ";           #Number Exact match
233
                elsif ( @$tags[$i] eq "any" ) {
241
                }elsif (@$operator[$i] eq "start"){
234
                    $attr = " \@attr 1=Any ";
242
                    $attr.=" \@attr 3=2 \@attr 4=1 \@attr 5=1 ";#Firstinfield Phrase, Right truncated
235
                }
243
                } else {
236
                elsif ( @$tags[$i] eq "match" ) {
244
                    $attr .=" \@attr 5=1 \@attr 4=6 ";## Word list, right truncated, anywhere
237
                    $attr = " \@attr 1=Match ";
238
                }
239
                elsif ( @$tags[$i] eq "match-heading" ) {
240
                    $attr = " \@attr 1=Match-heading ";
241
                }
242
                elsif ( @$tags[$i] eq "see-from" ) {
243
                    $attr = " \@attr 1=Match-heading-see-from ";
244
                }
245
                elsif ( @$tags[$i] eq "thesaurus" ) {
246
                    $attr = " \@attr 1=Subject-heading-thesaurus ";
247
                }
248
                if ( @$operator[$i] eq 'is' ) {
249
                    $attr .= " \@attr 4=1  \@attr 5=100 "
250
                      ; ##Phrase, No truncation,all of subfield field must match
251
                }
252
                elsif ( @$operator[$i] eq "=" ) {
253
                    $attr .= " \@attr 4=107 ";    #Number Exact match
254
                }
255
                elsif ( @$operator[$i] eq "start" ) {
256
                    $attr .= " \@attr 3=2 \@attr 4=1 \@attr 5=1 "
257
                      ;    #Firstinfield Phrase, Right truncated
258
                }
259
                elsif ( @$operator[$i] eq "exact" ) {
260
                    $attr .= " \@attr 4=1  \@attr 5=100 \@attr 6=3 "
261
                      ; ##Phrase, No truncation,all of subfield field must match
262
                }
263
                else {
264
                    $attr .= " \@attr 5=1 \@attr 4=6 "
265
                      ;    ## Word list, right truncated, anywhere
245
                }
266
                }
246
                @$value[$i] =~ s/"/\\"/g; # Escape the double-quotes in the search value
267
                @$value[$i] =~ s/"/\\"/g; # Escape the double-quotes in the search value
247
                $attr =$attr."\"".@$value[$i]."\"";
268
                $attr =$attr."\"".@$value[$i]."\"";
Lines 251-258 sub SearchAuthorities { Link Here
251
            }#if value
272
            }#if value
252
        }
273
        }
253
        ##Add how many queries generated
274
        ##Add how many queries generated
254
        if ($query=~/\S+/){
275
        if (defined $query && $query=~/\S+/){
255
          $query= $and x $attr_cnt . $query . $q2;
276
          $query= $and x $attr_cnt . $query . (defined $q2 ? $q2 : '');
256
        } else {
277
        } else {
257
          $query= $q2;
278
          $query= $q2;
258
        }
279
        }
Lines 309-343 sub SearchAuthorities { Link Here
309
            my $separator=C4::Context->preference('authoritysep');
330
            my $separator=C4::Context->preference('authoritysep');
310
            $authrecord = MARC::File::USMARC::decode($marcdata);
331
            $authrecord = MARC::File::USMARC::decode($marcdata);
311
            my $authid=$authrecord->field('001')->data(); 
332
            my $authid=$authrecord->field('001')->data(); 
312
            my $summary=BuildSummary($authrecord,$authid,$authtypecode);
313
            my $query_auth_tag = "SELECT auth_tag_to_report FROM auth_types WHERE authtypecode=?";
314
            my $sth = $dbh->prepare($query_auth_tag);
315
            $sth->execute($authtypecode);
316
            my $auth_tag_to_report = $sth->fetchrow;
317
            my $reported_tag;
318
            my $mainentry = $authrecord->field($auth_tag_to_report);
319
            if ($mainentry) {
320
                foreach ($mainentry->subfields()) {
321
                    $reported_tag .='$'.$_->[0].$_->[1];
322
                }
323
            }
324
            my %newline;
333
            my %newline;
325
            $newline{summary} = $summary;
326
            $newline{authid} = $authid;
334
            $newline{authid} = $authid;
327
            $newline{even} = $counter % 2;
335
            if ( !$skipmetadata ) {
328
            $newline{reported_tag} = $reported_tag;
336
                my $summary =
337
                  BuildSummary( $authrecord, $authid, $authtypecode );
338
                my $query_auth_tag =
339
"SELECT auth_tag_to_report FROM auth_types WHERE authtypecode=?";
340
                my $sth = $dbh->prepare($query_auth_tag);
341
                $sth->execute($authtypecode);
342
                my $auth_tag_to_report = $sth->fetchrow;
343
                my $reported_tag;
344
                my $mainentry = $authrecord->field($auth_tag_to_report);
345
                if ($mainentry) {
346
347
                    foreach ( $mainentry->subfields() ) {
348
                        $reported_tag .= '$' . $_->[0] . $_->[1];
349
                    }
350
                }
351
                $newline{summary}      = $summary;
352
                $newline{even}         = $counter % 2;
353
                $newline{reported_tag} = $reported_tag;
354
            }
329
            $counter++;
355
            $counter++;
330
            push @finalresult, \%newline;
356
            push @finalresult, \%newline;
331
            }## while counter
357
            }## while counter
332
        ###
358
            ###
333
        for (my $z=0; $z<@finalresult; $z++){
359
            if (! $skipmetadata) {
334
                my  $count=CountUsage($finalresult[$z]{authid});
360
                for (my $z=0; $z<@finalresult; $z++){
335
                $finalresult[$z]{used}=$count;
361
                    my  $count=CountUsage($finalresult[$z]{authid});
336
        }# all $z's
362
                    $finalresult[$z]{used}=$count;
337
        
363
                }# all $z's
364
            }
365
338
        }## if nbresult
366
        }## if nbresult
339
        NOLUCK:
367
        NOLUCK:
340
        # $oAResult->destroy();
368
        $oAResult->destroy();
341
        # $oAuth[0]->destroy();
369
        # $oAuth[0]->destroy();
342
        
370
        
343
        return (\@finalresult, $nbresults);
371
        return (\@finalresult, $nbresults);
Lines 854-906 sub GetAuthType { Link Here
854
}
882
}
855
883
856
884
857
sub AUTHhtml2marc {
858
    my ($rtags,$rsubfields,$rvalues,%indicators) = @_;
859
    my $dbh=C4::Context->dbh;
860
    my $prevtag = -1;
861
    my $record = MARC::Record->new();
862
#---- TODO : the leader is missing
863
864
#     my %subfieldlist=();
865
    my $prevvalue; # if tag <10
866
    my $field; # if tag >=10
867
    for (my $i=0; $i< @$rtags; $i++) {
868
        # rebuild MARC::Record
869
        if (@$rtags[$i] ne $prevtag) {
870
            if ($prevtag < 10) {
871
                if ($prevvalue) {
872
                    $record->add_fields((sprintf "%03s",$prevtag),$prevvalue);
873
                }
874
            } else {
875
                if ($field) {
876
                    $record->add_fields($field);
877
                }
878
            }
879
            $indicators{@$rtags[$i]}.='  ';
880
            if (@$rtags[$i] <10) {
881
                $prevvalue= @$rvalues[$i];
882
                undef $field;
883
            } else {
884
                undef $prevvalue;
885
                $field = MARC::Field->new( (sprintf "%03s",@$rtags[$i]), substr($indicators{@$rtags[$i]},0,1),substr($indicators{@$rtags[$i]},1,1), @$rsubfields[$i] => @$rvalues[$i]);
886
            }
887
            $prevtag = @$rtags[$i];
888
        } else {
889
            if (@$rtags[$i] <10) {
890
                $prevvalue=@$rvalues[$i];
891
            } else {
892
                if (length(@$rvalues[$i])>0) {
893
                    $field->add_subfields(@$rsubfields[$i] => @$rvalues[$i]);
894
                }
895
            }
896
            $prevtag= @$rtags[$i];
897
        }
898
    }
899
    # the last has not been included inside the loop... do it now !
900
    $record->add_fields($field) if $field;
901
    return $record;
902
}
903
904
=head2 FindDuplicateAuthority
885
=head2 FindDuplicateAuthority
905
886
906
  $record= &FindDuplicateAuthority( $record, $authtypecode)
887
  $record= &FindDuplicateAuthority( $record, $authtypecode)
Lines 1015-1028 sub BuildSummary{ Link Here
1015
    $resultstring =~ s/\n/<br>/g;
996
    $resultstring =~ s/\n/<br>/g;
1016
	$summary      =  $resultstring;
997
	$summary      =  $resultstring;
1017
  } else {
998
  } else {
1018
    my $heading; 
999
    my $heading = '';
1019
    my $altheading;
1000
    my $altheading = '';
1020
    my $seealso;
1001
    my $seealso = '';
1021
    my $broaderterms;
1002
    my $broaderterms = '';
1022
    my $narrowerterms;
1003
    my $narrowerterms = '';
1023
    my $see;
1004
    my $see = '';
1024
    my $seeheading;
1005
    my $seeheading = '';
1025
        my $notes;
1006
    my $notes = '';
1026
    my @fields = $record->fields();
1007
    my @fields = $record->fields();
1027
    if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
1008
    if (C4::Context->preference('marcflavour') eq 'UNIMARC') {
1028
    # construct UNIMARC summary, that is quite different from MARC21 one
1009
    # construct UNIMARC summary, that is quite different from MARC21 one
Lines 1471-1477 sub get_auth_type_location { Link Here
1471
    my $auth_type_code = @_ ? shift : '';
1452
    my $auth_type_code = @_ ? shift : '';
1472
1453
1473
    my ($tag, $subfield) = GetAuthMARCFromKohaField('auth_header.authtypecode', $auth_type_code);
1454
    my ($tag, $subfield) = GetAuthMARCFromKohaField('auth_header.authtypecode', $auth_type_code);
1474
    if (defined $tag and defined $subfield and $tag != 0 and $subfield != 0) {
1455
    if (defined $tag and defined $subfield and $tag != 0 and $subfield ne '' and $subfield ne ' ') {
1475
        return ($tag, $subfield);
1456
        return ($tag, $subfield);
1476
    } else {
1457
    } else {
1477
        if (C4::Context->preference('marcflavour') eq "MARC21")  {
1458
        if (C4::Context->preference('marcflavour') eq "MARC21")  {
(-)a/C4/Biblio.pm (-13 / +119 lines)
Lines 35-40 use C4::Dates qw/format_date/; Link Here
35
use C4::Log;    # logaction
35
use C4::Log;    # logaction
36
use C4::ClassSource;
36
use C4::ClassSource;
37
use C4::Charset;
37
use C4::Charset;
38
use C4::Linker;
38
require C4::Heading;
39
require C4::Heading;
39
require C4::Serials;
40
require C4::Serials;
40
require C4::Items;
41
require C4::Items;
Lines 114-119 BEGIN { Link Here
114
    # To link headings in a bib record
115
    # To link headings in a bib record
115
    # to authority records.
116
    # to authority records.
116
    push @EXPORT, qw(
117
    push @EXPORT, qw(
118
      &BiblioAutoLink
117
      &LinkBibHeadingsToAuthorities
119
      &LinkBibHeadingsToAuthorities
118
    );
120
    );
119
121
Lines 457-465 sub DelBiblio { Link Here
457
    return;
459
    return;
458
}
460
}
459
461
462
463
=head2 BiblioAutoLink
464
465
  my $headings_linked = BiblioAutoLink($record, $frameworkcode)
466
467
Automatically links headings in a bib record to authorities.
468
469
=cut
470
471
sub BiblioAutoLink {
472
    my $record        = shift;
473
    my $frameworkcode = shift;
474
    my ( $num_headings_changed, %results );
475
476
    my $linker_module =
477
      "C4::Linker::" . ( C4::Context->preference("LinkerModule") || 'Default' );
478
    eval { eval "require $linker_module"; };
479
    if ($@) {
480
        $linker_module = 'C4::Linker::Default';
481
        eval "require $linker_module";
482
    }
483
    if ($@) {
484
        return 0, 0;
485
    }
486
487
    my $linker = $linker_module->new(
488
        { 'options' => C4::Context->preference("LinkerOptions") } );
489
    my ( $headings_changed, undef ) =
490
      LinkBibHeadingsToAuthorities( $linker, $record, $frameworkcode );
491
    return $headings_changed;
492
}
493
460
=head2 LinkBibHeadingsToAuthorities
494
=head2 LinkBibHeadingsToAuthorities
461
495
462
  my $headings_linked = LinkBibHeadingsToAuthorities($marc);
496
  my $num_headings_changed, %results = LinkBibHeadingsToAuthorities($linker, $marc, $frameworkcode);
463
497
464
Links bib headings to authority records by checking
498
Links bib headings to authority records by checking
465
each authority-controlled field in the C<MARC::Record>
499
each authority-controlled field in the C<MARC::Record>
Lines 477-513 MARC record. Link Here
477
=cut
511
=cut
478
512
479
sub LinkBibHeadingsToAuthorities {
513
sub LinkBibHeadingsToAuthorities {
480
    my $bib = shift;
514
    my $linker        = shift;
515
    my $bib           = shift;
516
    my $frameworkcode = shift;
517
    my %results;
518
    require C4::AuthoritiesMarc;
481
519
482
    my $num_headings_changed = 0;
520
    my $num_headings_changed = 0;
483
    foreach my $field ( $bib->fields() ) {
521
    foreach my $field ( $bib->fields() ) {
484
        my $heading = C4::Heading->new_from_bib_field($field);
522
        my $heading = C4::Heading->new_from_bib_field( $field, $frameworkcode );
485
        next unless defined $heading;
523
        next unless defined $heading;
486
524
487
        # check existing $9
525
        # check existing $9
488
        my $current_link = $field->subfield('9');
526
        my $current_link = $field->subfield('9');
489
527
490
        # look for matching authorities
528
        if ( defined $current_link && !C4::Context->preference('LinkerRelink') )
491
        my $authorities = $heading->authorities();
529
        {
530
            $results{'linked'}->{ $heading->display_form() }++;
531
            next;
532
        }
492
533
493
        # want only one exact match
534
        my ( $authid, $fuzzy ) = $linker->get_link($heading);
494
        if ( $#{$authorities} == 0 ) {
535
        if ($authid) {
495
            my $authority = MARC::Record->new_from_usmarc( $authorities->[0] );
536
            $results{ $fuzzy ? 'fuzzy' : 'linked' }
496
            my $authid    = $authority->field('001')->data();
537
              ->{ $heading->display_form() }++;
497
            next if defined $current_link and $current_link eq $authid;
538
            next if defined $current_link and $current_link == $authid;
498
539
499
            $field->delete_subfield( code => '9' ) if defined $current_link;
540
            $field->delete_subfield( code => '9' ) if defined $current_link;
500
            $field->add_subfields( '9', $authid );
541
            $field->add_subfields( '9', $authid );
501
            $num_headings_changed++;
542
            $num_headings_changed++;
502
        } else {
543
        }
503
            if ( defined $current_link ) {
544
        else {
545
            if ( defined $current_link
546
                && C4::Context->preference('LinkerKeepStale') )
547
            {
548
                $results{'fuzzy'}->{ $heading->display_form() }++;
549
            }
550
            elsif ( C4::Context->preference('AutoCreateAuthorities') ) {
551
                my $authtypedata =
552
                  C4::AuthoritiesMarc::GetAuthType( $heading->auth_type() );
553
                my $marcrecordauth = MARC::Record->new();
554
                if ( C4::Context->preference('marcflavour') eq 'MARC21' ) {
555
                    $marcrecordauth->leader('     nz  a22     o  4500');
556
                    SetMarcUnicodeFlag( $marcrecordauth, 'MARC21' );
557
                }
558
                my $authfield =
559
                  MARC::Field->new( $authtypedata->{auth_tag_to_report},
560
                    '', '', "a" => "" . $field->subfield('a') );
561
                map {
562
                    $authfield->add_subfields( $_->[0] => $_->[1] )
563
                      if ( $_->[0] =~ /[A-z]/ && $_->[0] ne "a" )
564
                } $field->subfields();
565
                $marcrecordauth->insert_fields_ordered($authfield);
566
567
# bug 2317: ensure new authority knows it's using UTF-8; currently
568
# only need to do this for MARC21, as MARC::Record->as_xml_record() handles
569
# automatically for UNIMARC (by not transcoding)
570
# FIXME: AddAuthority() instead should simply explicitly require that the MARC::Record
571
# use UTF-8, but as of 2008-08-05, did not want to introduce that kind
572
# of change to a core API just before the 3.0 release.
573
574
                if ( C4::Context->preference('marcflavour') eq 'MARC21' ) {
575
                    $marcrecordauth->insert_fields_ordered(
576
                        MARC::Field->new(
577
                            '667', '', '',
578
                            'a' => "Machine generated authority record."
579
                        )
580
                    );
581
                    my $cite =
582
                        $bib->author() . ", "
583
                      . $bib->title_proper() . ", "
584
                      . $bib->publication_date() . " ";
585
                    $cite =~ s/^[\s\,]*//;
586
                    $cite =~ s/[\s\,]*$//;
587
                    $cite =
588
                        "Work cat.: ("
589
                      . C4::Context->preference('MARCOrgCode') . ")"
590
                      . $bib->subfield( '999', 'c' ) . ": "
591
                      . $cite;
592
                    $marcrecordauth->insert_fields_ordered(
593
                        MARC::Field->new( '670', '', '', 'a' => $cite ) );
594
                }
595
596
           #          warn "AUTH RECORD ADDED : ".$marcrecordauth->as_formatted;
597
598
                $authid =
599
                  C4::AuthoritiesMarc::AddAuthority( $marcrecordauth, '',
600
                    $heading->auth_type() );
601
                $field->add_subfields( '9', $authid );
602
                $num_headings_changed++;
603
                $results{'added'}->{ $heading->display_form() }++;
604
            }
605
            elsif ( defined $current_link ) {
504
                $field->delete_subfield( code => '9' );
606
                $field->delete_subfield( code => '9' );
505
                $num_headings_changed++;
607
                $num_headings_changed++;
608
                $results{'unlinked'}->{ $heading->display_form() }++;
609
            }
610
            else {
611
                $results{'unlinked'}->{ $heading->display_form() }++;
506
            }
612
            }
507
        }
613
        }
508
614
509
    }
615
    }
510
    return $num_headings_changed;
616
    return $num_headings_changed, \%results;
511
}
617
}
512
618
513
=head2 GetRecordValue
619
=head2 GetRecordValue
(-)a/C4/Heading.pm (-54 / +101 lines)
Lines 1-7 Link Here
1
package C4::Heading;
1
package C4::Heading;
2
2
3
# Copyright (C) 2008 LibLime
3
# Copyright (C) 2008 LibLime
4
# 
4
#
5
# This file is part of Koha.
5
# This file is part of Koha.
6
#
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
7
# Koha is free software; you can redistribute it and/or modify it under the
Lines 18-29 package C4::Heading; Link Here
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
19
20
use strict;
20
use strict;
21
#use warnings; FIXME - Bug 2505
21
use warnings;
22
use MARC::Record;
22
use MARC::Record;
23
use MARC::Field;
23
use MARC::Field;
24
use C4::Context;
24
use C4::Context;
25
use C4::Heading::MARC21;
25
use C4::AuthoritiesMarc;
26
use C4::Search;
26
use Module::Load;
27
use Carp;
27
use Carp;
28
28
29
our $VERSION = 3.00;
29
our $VERSION = 3.00;
Lines 35-45 C4::Heading Link Here
35
=head1 SYNOPSIS
35
=head1 SYNOPSIS
36
36
37
 use C4::Heading;
37
 use C4::Heading;
38
 my $heading = C4::Heading->new_from_bib_field($field);
38
 my $heading = C4::Heading->new_from_bib_field($field, $frameworkcode);
39
 my $thesaurus = $heading->thesaurus();
39
 my $thesaurus = $heading->thesaurus();
40
 my $type = $heading->type();
40
 my $type = $heading->type();
41
 my $display_heading = $heading->display();
41
 my $display_heading = $heading->display_form();
42
 my $search_string = $heading->search_string();
42
 my $search_form = $heading->search_form();
43
43
44
=head1 DESCRIPTION
44
=head1 DESCRIPTION
45
45
Lines 50-56 headings found in bibliographic and authority records. Link Here
50
50
51
=head2 new_from_bib_field
51
=head2 new_from_bib_field
52
52
53
  my $heading = C4::Heading->new_from_bib_field($field[, $marc_flavour]);
53
  my $heading = C4::Heading->new_from_bib_field($field, $frameworkcode, [, $marc_flavour]);
54
54
55
Given a C<MARC::Field> object containing a heading from a 
55
Given a C<MARC::Field> object containing a heading from a 
56
bib record, create a C<C4::Heading> object.
56
bib record, create a C<C4::Heading> object.
Lines 65-88 is returned. Link Here
65
=cut
65
=cut
66
66
67
sub new_from_bib_field {
67
sub new_from_bib_field {
68
    my $class = shift;
68
    my $class         = shift;
69
    my $field = shift;
69
    my $field         = shift;
70
    my $marcflavour = @_ ? shift : C4::Context->preference('marcflavour');
70
    my $frameworkcode = shift;
71
    my $marcflavour   = @_ ? shift : C4::Context->preference('marcflavour');
71
72
72
    my $marc_handler = _marc_format_handler($marcflavour);
73
    my $marc_handler = _marc_format_handler($marcflavour);
73
74
74
    my $tag = $field->tag();
75
    my $tag = $field->tag();
75
    return unless $marc_handler->valid_bib_heading_tag($tag);
76
    return unless $marc_handler->valid_bib_heading_tag( $tag, $frameworkcode );
76
    my $self = {};
77
    my $self = {};
77
   
78
78
    ($self->{'auth_type'}, $self->{'subject_added_entry'}, $self->{'series_added_entry'}, $self->{'main_entry'},
79
    $self->{'field'} = $field;
79
     $self->{'thesaurus'}, $self->{'search_form'}, $self->{'display_form'}) =
80
    (
80
        $marc_handler->parse_heading($field);
81
        $self->{'auth_type'},   $self->{'thesaurus'},
82
        $self->{'search_form'}, $self->{'display_form'},
83
        $self->{'match_type'}
84
    ) = $marc_handler->parse_heading($field);
81
85
82
    bless $self, $class;
86
    bless $self, $class;
83
    return $self;
87
    return $self;
84
}
88
}
85
89
90
=head2 auth_type
91
92
  my $auth_type = $heading->auth_type();
93
94
Return the auth_type of the heading.
95
96
=cut
97
98
sub auth_type {
99
    my $self = shift;
100
    return $self->{'auth_type'};
101
}
102
103
=head2 field
104
105
  my $field = $heading->field();
106
107
Return the MARC::Field the heading is based on.
108
109
=cut
110
111
sub field {
112
    my $self = shift;
113
    return $self->{'field'};
114
}
115
86
=head2 display_form
116
=head2 display_form
87
117
88
  my $display = $heading->display_form();
118
  my $display = $heading->display_form();
Lines 96-118 sub display_form { Link Here
96
    return $self->{'display_form'};
126
    return $self->{'display_form'};
97
}
127
}
98
128
129
=head2 search_form
130
131
  my $search_form = $heading->search_form();
132
133
Return the "canonical" search form of the heading.
134
135
=cut
136
137
sub search_form {
138
    my $self = shift;
139
    return $self->{'search_form'};
140
}
141
99
=head2 authorities
142
=head2 authorities
100
143
101
  my $authorities = $heading->authorities;
144
  my $authorities = $heading->authorities([$skipmetadata]);
102
145
103
Return a list of authority records for this 
146
Return a list of authority records for this 
104
heading.
147
heading. If passed a true value for $skipmetadata,
148
SearchAuthorities will return only authids.
105
149
106
=cut
150
=cut
107
151
108
sub authorities {
152
sub authorities {
109
    my $self = shift;
153
    my $self         = shift;
110
    my $query = qq(Match-heading,do-not-truncate,ext="$self->{'search_form'}");
154
    my $skipmetadata = shift;
111
    $query .= $self->_query_limiters();
155
    my ( $results, $total ) = _search( $self, 'match-heading', $skipmetadata );
112
    my ($error, $results, $total_hits) = SimpleSearch( $query, undef, undef, [ "authorityserver" ] );
113
    if (defined $error) {
114
        carp "Error:$error from search $query";
115
    }
116
    return $results;
156
    return $results;
117
}
157
}
118
158
Lines 127-162 that are a preferred form of the heading. Link Here
127
167
128
sub preferred_authorities {
168
sub preferred_authorities {
129
    my $self = shift;
169
    my $self = shift;
130
    my $query = "Match-heading-see-from,do-not-truncate,ext='$self->{'search_form'}'";
170
    my $skipmetadata = shift || undef;
131
    $query .= $self->_query_limiters();
171
    my ( $results, $total ) = _search( 'see-from', $skipmetadata );
132
    my ($error, $results, $total_hits) = SimpleSearch( $query, undef, undef, [ "authorityserver" ] );
133
    if (defined $error) {
134
        carp "Error:$error from search $query";
135
    }
136
    return $results;
172
    return $results;
137
}
173
}
138
174
139
=head1 INTERNAL METHODS
175
=head1 INTERNAL METHODS
140
176
141
=head2 _query_limiters
177
=head2 _search
142
178
143
=cut
179
=cut
144
180
145
sub _query_limiters {
181
sub _search {
146
    my $self = shift;
182
    my $self         = shift;
147
183
    my $index        = shift || undef;
148
    my $limiters = " AND at='$self->{'auth_type'}'";
184
    my $skipmetadata = shift || undef;
149
    if ($self->{'subject_added_entry'}) {
185
    my @marclist;
150
        $limiters .= " AND Heading-use-subject-added-entry=a"; # FIXME -- is this properly in C4::Heading::MARC21?
186
    my @and_or;
151
        $limiters .= " AND Subject-heading-thesaurus=$self->{'thesaurus'}";
187
    my @excluding = [];
152
    }
188
    my @operator;
153
    if ($self->{'series_added_entry'}) {
189
    my @value;
154
        $limiters .= " AND Heading-use-series-added-entry=a"; # FIXME -- is this properly in C4::Heading::MARC21?
190
155
    }
191
    if ($index) {
156
    if (not $self->{'subject_added_entry'} and not $self->{'series_added_entry'}) {
192
        push @marclist, $index;
157
        $limiters .= " AND Heading-use-main-or-added-entry=a" # FIXME -- is this properly in C4::Heading::MARC21?
193
        push @and_or,   'and';
194
        push @operator, $self->{'match_type'};
195
        push @value,    $self->{'search_form'};
158
    }
196
    }
159
    return $limiters;
197
198
    #    if ($self->{'thesaurus'}) {
199
    #        push @marclist, 'thesaurus';
200
    #        push @and_or, 'and';
201
    #        push @excluding, '';
202
    #        push @operator, 'is';
203
    #        push @value, $self->{'thesaurus'};
204
    #    }
205
    return SearchAuthorities(
206
        \@marclist, \@and_or, \@excluding, \@operator,
207
        \@value,    0,        20,          $self->{'auth_type'},
208
        '',         $skipmetadata
209
    );
160
}
210
}
161
211
162
=head1 INTERNAL FUNCTIONS
212
=head1 INTERNAL FUNCTIONS
Lines 169-182 depending on the selected MARC flavour. Link Here
169
=cut
219
=cut
170
220
171
sub _marc_format_handler {
221
sub _marc_format_handler {
172
    my $marcflavour = shift;
222
    my $marcflavour = uc shift;
173
223
    $marcflavour = 'MARC21' if ( $marcflavour eq 'NORMARC' );
174
    if ($marcflavour eq 'UNIMARC') {
224
    my $pname = "C4::Heading::$marcflavour";
175
        return C4::Heading::UNIMARC->new();
225
    load $pname;
176
    } else {
226
    return $pname->new();
177
        return C4::Heading::MARC21->new();
178
    }
179
180
}
227
}
181
228
182
=head1 AUTHOR
229
=head1 AUTHOR
(-)a/C4/Heading/MARC21.pm (-64 / +134 lines)
Lines 1-7 Link Here
1
package C4::Heading::MARC21;
1
package C4::Heading::MARC21;
2
2
3
# Copyright (C) 2008 LibLime
3
# Copyright (C) 2008 LibLime
4
# 
4
#
5
# This file is part of Koha.
5
# This file is part of Koha.
6
#
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
7
# Koha is free software; you can redistribute it and/or modify it under the
Lines 18-24 package C4::Heading::MARC21; Link Here
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
19
20
use strict;
20
use strict;
21
#use warnings; FIXME - Bug 2505
21
use warnings;
22
use MARC::Record;
22
use MARC::Record;
23
use MARC::Field;
23
use MARC::Field;
24
24
Lines 49-75 FIXME - this should be moved to a configuration file. Link Here
49
=cut
49
=cut
50
50
51
my $bib_heading_fields = {
51
my $bib_heading_fields = {
52
    '100' => { auth_type => 'PERSO_NAME', subfields => 'abcdefghjklmnopqrst', main_entry => 1 },
52
    '100' => {
53
    '110' => { auth_type => 'CORPO_NAME', subfields => 'abcdefghklmnoprst', main_entry => 1 },
53
        auth_type  => 'PERSO_NAME',
54
    '111' => { auth_type => 'MEETI_NAME', subfields => 'acdefghjklnpqst', main_entry => 1 },
54
        subfields  => 'abcdfghjklmnopqrst',
55
    '130' => { auth_type => 'UNIF_TITLE', subfields => 'adfghklmnoprst', main_entry => 1 },
55
        main_entry => 1
56
    },
57
    '110' => {
58
        auth_type  => 'CORPO_NAME',
59
        subfields  => 'abcdfghklmnoprst',
60
        main_entry => 1
61
    },
62
    '111' => {
63
        auth_type  => 'MEETI_NAME',
64
        subfields  => 'acdfghjklnpqst',
65
        main_entry => 1
66
    },
67
    '130' => {
68
        auth_type  => 'UNIF_TITLE',
69
        subfields  => 'adfghklmnoprst',
70
        main_entry => 1
71
    },
56
    '440' => { auth_type => 'UNIF_TITLE', subfields => 'anp', series => 1 },
72
    '440' => { auth_type => 'UNIF_TITLE', subfields => 'anp', series => 1 },
57
    '600' => { auth_type => 'PERSO_NAME', subfields => 'abcdefghjklmnopqrstvxyz', subject => 1 },
73
    '600' => {
58
    '610' => { auth_type => 'CORPO_NAME', subfields => 'abcdefghklmnoprstvxyz', subject => 1 },
74
        auth_type => 'PERSO_NAME',
59
    '611' => { auth_type => 'MEETI_NAME', subfields => 'acdefghjklnpqstvxyz', subject => 1 },
75
        subfields => 'abcdfghjklmnopqrstvxyz',
60
    '630' => { auth_type => 'UNIF_TITLE', subfields => 'adfghklmnoprstvxyz', subject => 1 },
76
        subject   => 1
61
    '648' => { auth_type => 'CHRON_TERM', subfields => 'avxyz', subject => 1 },
77
    },
78
    '610' => {
79
        auth_type => 'CORPO_NAME',
80
        subfields => 'abcdfghklmnoprstvxyz',
81
        subject   => 1
82
    },
83
    '611' => {
84
        auth_type => 'MEETI_NAME',
85
        subfields => 'acdfghjklnpqstvxyz',
86
        subject   => 1
87
    },
88
    '630' => {
89
        auth_type => 'UNIF_TITLE',
90
        subfields => 'adfghklmnoprstvxyz',
91
        subject   => 1
92
    },
93
    '648' => { auth_type => 'CHRON_TERM', subfields => 'avxyz',  subject => 1 },
62
    '650' => { auth_type => 'TOPIC_TERM', subfields => 'abvxyz', subject => 1 },
94
    '650' => { auth_type => 'TOPIC_TERM', subfields => 'abvxyz', subject => 1 },
63
    '651' => { auth_type => 'GEOGR_NAME', subfields => 'avxyz', subject => 1 },
95
    '651' => { auth_type => 'GEOGR_NAME', subfields => 'avxyz',  subject => 1 },
64
    '655' => { auth_type => 'GENRE/FORM', subfields => 'avxyz', subject => 1 },
96
    '655' => { auth_type => 'GENRE/FORM', subfields => 'avxyz',  subject => 1 },
65
    '700' => { auth_type => 'PERSO_NAME', subfields => 'abcdefghjklmnopqrst' },
97
    '700' => { auth_type => 'PERSO_NAME', subfields => 'abcdfghjklmnopqrst' },
66
    '710' => { auth_type => 'CORPO_NAME', subfields => 'abcdefghklmnoprst' },
98
    '710' => { auth_type => 'CORPO_NAME', subfields => 'abcdfghklmnoprst' },
67
    '711' => { auth_type => 'MEETI_NAME', subfields => 'acdefghjklnpqst' },
99
    '711' => { auth_type => 'MEETI_NAME', subfields => 'acdfghjklnpqst' },
68
    '730' => { auth_type => 'UNIF_TITLE', subfields => 'adfghklmnoprst' },
100
    '730' => { auth_type => 'UNIF_TITLE', subfields => 'adfghklmnoprst' },
69
    '800' => { auth_type => 'PERSO_NAME', subfields => 'abcdefghjklmnopqrst', series => 1 },
101
    '800' => {
70
    '810' => { auth_type => 'CORPO_NAME', subfields => 'abcdefghklmnoprst', series => 1 },
102
        auth_type => 'PERSO_NAME',
71
    '811' => { auth_type => 'MEETI_NAME', subfields => 'acdefghjklnpqst', series => 1 },
103
        subfields => 'abcdfghjklmnopqrst',
72
    '830' => { auth_type => 'UNIF_TITLE', subfields => 'adfghklmnoprst', series => 1 },
104
        series    => 1
105
    },
106
    '810' => {
107
        auth_type => 'CORPO_NAME',
108
        subfields => 'abcdfghklmnoprst',
109
        series    => 1
110
    },
111
    '811' =>
112
      { auth_type => 'MEETI_NAME', subfields => 'acdfghjklnpqst', series => 1 },
113
    '830' =>
114
      { auth_type => 'UNIF_TITLE', subfields => 'adfghklmnoprst', series => 1 },
73
};
115
};
74
116
75
=head2 subdivisions
117
=head2 subdivisions
Lines 101-112 sub new { Link Here
101
=cut
143
=cut
102
144
103
sub valid_bib_heading_tag {
145
sub valid_bib_heading_tag {
104
    my $self = shift;
146
    my $self          = shift;
105
    my $tag = shift;
147
    my $tag           = shift;
148
    my $frameworkcode = shift;
106
149
107
    if (exists $bib_heading_fields->{$tag}) {
150
    if ( exists $bib_heading_fields->{$tag} ) {
108
        return 1
151
        return 1;
109
    } else {
152
    }
153
    else {
110
        return 0;
154
        return 0;
111
    }
155
    }
112
156
Lines 117-137 sub valid_bib_heading_tag { Link Here
117
=cut
161
=cut
118
162
119
sub parse_heading {
163
sub parse_heading {
120
    my $self = shift;
164
    my $self  = shift;
121
    my $field = shift;
165
    my $field = shift;
122
166
123
    my $tag = $field->tag;
167
    my $tag        = $field->tag;
124
    my $field_info = $bib_heading_fields->{$tag};
168
    my $field_info = $bib_heading_fields->{$tag};
125
169
126
    my $auth_type = $field_info->{'auth_type'};
170
    my $auth_type = $field_info->{'auth_type'};
127
    my $subject = $field_info->{'subject'} ? 1 : 0;
171
    my $thesaurus =
128
    my $series = $field_info->{'series'} ? 1 : 0;
172
      $tag =~ m/6../
129
    my $main_entry = $field_info->{'main_entry'} ? 1 : 0;
173
      ? _get_subject_thesaurus($field)
130
    my $thesaurus = $subject ? _get_subject_thesaurus($field) : "lcsh"; # use 'lcsh' for names, UT, etc.
174
      : "lcsh";    # use 'lcsh' for names, UT, etc.
131
    my $search_heading = _get_search_heading($field, $field_info->{'subfields'});
175
    my $search_heading =
132
    my $display_heading = _get_display_heading($field, $field_info->{'subfields'});
176
      _get_search_heading( $field, $field_info->{'subfields'} );
133
177
    my $display_heading =
134
    return ($auth_type, $subject, $series, $main_entry, $thesaurus, $search_heading, $display_heading);
178
      _get_display_heading( $field, $field_info->{'subfields'} );
179
180
    return ( $auth_type, $thesaurus, $search_heading, $display_heading,
181
        'exact' );
135
}
182
}
136
183
137
=head1 INTERNAL FUNCTIONS
184
=head1 INTERNAL FUNCTIONS
Lines 142-165 sub parse_heading { Link Here
142
189
143
sub _get_subject_thesaurus {
190
sub _get_subject_thesaurus {
144
    my $field = shift;
191
    my $field = shift;
145
    my $ind2 = $field->indicator(2);
192
    my $ind2  = $field->indicator(2);
146
193
147
    my $thesaurus = "notdefined";
194
    my $thesaurus = "notdefined";
148
    if ($ind2 eq '0') {
195
    if ( $ind2 eq '0' ) {
149
        $thesaurus = "lcsh";
196
        $thesaurus = "lcsh";
150
    } elsif ($ind2 eq '1') {
197
    }
198
    elsif ( $ind2 eq '1' ) {
151
        $thesaurus = "lcac";
199
        $thesaurus = "lcac";
152
    } elsif ($ind2 eq '2') {
200
    }
201
    elsif ( $ind2 eq '2' ) {
153
        $thesaurus = "mesh";
202
        $thesaurus = "mesh";
154
    } elsif ($ind2 eq '3') {
203
    }
204
    elsif ( $ind2 eq '3' ) {
155
        $thesaurus = "nal";
205
        $thesaurus = "nal";
156
    } elsif ($ind2 eq '4') {
206
    }
207
    elsif ( $ind2 eq '4' ) {
157
        $thesaurus = "notspecified";
208
        $thesaurus = "notspecified";
158
    } elsif ($ind2 eq '5') {
209
    }
210
    elsif ( $ind2 eq '5' ) {
159
        $thesaurus = "cash";
211
        $thesaurus = "cash";
160
    } elsif ($ind2 eq '6') {
212
    }
213
    elsif ( $ind2 eq '6' ) {
161
        $thesaurus = "rvm";
214
        $thesaurus = "rvm";
162
    } elsif ($ind2 eq '7') {
215
    }
216
    elsif ( $ind2 eq '7' ) {
163
        my $sf2 = $field->subfield('2');
217
        my $sf2 = $field->subfield('2');
164
        $thesaurus = $sf2 if defined($sf2);
218
        $thesaurus = $sf2 if defined($sf2);
165
    }
219
    }
Lines 172-195 sub _get_subject_thesaurus { Link Here
172
=cut
226
=cut
173
227
174
sub _get_search_heading {
228
sub _get_search_heading {
175
    my $field = shift;
229
    my $field     = shift;
176
    my $subfields = shift;
230
    my $subfields = shift;
177
231
178
    my $heading = "";
232
    my $heading   = "";
179
    my @subfields = $field->subfields();
233
    my @subfields = $field->subfields();
180
    my $first = 1;
234
    my $first     = 1;
181
    for (my $i = 0; $i <= $#subfields; $i++) {
235
    for ( my $i = 0 ; $i <= $#subfields ; $i++ ) {
182
        my $code = $subfields[$i]->[0];
236
        my $code    = $subfields[$i]->[0];
183
        my $code_re = quotemeta $code;
237
        my $code_re = quotemeta $code;
184
        my $value = $subfields[$i]->[1];
238
        my $value   = $subfields[$i]->[1];
239
        $value =~ s/[-,.:=;!%\/]$//;
185
        next unless $subfields =~ qr/$code_re/;
240
        next unless $subfields =~ qr/$code_re/;
186
        if ($first) {
241
        if ($first) {
187
            $first = 0;
242
            $first   = 0;
188
            $heading = $value;
243
            $heading = $value;
189
        } else {
244
        }
190
            if (exists $subdivisions{$code}) {
245
        else {
246
            if ( exists $subdivisions{$code} ) {
191
                $heading .= " $subdivisions{$code} $value";
247
                $heading .= " $subdivisions{$code} $value";
192
            } else {
248
            }
249
            else {
193
                $heading .= " $value";
250
                $heading .= " $value";
194
            }
251
            }
195
        }
252
        }
Lines 206-229 sub _get_search_heading { Link Here
206
=cut
263
=cut
207
264
208
sub _get_display_heading {
265
sub _get_display_heading {
209
    my $field = shift;
266
    my $field     = shift;
210
    my $subfields = shift;
267
    my $subfields = shift;
211
268
212
    my $heading = "";
269
    my $heading   = "";
213
    my @subfields = $field->subfields();
270
    my @subfields = $field->subfields();
214
    my $first = 1;
271
    my $first     = 1;
215
    for (my $i = 0; $i <= $#subfields; $i++) {
272
    for ( my $i = 0 ; $i <= $#subfields ; $i++ ) {
216
        my $code = $subfields[$i]->[0];
273
        my $code    = $subfields[$i]->[0];
217
        my $code_re = quotemeta $code;
274
        my $code_re = quotemeta $code;
218
        my $value = $subfields[$i]->[1];
275
        my $value   = $subfields[$i]->[1];
219
        next unless $subfields =~ qr/$code_re/;
276
        next unless $subfields =~ qr/$code_re/;
220
        if ($first) {
277
        if ($first) {
221
            $first = 0;
278
            $first   = 0;
222
            $heading = $value;
279
            $heading = $value;
223
        } else {
280
        }
224
            if (exists $subdivisions{$code}) {
281
        else {
282
            if ( exists $subdivisions{$code} ) {
225
                $heading .= "--$value";
283
                $heading .= "--$value";
226
            } else {
284
            }
285
            else {
227
                $heading .= " $value";
286
                $heading .= " $value";
228
            }
287
            }
229
        }
288
        }
Lines 231-236 sub _get_display_heading { Link Here
231
    return $heading;
290
    return $heading;
232
}
291
}
233
292
293
# Additional limiters that we aren't using:
294
#    if ($self->{'subject_added_entry'}) {
295
#        $limiters .= " AND Heading-use-subject-added-entry=a";
296
#    }
297
#    if ($self->{'series_added_entry'}) {
298
#        $limiters .= " AND Heading-use-series-added-entry=a";
299
#    }
300
#    if (not $self->{'subject_added_entry'} and not $self->{'series_added_entry'}) {
301
#        $limiters .= " AND Heading-use-main-or-added-entry=a"
302
#    }
303
234
=head1 AUTHOR
304
=head1 AUTHOR
235
305
236
Koha Development Team <http://koha-community.org/>
306
Koha Development Team <http://koha-community.org/>
(-)a/C4/Heading/UNIMARC.pm (+207 lines)
Line 0 Link Here
1
package C4::Heading::UNIMARC;
2
3
# Copyright (C) 2011 C & P Bibliography Services
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 2 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use 5.010;
21
use strict;
22
use warnings;
23
use MARC::Record;
24
use MARC::Field;
25
use C4::Context;
26
27
our $VERSION = 3.00;
28
29
=head1 NAME
30
31
C4::Heading::UNIMARC
32
33
=head1 SYNOPSIS
34
35
use C4::Heading::UNIMARC;
36
37
=head1 DESCRIPTION
38
39
This is an internal helper class used by
40
C<C4::Heading> to parse headings data from
41
UNIMARC records.  Object of this type
42
do not carry data, instead, they only
43
dispatch functions.
44
45
=head1 DATA STRUCTURES
46
47
FIXME - this should be moved to a configuration file.
48
49
=head2 subdivisions
50
51
=cut
52
53
my %subdivisions = (
54
    'j' => 'formsubdiv',
55
    'x' => 'generalsubdiv',
56
    'y' => 'chronologicalsubdiv',
57
    'z' => 'geographicsubdiv',
58
);
59
60
my $bib_heading_fields;
61
62
BEGIN {
63
    my $dbh = C4::Context->dbh;
64
    my $sth = $dbh->prepare(
65
        "SELECT tagfield, authtypecode
66
         FROM marc_subfield_structure
67
         WHERE frameworkcode = '' AND authtypecode <> ''"
68
    );
69
    $sth->execute();
70
    $bib_heading_fields = {};
71
    while ( my ( $tag, $auth_type ) = $sth->fetchrow ) {
72
        $bib_heading_fields->{$tag} = {
73
            auth_type => $auth_type,
74
            subfields => 'abcdefghjklmnopqrstvxyz',
75
        };
76
    }
77
}
78
79
=head1 METHODS
80
81
=head2 new
82
83
  my $marc_handler = C4::Heading::UNIMARC->new();
84
85
=cut
86
87
sub new {
88
    my $class = shift;
89
    return bless {}, $class;
90
}
91
92
=head2 valid_bib_heading_tag
93
94
=cut
95
96
sub valid_bib_heading_tag {
97
    my ( $self, $tag ) = @_;
98
    return $bib_heading_fields->{$tag};
99
}
100
101
=head2 parse_heading
102
103
=cut
104
105
sub parse_heading {
106
    my ( $self, $field ) = @_;
107
108
    my $tag        = $field->tag;
109
    my $field_info = $bib_heading_fields->{$tag};
110
    my $auth_type  = $field_info->{'auth_type'};
111
    my $search_heading =
112
      _get_search_heading( $field, $field_info->{'subfields'} );
113
    my $display_heading =
114
      _get_display_heading( $field, $field_info->{'subfields'} );
115
116
    return ( $auth_type, undef, $search_heading, $display_heading, 'exact' );
117
}
118
119
=head1 INTERNAL FUNCTIONS
120
121
=head2 _get_subject_thesaurus
122
123
=cut
124
125
sub _get_subject_thesaurus {
126
    my $field = shift;
127
128
    my $thesaurus = "notdefined";
129
    my $sf2       = $field->subfield('2');
130
    $thesaurus = $sf2 if defined($sf2);
131
132
    return $thesaurus;
133
}
134
135
=head2 _get_search_heading
136
137
=cut
138
139
sub _get_search_heading {
140
    my $field     = shift;
141
    my $subfields = shift;
142
143
    my $heading   = "";
144
    my @subfields = $field->subfields();
145
    my $first     = 1;
146
    for ( my $i = 0 ; $i <= $#subfields ; $i++ ) {
147
        my $code    = $subfields[$i]->[0];
148
        my $code_re = quotemeta $code;
149
        my $value   = $subfields[$i]->[1];
150
        $value =~ s/[-,.:=;!%\/]*$//;
151
        next unless $subfields =~ qr/$code_re/;
152
        if ($first) {
153
            $first   = 0;
154
            $heading = $value;
155
        }
156
        else {
157
            $heading .= " $value";
158
        }
159
    }
160
161
    # remove characters that are part of CCL syntax
162
    $heading =~ s/[)(=]//g;
163
164
    return $heading;
165
}
166
167
=head2 _get_display_heading
168
169
=cut
170
171
sub _get_display_heading {
172
    my $field     = shift;
173
    my $subfields = shift;
174
175
    my $heading   = "";
176
    my @subfields = $field->subfields();
177
    my $first     = 1;
178
    for ( my $i = 0 ; $i <= $#subfields ; $i++ ) {
179
        my $code    = $subfields[$i]->[0];
180
        my $code_re = quotemeta $code;
181
        my $value   = $subfields[$i]->[1];
182
        next unless $subfields =~ qr/$code_re/;
183
        if ($first) {
184
            $first   = 0;
185
            $heading = $value;
186
        }
187
        else {
188
            if ( exists $subdivisions{$code} ) {
189
                $heading .= "--$value";
190
            }
191
            else {
192
                $heading .= " $value";
193
            }
194
        }
195
    }
196
    return $heading;
197
}
198
199
=head1 AUTHOR
200
201
Koha Development Team <http://koha-community.org/>
202
203
Jared Camins-Esakov <jcamins@cpbibliography.com>
204
205
=cut
206
207
1;
(-)a/C4/Linker.pm (+123 lines)
Line 0 Link Here
1
package C4::Linker;
2
3
# Copyright 2011 C & P Bibliography Services
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 2 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
=head1 NAME
21
22
C4::Linker - Base class for linking authorities to bibliographic records
23
24
=head1 SYNOPSIS
25
26
  use C4::Linker (%params );
27
28
=head1 DESCRIPTION
29
30
Base class for C4::Linker::X. Subclasses need to provide the following methods
31
32
B<get_link ($field)> - return the authid for the authority that should be
33
linked to the provided MARC::Field object, and a boolean to indicate whether
34
the match is "fuzzy" (the semantics of "fuzzy" are up to the individual plugin).
35
In order to handle authority limits, get_link should always end with:
36
    return $self->SUPER::_handle_auth_limit($authid), $fuzzy;
37
38
B<flip_heading ($field)> - return a MARC::Field object with the heading flipped
39
to the preferred form.
40
41
=head1 FUNCTIONS
42
43
=cut
44
45
use strict;
46
use warnings;
47
use Carp;
48
use C4::Context;
49
50
use base qw(Class::Accessor);
51
52
__PACKAGE__->mk_accessors(qw( ));
53
54
sub new {
55
    my $class = shift;
56
    my $param = shift;
57
58
    my $self = {};
59
60
    while ( my ( $key, $value ) = each %$param ) {
61
        if ( $key eq 'auth_limit' && $value ) {
62
            my $dbh = C4::Context->dbh;
63
            my $sql =
64
              "SELECT authid FROM auth_header WHERE $value ORDER BY authid ASC";
65
            my $sth = $dbh->prepare($sql);
66
            $sth->execute();
67
            while ( my ($authid) = $sth->fetchrow_array() ) {
68
                push @{ $self->{'auths_to_link'} }, $authid;
69
            }
70
        }
71
        elsif ( $key eq 'options' && $value ) {
72
            foreach my $opt ( split( /\|/, $value ) ) {
73
                $self->{$opt} = 1;
74
            }
75
        }
76
        elsif ($value) {
77
            $self->{$key} = $value;
78
        }
79
    }
80
81
    bless $self, $class;
82
    return $self;
83
}
84
85
=head2 _handle_auth_limit
86
87
    return $self->SUPER::_handle_auth_limit($authid), $fuzzy;
88
89
=back
90
91
Function to be called by subclasses to handle authority record limits.
92
93
=cut
94
95
sub _handle_auth_limit {
96
    my $self   = shift;
97
    my $authid = shift;
98
99
    if ( defined $self->{'auths_to_link'} && !grep { $_ eq $authid }
100
        @{ $self->{'auths_to_link'} } )
101
    {
102
        undef $authid;
103
    }
104
    return $authid;
105
}
106
107
=head2 EXPORT
108
109
None by default.
110
111
=head1 SEE ALSO
112
113
C4::Linker::Default
114
115
=head1 AUTHOR
116
117
Jared Camins-Esakov, C & P Bibliography Services, E<lt>jcamins@cpbibliography.comE<gt>
118
119
=cut
120
121
1;
122
123
__END__
(-)a/C4/Linker/Default.pm (+97 lines)
Line 0 Link Here
1
package C4::Linker::Default;
2
3
# Copyright 2011 C & P Bibliography Services
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 2 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use strict;
21
use warnings;
22
use Carp;
23
use MARC::Field;
24
use C4::Heading;
25
26
use base qw(C4::Linker);
27
28
sub get_link {
29
    my $self        = shift;
30
    my $heading     = shift;
31
    my $behavior    = shift || 'default';
32
    my $search_form = $heading->search_form();
33
    my $authid;
34
    my $fuzzy = 0;
35
36
    if ( $self->{'cache'}->{$search_form}->{'cached'} ) {
37
        $authid = $self->{'cache'}->{$search_form}->{'authid'};
38
        $fuzzy  = $self->{'cache'}->{$search_form}->{'fuzzy'};
39
    }
40
    else {
41
42
        # look for matching authorities
43
        my $authorities = $heading->authorities(1);    # $skipmetadata = true
44
45
        if ( $behavior eq 'default' && $#{$authorities} == 0 ) {
46
            $authid = $authorities->[0]->{'authid'};
47
        }
48
        elsif ( $behavior eq 'first' && $#{$authorities} >= 0 ) {
49
            $authid = $authorities->[0]->{'authid'};
50
            $fuzzy  = $#{$authorities} > 0;
51
        }
52
        elsif ( $behavior eq 'last' && $#{$authorities} >= 0 ) {
53
            $authid = $authorities->[ $#{$authorities} ]->{'authid'};
54
            $fuzzy  = $#{$authorities} > 0;
55
        }
56
57
        if ( !defined $authid && $self->{'broader_headings'} ) {
58
            my $field     = $heading->field();
59
            my @subfields = $field->subfields();
60
            if ( scalar @subfields > 1 ) {
61
                pop @subfields;
62
                $field->replace_with(
63
                    MARC::Field->new(
64
                        $field->tag,
65
                        $field->indicator(1),
66
                        $field->indicator(2),
67
                        map { $_[0] => $_[1] } @subfields
68
                    )
69
                );
70
                ( $authid, $fuzzy ) =
71
                  $self->get_link( C4::Heading->new_from_bib_field($field),
72
                    $behavior );
73
            }
74
        }
75
76
        $self->{'cache'}->{$search_form}->{'cached'} = 1;
77
        $self->{'cache'}->{$search_form}->{'authid'} = $authid;
78
        $self->{'cache'}->{$search_form}->{'fuzzy'}  = $fuzzy;
79
    }
80
    return $self->SUPER::_handle_auth_limit($authid), $fuzzy;
81
}
82
83
sub flip_heading {
84
    my $self    = shift;
85
    my $heading = shift;
86
87
    # TODO: implement
88
}
89
90
1;
91
__END__
92
93
=head1 NAME
94
95
C4::Linker::Default - match only if there is a single matching auth
96
97
=cut
(-)a/C4/Linker/FirstMatch.pm (+58 lines)
Line 0 Link Here
1
package C4::Linker::FirstMatch;
2
3
# Copyright 2011 C & P Bibliography Services
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 2 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use strict;
21
use warnings;
22
use Carp;
23
use C4::Heading;
24
use C4::Linker::Default;    # Use Default for flipping
25
26
use base qw(C4::Linker);
27
28
sub new {
29
    my $class = shift;
30
    my $param = shift;
31
32
    my $self = $class->SUPER::new($param);
33
    $self->{'default_linker'} = C4::Linker::Default->new($param);
34
    bless $self, $class;
35
    return $self;
36
}
37
38
sub get_link {
39
    my $self    = shift;
40
    my $heading = shift;
41
    return $self->{'default_linker'}->get_link( $heading, 'first' );
42
}
43
44
sub flip_heading {
45
    my $self    = shift;
46
    my $heading = shift;
47
48
    return $self->{'default_linker'}->flip($heading);
49
}
50
51
1;
52
__END__
53
54
=head1 NAME
55
56
C4::Linker::FirstMatch - match against the first authority record
57
58
=cut
(-)a/C4/Linker/LastMatch.pm (+58 lines)
Line 0 Link Here
1
package C4::Linker::LastMatch;
2
3
# Copyright 2011 C & P Bibliography Services
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 2 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use strict;
21
use warnings;
22
use Carp;
23
use C4::Heading;
24
use C4::Linker::Default;    # Use Default for flipping
25
26
use base qw(C4::Linker);
27
28
sub new {
29
    my $class = shift;
30
    my $param = shift;
31
32
    my $self = $class->SUPER::new($param);
33
    $self->{'default_linker'} = C4::Linker::Default->new($param);
34
    bless $self, $class;
35
    return $self;
36
}
37
38
sub get_link {
39
    my $self    = shift;
40
    my $heading = shift;
41
    return $self->{'default_linker'}->get_link( $heading, 'last' );
42
}
43
44
sub flip_heading {
45
    my $self    = shift;
46
    my $heading = shift;
47
48
    return $self->{'default_linker'}->flip($heading);
49
}
50
51
1;
52
__END__
53
54
=head1 NAME
55
56
C4::Linker::LastMatch - match against the last authority record
57
58
=cut
(-)a/C4/Search.pm (-101 lines)
Lines 68-76 This module provides searching functions for Koha's bibliographic databases Link Here
68
  &NZgetRecords
68
  &NZgetRecords
69
  &AddSearchHistory
69
  &AddSearchHistory
70
  &GetDistinctValues
70
  &GetDistinctValues
71
  &BiblioAddAuthorities
72
);
71
);
73
#FIXME: i had to add BiblioAddAuthorities here because in Biblios.pm it caused circular dependencies (C4::Search uses C4::Biblio, and BiblioAddAuthorities uses SimpleSearch from C4::Search)
74
72
75
# make all your functions, whether exported or not;
73
# make all your functions, whether exported or not;
76
74
Lines 2638-2742 sub z3950_search_args { Link Here
2638
    return $array;
2636
    return $array;
2639
}
2637
}
2640
2638
2641
=head2 BiblioAddAuthorities
2642
2643
( $countlinked, $countcreated ) = BiblioAddAuthorities($record, $frameworkcode);
2644
2645
this function finds the authorities linked to the biblio
2646
    * search in the authority DB for the same authid (in $9 of the biblio)
2647
    * search in the authority DB for the same 001 (in $3 of the biblio in UNIMARC)
2648
    * search in the authority DB for the same values (exactly) (in all subfields of the biblio)
2649
OR adds a new authority record
2650
2651
=over 2
2652
2653
=item C<input arg:>
2654
2655
    * $record is the MARC record in question (marc blob)
2656
    * $frameworkcode is the bibliographic framework to use (if it is "" it uses the default framework)
2657
2658
=item C<Output arg:>
2659
2660
    * $countlinked is the number of authorities records that are linked to this authority
2661
    * $countcreated
2662
2663
=item C<BUGS>
2664
    * I had to add this to Search.pm (instead of the logical Biblio.pm) because of a circular dependency (this sub uses SimpleSearch, and Search.pm uses Biblio.pm)
2665
2666
=back
2667
2668
=cut
2669
2670
2671
sub BiblioAddAuthorities{
2672
  my ( $record, $frameworkcode ) = @_;
2673
  my $dbh=C4::Context->dbh;
2674
  my $query=$dbh->prepare(qq|
2675
SELECT authtypecode,tagfield
2676
FROM marc_subfield_structure
2677
WHERE frameworkcode=?
2678
AND (authtypecode IS NOT NULL AND authtypecode<>\"\")|);
2679
# SELECT authtypecode,tagfield
2680
# FROM marc_subfield_structure
2681
# WHERE frameworkcode=?
2682
# AND (authtypecode IS NOT NULL OR authtypecode<>\"\")|);
2683
  $query->execute($frameworkcode);
2684
  my ($countcreated,$countlinked);
2685
  while (my $data=$query->fetchrow_hashref){
2686
    foreach my $field ($record->field($data->{tagfield})){
2687
      next if ($field->subfield('3')||$field->subfield('9'));
2688
      # No authorities id in the tag.
2689
      # Search if there is any authorities to link to.
2690
      my $query='at='.$data->{authtypecode}.' ';
2691
      map {$query.= ' and he,ext="'.$_->[1].'"' if ($_->[0]=~/[A-z]/)}  $field->subfields();
2692
      my ($error, $results, $total_hits)=SimpleSearch( $query, undef, undef, [ "authorityserver" ] );
2693
    # there is only 1 result
2694
          if ( $error ) {
2695
        warn "BIBLIOADDSAUTHORITIES: $error";
2696
            return (0,0) ;
2697
          }
2698
      if ( @{$results} == 1 ) {
2699
        my $marcrecord = MARC::File::USMARC::decode($results->[0]);
2700
        $field->add_subfields('9'=>$marcrecord->field('001')->data);
2701
        $countlinked++;
2702
      } elsif ( @{$results} > 1 ) {
2703
   #More than One result
2704
   #This can comes out of a lack of a subfield.
2705
#         my $marcrecord = MARC::File::USMARC::decode($results->[0]);
2706
#         $record->field($data->{tagfield})->add_subfields('9'=>$marcrecord->field('001')->data);
2707
  $countlinked++;
2708
      } else {
2709
  #There are no results, build authority record, add it to Authorities, get authid and add it to 9
2710
  ###NOTICE : This is only valid if a subfield is linked to one and only one authtypecode
2711
  ###NOTICE : This can be a problem. We should also look into other types and rejected forms.
2712
         my $authtypedata=C4::AuthoritiesMarc::GetAuthType($data->{authtypecode});
2713
         next unless $authtypedata;
2714
         my $marcrecordauth=MARC::Record->new();
2715
         my $authfield=MARC::Field->new($authtypedata->{auth_tag_to_report},'','',"a"=>"".$field->subfield('a'));
2716
         map { $authfield->add_subfields($_->[0]=>$_->[1]) if ($_->[0]=~/[A-z]/ && $_->[0] ne "a" )}  $field->subfields();
2717
         $marcrecordauth->insert_fields_ordered($authfield);
2718
2719
         # bug 2317: ensure new authority knows it's using UTF-8; currently
2720
         # only need to do this for MARC21, as MARC::Record->as_xml_record() handles
2721
         # automatically for UNIMARC (by not transcoding)
2722
         # FIXME: AddAuthority() instead should simply explicitly require that the MARC::Record
2723
         # use UTF-8, but as of 2008-08-05, did not want to introduce that kind
2724
         # of change to a core API just before the 3.0 release.
2725
         if (C4::Context->preference('marcflavour') eq 'MARC21') {
2726
            SetMarcUnicodeFlag($marcrecordauth, 'MARC21');
2727
         }
2728
2729
#          warn "AUTH RECORD ADDED : ".$marcrecordauth->as_formatted;
2730
2731
         my $authid=AddAuthority($marcrecordauth,'',$data->{authtypecode});
2732
         $countcreated++;
2733
         $field->add_subfields('9'=>$authid);
2734
      }
2735
    }
2736
  }
2737
  return ($countlinked,$countcreated);
2738
}
2739
2740
=head2 GetDistinctValues($field);
2639
=head2 GetDistinctValues($field);
2741
2640
2742
C<$field> is a reference to the fields array
2641
C<$field> is a reference to the fields array
(-)a/acqui/addorderiso2709.pl (-2 / +2 lines)
Lines 33-39 use C4::Input; Link Here
33
use C4::Output;
33
use C4::Output;
34
use C4::ImportBatch;
34
use C4::ImportBatch;
35
use C4::Matcher;
35
use C4::Matcher;
36
use C4::Search qw/FindDuplicate BiblioAddAuthorities/;
36
use C4::Search qw/FindDuplicate/;
37
use C4::Acquisition;
37
use C4::Acquisition;
38
use C4::Biblio;
38
use C4::Biblio;
39
use C4::Items;
39
use C4::Items;
Lines 183-189 if ($op eq ""){ Link Here
183
            SetImportRecordStatus( $biblio->{'import_record_id'}, 'imported' );
183
            SetImportRecordStatus( $biblio->{'import_record_id'}, 'imported' );
184
            # 2nd add authorities if applicable
184
            # 2nd add authorities if applicable
185
            if (C4::Context->preference("BiblioAddsAuthorities")){
185
            if (C4::Context->preference("BiblioAddsAuthorities")){
186
                my ($countlinked,$countcreated)=BiblioAddAuthorities($marcrecord, $cgiparams->{'frameworkcode'});
186
                my $headings_linked =BiblioAutoLink($marcrecord, $cgiparams->{'frameworkcode'});
187
            }
187
            }
188
        } else {
188
        } else {
189
            SetImportRecordStatus( $biblio->{'import_record_id'}, 'imported' );
189
            SetImportRecordStatus( $biblio->{'import_record_id'}, 'imported' );
(-)a/acqui/neworderempty.pl (-2 / +2 lines)
Lines 86-92 use C4::Input; Link Here
86
use C4::Koha;
86
use C4::Koha;
87
use C4::Branch;			# GetBranches
87
use C4::Branch;			# GetBranches
88
use C4::Members;
88
use C4::Members;
89
use C4::Search qw/FindDuplicate BiblioAddAuthorities/;
89
use C4::Search qw/FindDuplicate/;
90
90
91
#needed for z3950 import:
91
#needed for z3950 import:
92
use C4::ImportBatch qw/GetImportRecordMarc SetImportRecordStatus/;
92
use C4::ImportBatch qw/GetImportRecordMarc SetImportRecordStatus/;
Lines 148-154 if ( $ordernumber eq '' and defined $params->{'breedingid'}){ Link Here
148
    }
148
    }
149
    #from this point: add a new record
149
    #from this point: add a new record
150
        if (C4::Context->preference("BiblioAddsAuthorities")){
150
        if (C4::Context->preference("BiblioAddsAuthorities")){
151
            my ($countlinked,$countcreated)=BiblioAddAuthorities($marcrecord, $params->{'frameworkcode'});
151
            my $headings_linked=BiblioAutoLink($marcrecord, $params->{'frameworkcode'});
152
        }
152
        }
153
        my $bibitemnum;
153
        my $bibitemnum;
154
        $params->{'frameworkcode'} or $params->{'frameworkcode'} = "";
154
        $params->{'frameworkcode'} or $params->{'frameworkcode'} = "";
(-)a/authorities/auth_finder.pl (-4 / +4 lines)
Lines 60-66 if ( $op eq "do_search" ) { Link Here
60
    my @and_or    = $query->param('and_or');
60
    my @and_or    = $query->param('and_or');
61
    my @excluding = $query->param('excluding');
61
    my @excluding = $query->param('excluding');
62
    my @operator  = $query->param('operator');
62
    my @operator  = $query->param('operator');
63
    my @value     = ($query->param('value_mainstr')||undef, $query->param('value_main')||undef, $query->param('value_any')||undef);
63
    my @value     = ($query->param('value_mainstr')||undef, $query->param('value_main')||undef, $query->param('value_any')||undef, $query->param('value_match')||undef);
64
    my $orderby   = $query->param('orderby');
64
    my $orderby   = $query->param('orderby');
65
65
66
    $resultsperpage = $query->param('resultsperpage');
66
    $resultsperpage = $query->param('resultsperpage');
Lines 106-111 if ( $op eq "do_search" ) { Link Here
106
    push @field_data, { term => "value_mainstr", val => $query->param('value_mainstr') || "" };
106
    push @field_data, { term => "value_mainstr", val => $query->param('value_mainstr') || "" };
107
    push @field_data, { term => "value_main",    val => $query->param('value_main')    || "" };
107
    push @field_data, { term => "value_main",    val => $query->param('value_main')    || "" };
108
    push @field_data, { term => "value_any",     val => $query->param('value_any')     || ""};
108
    push @field_data, { term => "value_any",     val => $query->param('value_any')     || ""};
109
    push @field_data, { term => "value_match",   val => $query->param('value_match')   || ""};
109
110
110
    my @numbers = ();
111
    my @numbers = ();
111
112
Lines 162-167 if ( $op eq "do_search" ) { Link Here
162
        value_mainstr  => $query->param('value_mainstr') || "", 
163
        value_mainstr  => $query->param('value_mainstr') || "", 
163
        value_main     => $query->param('value_main') || "",
164
        value_main     => $query->param('value_main') || "",
164
        value_any      => $query->param('value_any') || "",
165
        value_any      => $query->param('value_any') || "",
166
        value_match    => $query->param('value_match') || "",
165
    );
167
    );
166
} else {
168
} else {
167
    ( $template, $loggedinuser, $cookie ) = get_template_and_user(
169
    ( $template, $loggedinuser, $cookie ) = get_template_and_user(
Lines 183-195 $template->param( Link Here
183
    value_mainstr => $query->param('value_mainstr') || "", 
185
    value_mainstr => $query->param('value_mainstr') || "", 
184
    value_main    => $query->param('value_main') || "",
186
    value_main    => $query->param('value_main') || "",
185
    value_any     => $query->param('value_any') || "",
187
    value_any     => $query->param('value_any') || "",
188
    value_match   => $query->param('value_match') || "",
186
    tagid         => $tagid,
189
    tagid         => $tagid,
187
    index         => $index,
190
    index         => $index,
188
    authtypesloop => \@authtypesloop,
191
    authtypesloop => \@authtypesloop,
189
    authtypecode  => $authtypecode,
192
    authtypecode  => $authtypecode,
190
    value_mainstr  => $query->param('value_mainstr') || "", 
191
    value_main     => $query->param('value_main')    || "",
192
    value_any      => $query->param('value_any')     || "",
193
);
193
);
194
194
195
# Print the page
195
# Print the page
(-)a/cataloguing/addbiblio.pl (-90 / +1 lines)
Lines 736-830 sub build_tabs { Link Here
736
    $template->param( BIG_LOOP => \@BIG_LOOP );
736
    $template->param( BIG_LOOP => \@BIG_LOOP );
737
}
737
}
738
738
739
#
740
# sub that tries to find authorities linked to the biblio
741
# the sub :
742
#   - search in the authority DB for the same authid (in $9 of the biblio)
743
#   - search in the authority DB for the same 001 (in $3 of the biblio in UNIMARC)
744
#   - search in the authority DB for the same values (exactly) (in all subfields of the biblio)
745
# if the authority is found, the biblio is modified accordingly to be connected to the authority.
746
# if the authority is not found, it's added, and the biblio is then modified to be connected to the authority.
747
#
748
749
sub BiblioAddAuthorities{
750
  my ( $record, $frameworkcode ) = @_;
751
  my $dbh=C4::Context->dbh;
752
  my $query=$dbh->prepare(qq|
753
SELECT authtypecode,tagfield
754
FROM marc_subfield_structure 
755
WHERE frameworkcode=? 
756
AND (authtypecode IS NOT NULL AND authtypecode<>\"\")|);
757
# SELECT authtypecode,tagfield
758
# FROM marc_subfield_structure 
759
# WHERE frameworkcode=? 
760
# AND (authtypecode IS NOT NULL OR authtypecode<>\"\")|);
761
  $query->execute($frameworkcode);
762
  my ($countcreated,$countlinked);
763
  while (my $data=$query->fetchrow_hashref){
764
    foreach my $field ($record->field($data->{tagfield})){
765
      next if ($field->subfield('3') || $field->subfield('9'));
766
      # No authorities id in the tag.
767
      # Search if there is any authorities to link to.
768
      my $query='at='.$data->{authtypecode}.' ';
769
      map {$query.= ' and he,ext="'.$_->[1].'"' if ($_->[0]=~/[A-z]/)}  $field->subfields();
770
      my ($error, $results, $total_hits)=SimpleSearch( $query, undef, undef, [ "authorityserver" ] );
771
    # there is only 1 result 
772
	  if ( $error ) {
773
        warn "BIBLIOADDSAUTHORITIES: $error";
774
	    return (0,0) ;
775
	  }
776
      if ( @{$results} == 1) {
777
        my $marcrecord = MARC::File::USMARC::decode($results->[0]);
778
        $field->add_subfields('9'=>$marcrecord->field('001')->data);
779
        $countlinked++;
780
      } elsif (@{$results} > 1) {
781
   #More than One result 
782
   #This can comes out of a lack of a subfield.
783
#         my $marcrecord = MARC::File::USMARC::decode($results->[0]);
784
#         $record->field($data->{tagfield})->add_subfields('9'=>$marcrecord->field('001')->data);
785
        $countlinked++;
786
      } else {
787
  #There are no results, build authority record, add it to Authorities, get authid and add it to 9
788
  ###NOTICE : This is only valid if a subfield is linked to one and only one authtypecode     
789
  ###NOTICE : This can be a problem. We should also look into other types and rejected forms.
790
         my $authtypedata=GetAuthType($data->{authtypecode});
791
         next unless $authtypedata;
792
         my $marcrecordauth=MARC::Record->new();
793
		if (C4::Context->preference('marcflavour') eq 'MARC21') {
794
			$marcrecordauth->leader('     nz  a22     o  4500');
795
			SetMarcUnicodeFlag($marcrecordauth, 'MARC21');
796
			}
797
         my $authfield=MARC::Field->new($authtypedata->{auth_tag_to_report},'','',"a"=>"".$field->subfield('a'));
798
         map { $authfield->add_subfields($_->[0]=>$_->[1]) if ($_->[0]=~/[A-z]/ && $_->[0] ne "a" )}  $field->subfields();
799
         $marcrecordauth->insert_fields_ordered($authfield);
800
801
         # bug 2317: ensure new authority knows it's using UTF-8; currently
802
         # only need to do this for MARC21, as MARC::Record->as_xml_record() handles
803
         # automatically for UNIMARC (by not transcoding)
804
         # FIXME: AddAuthority() instead should simply explicitly require that the MARC::Record
805
         # use UTF-8, but as of 2008-08-05, did not want to introduce that kind
806
         # of change to a core API just before the 3.0 release.
807
808
				if (C4::Context->preference('marcflavour') eq 'MARC21') {
809
					$marcrecordauth->insert_fields_ordered(MARC::Field->new('667','','','a'=>"Machine generated authority record."));
810
					my $cite = $record->author() . ", " .  $record->title_proper() . ", " . $record->publication_date() . " "; 
811
					$cite =~ s/^[\s\,]*//;
812
					$cite =~ s/[\s\,]*$//;
813
					$cite = "Work cat.: (" . C4::Context->preference('MARCOrgCode') . ")". $record->subfield('999','c') . ": " . $cite;
814
					$marcrecordauth->insert_fields_ordered(MARC::Field->new('670','','','a'=>$cite));
815
				}
816
817
#          warn "AUTH RECORD ADDED : ".$marcrecordauth->as_formatted;
818
819
         my $authid=AddAuthority($marcrecordauth,'',$data->{authtypecode});
820
         $countcreated++;
821
         $field->add_subfields('9'=>$authid);
822
      }
823
    }  
824
  }
825
  return ($countlinked,$countcreated);
826
}
827
828
# ========================
739
# ========================
829
#          MAIN
740
#          MAIN
830
#=========================
741
#=========================
Lines 957-963 if ( $op eq "addbiblio" ) { Link Here
957
        my $oldbibnum;
868
        my $oldbibnum;
958
        my $oldbibitemnum;
869
        my $oldbibitemnum;
959
        if (C4::Context->preference("BiblioAddsAuthorities")){
870
        if (C4::Context->preference("BiblioAddsAuthorities")){
960
          my ($countlinked,$countcreated)=BiblioAddAuthorities($record,$frameworkcode);
871
          my ($countlinked,$countcreated)=BiblioAutoLink($record,$frameworkcode);
961
        } 
872
        } 
962
        if ( $is_a_modif ) {
873
        if ( $is_a_modif ) {
963
            ModBiblioframework( $biblionumber, $frameworkcode ); 
874
            ModBiblioframework( $biblionumber, $frameworkcode ); 
(-)a/etc/zebradb/authorities/etc/bib1.att (+1 lines)
Lines 74-79 att 8807 Subdivision-see-also-from Link Here
74
att 8808    Subdivision-see-from
74
att 8808    Subdivision-see-from
75
att 8809    Match-heading-see-from
75
att 8809    Match-heading-see-from
76
att 8810    Match-subdivision-see-from
76
att 8810    Match-subdivision-see-from
77
att 8900    Match
77
78
78
# General Subdivision (defined in att 47)
79
# General Subdivision (defined in att 47)
79
att 9023    General-subdivision
80
att 9023    General-subdivision
(-)a/etc/zebradb/marc_defs/marc21/authorities/authority-koha-indexdefs.xml (+64 lines)
Lines 65-70 authority-zebra-indexdefs.xsl` Link Here
65
    <kohaidx:target_index>Heading-Main:s</kohaidx:target_index>
65
    <kohaidx:target_index>Heading-Main:s</kohaidx:target_index>
66
  </kohaidx:index_heading>
66
  </kohaidx:index_heading>
67
  <kohaidx:index_match_heading tag="100" subfields="abcdefghjklmnopqrstvxyz" subdivisions="vxyz">
67
  <kohaidx:index_match_heading tag="100" subfields="abcdefghjklmnopqrstvxyz" subdivisions="vxyz">
68
    <kohaidx:target_index>Match:w</kohaidx:target_index>
69
    <kohaidx:target_index>Match:p</kohaidx:target_index>
68
    <kohaidx:target_index>Match-heading:p</kohaidx:target_index>
70
    <kohaidx:target_index>Match-heading:p</kohaidx:target_index>
69
    <kohaidx:target_index>Match-heading:s</kohaidx:target_index>
71
    <kohaidx:target_index>Match-heading:s</kohaidx:target_index>
70
  </kohaidx:index_match_heading>
72
  </kohaidx:index_match_heading>
Lines 78-83 authority-zebra-indexdefs.xsl` Link Here
78
    <kohaidx:target_index>See-from:s</kohaidx:target_index>
80
    <kohaidx:target_index>See-from:s</kohaidx:target_index>
79
  </kohaidx:index_heading>
81
  </kohaidx:index_heading>
80
  <kohaidx:index_match_heading tag="400" subfields="abcdefghjklmnopqrstvxyz" subdivisions="vxyz">
82
  <kohaidx:index_match_heading tag="400" subfields="abcdefghjklmnopqrstvxyz" subdivisions="vxyz">
83
    <kohaidx:target_index>Match:w</kohaidx:target_index>
84
    <kohaidx:target_index>Match:p</kohaidx:target_index>
81
    <kohaidx:target_index>Match-heading-see-from:p</kohaidx:target_index>
85
    <kohaidx:target_index>Match-heading-see-from:p</kohaidx:target_index>
82
    <kohaidx:target_index>Match-heading-see-from:s</kohaidx:target_index>
86
    <kohaidx:target_index>Match-heading-see-from:s</kohaidx:target_index>
83
  </kohaidx:index_match_heading>
87
  </kohaidx:index_match_heading>
Lines 90-95 authority-zebra-indexdefs.xsl` Link Here
90
    <kohaidx:target_index>See-also-from:p</kohaidx:target_index>
94
    <kohaidx:target_index>See-also-from:p</kohaidx:target_index>
91
    <kohaidx:target_index>See-also-from:s</kohaidx:target_index>
95
    <kohaidx:target_index>See-also-from:s</kohaidx:target_index>
92
  </kohaidx:index_heading>
96
  </kohaidx:index_heading>
97
  <kohaidx:index_match_heading tag="500" subfields="abcdefghjklmnopqrstvxyz" subdivisions="vxyz">
98
    <kohaidx:target_index>Match:w</kohaidx:target_index>
99
    <kohaidx:target_index>Match:p</kohaidx:target_index>
100
  </kohaidx:index_match_heading>
93
  
101
  
94
  <!-- Corporate name headings -->
102
  <!-- Corporate name headings -->
95
  <kohaidx:index_subfields tag="110" subfields="abcdefghklmnoprstvxyz">
103
  <kohaidx:index_subfields tag="110" subfields="abcdefghklmnoprstvxyz">
Lines 110-115 authority-zebra-indexdefs.xsl` Link Here
110
    <kohaidx:target_index>Heading-Main:s</kohaidx:target_index>
118
    <kohaidx:target_index>Heading-Main:s</kohaidx:target_index>
111
  </kohaidx:index_heading>
119
  </kohaidx:index_heading>
112
  <kohaidx:index_match_heading tag="110" subfields="abcdefghklmnoprstvxyz" subdivisions="vxyz">
120
  <kohaidx:index_match_heading tag="110" subfields="abcdefghklmnoprstvxyz" subdivisions="vxyz">
121
    <kohaidx:target_index>Match:w</kohaidx:target_index>
122
    <kohaidx:target_index>Match:p</kohaidx:target_index>
113
    <kohaidx:target_index>Match-heading:p</kohaidx:target_index>
123
    <kohaidx:target_index>Match-heading:p</kohaidx:target_index>
114
    <kohaidx:target_index>Match-heading:s</kohaidx:target_index>
124
    <kohaidx:target_index>Match-heading:s</kohaidx:target_index>
115
  </kohaidx:index_match_heading>
125
  </kohaidx:index_match_heading>
Lines 123-128 authority-zebra-indexdefs.xsl` Link Here
123
    <kohaidx:target_index>See-from:s</kohaidx:target_index>
133
    <kohaidx:target_index>See-from:s</kohaidx:target_index>
124
  </kohaidx:index_heading>
134
  </kohaidx:index_heading>
125
  <kohaidx:index_match_heading tag="410" subfields="abcdefghklmnoprstvxyz" subdivisions="vxyz">
135
  <kohaidx:index_match_heading tag="410" subfields="abcdefghklmnoprstvxyz" subdivisions="vxyz">
136
    <kohaidx:target_index>Match:w</kohaidx:target_index>
137
    <kohaidx:target_index>Match:p</kohaidx:target_index>
126
    <kohaidx:target_index>Match-heading-see-from:p</kohaidx:target_index>
138
    <kohaidx:target_index>Match-heading-see-from:p</kohaidx:target_index>
127
    <kohaidx:target_index>Match-heading-see-from:s</kohaidx:target_index>
139
    <kohaidx:target_index>Match-heading-see-from:s</kohaidx:target_index>
128
  </kohaidx:index_match_heading>
140
  </kohaidx:index_match_heading>
Lines 135-140 authority-zebra-indexdefs.xsl` Link Here
135
    <kohaidx:target_index>See-also-from:p</kohaidx:target_index>
147
    <kohaidx:target_index>See-also-from:p</kohaidx:target_index>
136
    <kohaidx:target_index>See-also-from:s</kohaidx:target_index>
148
    <kohaidx:target_index>See-also-from:s</kohaidx:target_index>
137
  </kohaidx:index_heading>
149
  </kohaidx:index_heading>
150
  <kohaidx:index_match_heading tag="510" subfields="abcdefghklmnoprstvxyz" subdivisions="vxyz">
151
    <kohaidx:target_index>Match:w</kohaidx:target_index>
152
    <kohaidx:target_index>Match:p</kohaidx:target_index>
153
  </kohaidx:index_match_heading>
138
  
154
  
139
  <!-- Meeting name -->
155
  <!-- Meeting name -->
140
  <kohaidx:index_subfields tag="111" subfields="acdefghjklnpqstvxyz">
156
  <kohaidx:index_subfields tag="111" subfields="acdefghjklnpqstvxyz">
Lines 155-160 authority-zebra-indexdefs.xsl` Link Here
155
    <kohaidx:target_index>Heading-Main:s</kohaidx:target_index>
171
    <kohaidx:target_index>Heading-Main:s</kohaidx:target_index>
156
  </kohaidx:index_heading>
172
  </kohaidx:index_heading>
157
  <kohaidx:index_match_heading tag="111" subfields="acdefghjklnpqstvxyz" subdivisions="vxyz">
173
  <kohaidx:index_match_heading tag="111" subfields="acdefghjklnpqstvxyz" subdivisions="vxyz">
174
    <kohaidx:target_index>Match:w</kohaidx:target_index>
175
    <kohaidx:target_index>Match:p</kohaidx:target_index>
158
    <kohaidx:target_index>Match-heading:p</kohaidx:target_index>
176
    <kohaidx:target_index>Match-heading:p</kohaidx:target_index>
159
    <kohaidx:target_index>Match-heading:s</kohaidx:target_index>
177
    <kohaidx:target_index>Match-heading:s</kohaidx:target_index>
160
  </kohaidx:index_match_heading>
178
  </kohaidx:index_match_heading>
Lines 168-173 authority-zebra-indexdefs.xsl` Link Here
168
    <kohaidx:target_index>See-from:s</kohaidx:target_index>
186
    <kohaidx:target_index>See-from:s</kohaidx:target_index>
169
  </kohaidx:index_heading>
187
  </kohaidx:index_heading>
170
  <kohaidx:index_match_heading tag="411" subfields="acdefghjklnpqstvxyz" subdivisions="vxyz">
188
  <kohaidx:index_match_heading tag="411" subfields="acdefghjklnpqstvxyz" subdivisions="vxyz">
189
    <kohaidx:target_index>Match:w</kohaidx:target_index>
190
    <kohaidx:target_index>Match:p</kohaidx:target_index>
171
    <kohaidx:target_index>Match-heading-see-from:p</kohaidx:target_index>
191
    <kohaidx:target_index>Match-heading-see-from:p</kohaidx:target_index>
172
    <kohaidx:target_index>Match-heading-see-from:s</kohaidx:target_index>
192
    <kohaidx:target_index>Match-heading-see-from:s</kohaidx:target_index>
173
  </kohaidx:index_match_heading>
193
  </kohaidx:index_match_heading>
Lines 180-185 authority-zebra-indexdefs.xsl` Link Here
180
    <kohaidx:target_index>See-also-from:p</kohaidx:target_index>
200
    <kohaidx:target_index>See-also-from:p</kohaidx:target_index>
181
    <kohaidx:target_index>See-also-from:s</kohaidx:target_index>
201
    <kohaidx:target_index>See-also-from:s</kohaidx:target_index>
182
  </kohaidx:index_heading>
202
  </kohaidx:index_heading>
203
  <kohaidx:index_match_heading tag="511" subfields="acdefghjklnpqstvxyz" subdivisions="vxyz">
204
    <kohaidx:target_index>Match:w</kohaidx:target_index>
205
    <kohaidx:target_index>Match:p</kohaidx:target_index>
206
  </kohaidx:index_match_heading>
183
  
207
  
184
  <!-- Uniform title -->
208
  <!-- Uniform title -->
185
  <kohaidx:index_subfields tag="130" subfields="adfghklmnoprstvxyz">
209
  <kohaidx:index_subfields tag="130" subfields="adfghklmnoprstvxyz">
Lines 200-205 authority-zebra-indexdefs.xsl` Link Here
200
    <kohaidx:target_index>Heading-Main:s</kohaidx:target_index>
224
    <kohaidx:target_index>Heading-Main:s</kohaidx:target_index>
201
  </kohaidx:index_heading>
225
  </kohaidx:index_heading>
202
  <kohaidx:index_match_heading tag="130" subfields="adfghklmnoprstvxyz" subdivisions="vxyz">
226
  <kohaidx:index_match_heading tag="130" subfields="adfghklmnoprstvxyz" subdivisions="vxyz">
227
    <kohaidx:target_index>Match:w</kohaidx:target_index>
228
    <kohaidx:target_index>Match:p</kohaidx:target_index>
203
    <kohaidx:target_index>Match-heading:p</kohaidx:target_index>
229
    <kohaidx:target_index>Match-heading:p</kohaidx:target_index>
204
    <kohaidx:target_index>Match-heading:s</kohaidx:target_index>
230
    <kohaidx:target_index>Match-heading:s</kohaidx:target_index>
205
  </kohaidx:index_match_heading>
231
  </kohaidx:index_match_heading>
Lines 213-218 authority-zebra-indexdefs.xsl` Link Here
213
    <kohaidx:target_index>See-from:s</kohaidx:target_index>
239
    <kohaidx:target_index>See-from:s</kohaidx:target_index>
214
  </kohaidx:index_heading>
240
  </kohaidx:index_heading>
215
  <kohaidx:index_match_heading tag="430" subfields="adfghklmnoprstvxyz" subdivisions="vxyz">
241
  <kohaidx:index_match_heading tag="430" subfields="adfghklmnoprstvxyz" subdivisions="vxyz">
242
    <kohaidx:target_index>Match:w</kohaidx:target_index>
243
    <kohaidx:target_index>Match:p</kohaidx:target_index>
216
    <kohaidx:target_index>Match-heading-see-from:p</kohaidx:target_index>
244
    <kohaidx:target_index>Match-heading-see-from:p</kohaidx:target_index>
217
    <kohaidx:target_index>Match-heading-see-from:s</kohaidx:target_index>
245
    <kohaidx:target_index>Match-heading-see-from:s</kohaidx:target_index>
218
  </kohaidx:index_match_heading>
246
  </kohaidx:index_match_heading>
Lines 225-230 authority-zebra-indexdefs.xsl` Link Here
225
    <kohaidx:target_index>See-also-from:p</kohaidx:target_index>
253
    <kohaidx:target_index>See-also-from:p</kohaidx:target_index>
226
    <kohaidx:target_index>See-also-from:s</kohaidx:target_index>
254
    <kohaidx:target_index>See-also-from:s</kohaidx:target_index>
227
  </kohaidx:index_heading>
255
  </kohaidx:index_heading>
256
  <kohaidx:index_match_heading tag="530" subfields="adfghklmnoprstvxyz" subdivisions="vxyz">
257
    <kohaidx:target_index>Match:w</kohaidx:target_index>
258
    <kohaidx:target_index>Match:p</kohaidx:target_index>
259
  </kohaidx:index_match_heading>
228
  
260
  
229
  <!-- Chronological term -->
261
  <!-- Chronological term -->
230
  <kohaidx:index_subfields tag="148" subfields="avxyz">
262
  <kohaidx:index_subfields tag="148" subfields="avxyz">
Lines 245-250 authority-zebra-indexdefs.xsl` Link Here
245
    <kohaidx:target_index>Heading-Main:s</kohaidx:target_index>
277
    <kohaidx:target_index>Heading-Main:s</kohaidx:target_index>
246
  </kohaidx:index_heading>
278
  </kohaidx:index_heading>
247
  <kohaidx:index_match_heading tag="148" subfields="avxyz" subdivisions="vxyz">
279
  <kohaidx:index_match_heading tag="148" subfields="avxyz" subdivisions="vxyz">
280
    <kohaidx:target_index>Match:w</kohaidx:target_index>
281
    <kohaidx:target_index>Match:p</kohaidx:target_index>
248
    <kohaidx:target_index>Match-heading:p</kohaidx:target_index>
282
    <kohaidx:target_index>Match-heading:p</kohaidx:target_index>
249
    <kohaidx:target_index>Match-heading:s</kohaidx:target_index>
283
    <kohaidx:target_index>Match-heading:s</kohaidx:target_index>
250
  </kohaidx:index_match_heading>
284
  </kohaidx:index_match_heading>
Lines 258-263 authority-zebra-indexdefs.xsl` Link Here
258
    <kohaidx:target_index>See-from:s</kohaidx:target_index>
292
    <kohaidx:target_index>See-from:s</kohaidx:target_index>
259
  </kohaidx:index_heading>
293
  </kohaidx:index_heading>
260
  <kohaidx:index_match_heading tag="448" subfields="avxyz" subdivisions="vxyz">
294
  <kohaidx:index_match_heading tag="448" subfields="avxyz" subdivisions="vxyz">
295
    <kohaidx:target_index>Match:w</kohaidx:target_index>
296
    <kohaidx:target_index>Match:p</kohaidx:target_index>
261
    <kohaidx:target_index>Match-heading-see-from:p</kohaidx:target_index>
297
    <kohaidx:target_index>Match-heading-see-from:p</kohaidx:target_index>
262
    <kohaidx:target_index>Match-heading-see-from:s</kohaidx:target_index>
298
    <kohaidx:target_index>Match-heading-see-from:s</kohaidx:target_index>
263
  </kohaidx:index_match_heading>
299
  </kohaidx:index_match_heading>
Lines 270-275 authority-zebra-indexdefs.xsl` Link Here
270
    <kohaidx:target_index>See-also-from:p</kohaidx:target_index>
306
    <kohaidx:target_index>See-also-from:p</kohaidx:target_index>
271
    <kohaidx:target_index>See-also-from:s</kohaidx:target_index>
307
    <kohaidx:target_index>See-also-from:s</kohaidx:target_index>
272
  </kohaidx:index_heading>
308
  </kohaidx:index_heading>
309
  <kohaidx:index_match_heading tag="548" subfields="avxyz" subdivisions="vxyz">
310
    <kohaidx:target_index>Match:w</kohaidx:target_index>
311
    <kohaidx:target_index>Match:p</kohaidx:target_index>
312
  </kohaidx:index_match_heading>
273
  
313
  
274
  
314
  
275
  <!-- Topical term -->
315
  <!-- Topical term -->
Lines 291-296 authority-zebra-indexdefs.xsl` Link Here
291
    <kohaidx:target_index>Heading-Main:s</kohaidx:target_index>
331
    <kohaidx:target_index>Heading-Main:s</kohaidx:target_index>
292
  </kohaidx:index_heading>
332
  </kohaidx:index_heading>
293
  <kohaidx:index_match_heading tag="150" subfields="abvxyz" subdivisions="vxyz">
333
  <kohaidx:index_match_heading tag="150" subfields="abvxyz" subdivisions="vxyz">
334
    <kohaidx:target_index>Match:w</kohaidx:target_index>
335
    <kohaidx:target_index>Match:p</kohaidx:target_index>
294
    <kohaidx:target_index>Match-heading:p</kohaidx:target_index>
336
    <kohaidx:target_index>Match-heading:p</kohaidx:target_index>
295
    <kohaidx:target_index>Match-heading:s</kohaidx:target_index>
337
    <kohaidx:target_index>Match-heading:s</kohaidx:target_index>
296
  </kohaidx:index_match_heading>
338
  </kohaidx:index_match_heading>
Lines 304-309 authority-zebra-indexdefs.xsl` Link Here
304
    <kohaidx:target_index>See-from:s</kohaidx:target_index>
346
    <kohaidx:target_index>See-from:s</kohaidx:target_index>
305
  </kohaidx:index_heading>
347
  </kohaidx:index_heading>
306
  <kohaidx:index_match_heading tag="450" subfields="abvxyz" subdivisions="vxyz">
348
  <kohaidx:index_match_heading tag="450" subfields="abvxyz" subdivisions="vxyz">
349
    <kohaidx:target_index>Match:w</kohaidx:target_index>
350
    <kohaidx:target_index>Match:p</kohaidx:target_index>
307
    <kohaidx:target_index>Match-heading-see-from:p</kohaidx:target_index>
351
    <kohaidx:target_index>Match-heading-see-from:p</kohaidx:target_index>
308
    <kohaidx:target_index>Match-heading-see-from:s</kohaidx:target_index>
352
    <kohaidx:target_index>Match-heading-see-from:s</kohaidx:target_index>
309
  </kohaidx:index_match_heading>
353
  </kohaidx:index_match_heading>
Lines 316-321 authority-zebra-indexdefs.xsl` Link Here
316
    <kohaidx:target_index>See-also-from:p</kohaidx:target_index>
360
    <kohaidx:target_index>See-also-from:p</kohaidx:target_index>
317
    <kohaidx:target_index>See-also-from:s</kohaidx:target_index>
361
    <kohaidx:target_index>See-also-from:s</kohaidx:target_index>
318
  </kohaidx:index_heading>
362
  </kohaidx:index_heading>
363
  <kohaidx:index_match_heading tag="550" subfields="abvxyz" subdivisions="vxyz">
364
    <kohaidx:target_index>Match:w</kohaidx:target_index>
365
    <kohaidx:target_index>Match:p</kohaidx:target_index>
366
  </kohaidx:index_match_heading>
319
  
367
  
320
  <!-- Geographic name -->
368
  <!-- Geographic name -->
321
  <kohaidx:index_subfields tag="151" subfields="avxyz">
369
  <kohaidx:index_subfields tag="151" subfields="avxyz">
Lines 336-341 authority-zebra-indexdefs.xsl` Link Here
336
    <kohaidx:target_index>Heading-Main:s</kohaidx:target_index>
384
    <kohaidx:target_index>Heading-Main:s</kohaidx:target_index>
337
  </kohaidx:index_heading>
385
  </kohaidx:index_heading>
338
  <kohaidx:index_match_heading tag="151" subfields="avxyz" subdivisions="vxyz">
386
  <kohaidx:index_match_heading tag="151" subfields="avxyz" subdivisions="vxyz">
387
    <kohaidx:target_index>Match:w</kohaidx:target_index>
388
    <kohaidx:target_index>Match:p</kohaidx:target_index>
339
    <kohaidx:target_index>Match-heading:p</kohaidx:target_index>
389
    <kohaidx:target_index>Match-heading:p</kohaidx:target_index>
340
    <kohaidx:target_index>Match-heading:s</kohaidx:target_index>
390
    <kohaidx:target_index>Match-heading:s</kohaidx:target_index>
341
  </kohaidx:index_match_heading>
391
  </kohaidx:index_match_heading>
Lines 349-354 authority-zebra-indexdefs.xsl` Link Here
349
    <kohaidx:target_index>See-from:s</kohaidx:target_index>
399
    <kohaidx:target_index>See-from:s</kohaidx:target_index>
350
  </kohaidx:index_heading>
400
  </kohaidx:index_heading>
351
  <kohaidx:index_match_heading tag="451" subfields="avxyz" subdivisions="vxyz">
401
  <kohaidx:index_match_heading tag="451" subfields="avxyz" subdivisions="vxyz">
402
    <kohaidx:target_index>Match:w</kohaidx:target_index>
403
    <kohaidx:target_index>Match:p</kohaidx:target_index>
352
    <kohaidx:target_index>Match-heading-see-from:p</kohaidx:target_index>
404
    <kohaidx:target_index>Match-heading-see-from:p</kohaidx:target_index>
353
    <kohaidx:target_index>Match-heading-see-from:s</kohaidx:target_index>
405
    <kohaidx:target_index>Match-heading-see-from:s</kohaidx:target_index>
354
  </kohaidx:index_match_heading>
406
  </kohaidx:index_match_heading>
Lines 361-366 authority-zebra-indexdefs.xsl` Link Here
361
    <kohaidx:target_index>See-also-from:p</kohaidx:target_index>
413
    <kohaidx:target_index>See-also-from:p</kohaidx:target_index>
362
    <kohaidx:target_index>See-also-from:s</kohaidx:target_index>
414
    <kohaidx:target_index>See-also-from:s</kohaidx:target_index>
363
  </kohaidx:index_heading>
415
  </kohaidx:index_heading>
416
  <kohaidx:index_match_heading tag="551" subfields="avxyz" subdivisions="vxyz">
417
    <kohaidx:target_index>Match:w</kohaidx:target_index>
418
    <kohaidx:target_index>Match:p</kohaidx:target_index>
419
  </kohaidx:index_match_heading>
364
  
420
  
365
  <!-- Genre/form term -->
421
  <!-- Genre/form term -->
366
  <kohaidx:index_subfields tag="155" subfields="avxyz">
422
  <kohaidx:index_subfields tag="155" subfields="avxyz">
Lines 381-386 authority-zebra-indexdefs.xsl` Link Here
381
    <kohaidx:target_index>Heading-Main:s</kohaidx:target_index>
437
    <kohaidx:target_index>Heading-Main:s</kohaidx:target_index>
382
  </kohaidx:index_heading>
438
  </kohaidx:index_heading>
383
  <kohaidx:index_match_heading tag="155" subfields="avxyz" subdivisions="vxyz">
439
  <kohaidx:index_match_heading tag="155" subfields="avxyz" subdivisions="vxyz">
440
    <kohaidx:target_index>Match:w</kohaidx:target_index>
441
    <kohaidx:target_index>Match:p</kohaidx:target_index>
384
    <kohaidx:target_index>Match-heading:p</kohaidx:target_index>
442
    <kohaidx:target_index>Match-heading:p</kohaidx:target_index>
385
    <kohaidx:target_index>Match-heading:s</kohaidx:target_index>
443
    <kohaidx:target_index>Match-heading:s</kohaidx:target_index>
386
  </kohaidx:index_match_heading>
444
  </kohaidx:index_match_heading>
Lines 394-399 authority-zebra-indexdefs.xsl` Link Here
394
    <kohaidx:target_index>See-from:s</kohaidx:target_index>
452
    <kohaidx:target_index>See-from:s</kohaidx:target_index>
395
  </kohaidx:index_heading>
453
  </kohaidx:index_heading>
396
  <kohaidx:index_match_heading tag="455" subfields="avxyz" subdivisions="vxyz">
454
  <kohaidx:index_match_heading tag="455" subfields="avxyz" subdivisions="vxyz">
455
    <kohaidx:target_index>Match:w</kohaidx:target_index>
456
    <kohaidx:target_index>Match:p</kohaidx:target_index>
397
    <kohaidx:target_index>Match-heading-see-from:p</kohaidx:target_index>
457
    <kohaidx:target_index>Match-heading-see-from:p</kohaidx:target_index>
398
    <kohaidx:target_index>Match-heading-see-from:s</kohaidx:target_index>
458
    <kohaidx:target_index>Match-heading-see-from:s</kohaidx:target_index>
399
  </kohaidx:index_match_heading>
459
  </kohaidx:index_match_heading>
Lines 406-411 authority-zebra-indexdefs.xsl` Link Here
406
    <kohaidx:target_index>See-also-from:p</kohaidx:target_index>
466
    <kohaidx:target_index>See-also-from:p</kohaidx:target_index>
407
    <kohaidx:target_index>See-also-from:s</kohaidx:target_index>
467
    <kohaidx:target_index>See-also-from:s</kohaidx:target_index>
408
  </kohaidx:index_heading>
468
  </kohaidx:index_heading>
469
  <kohaidx:index_match_heading tag="555" subfields="avxyz" subdivisions="vxyz">
470
    <kohaidx:target_index>Match:w</kohaidx:target_index>
471
    <kohaidx:target_index>Match:p</kohaidx:target_index>
472
  </kohaidx:index_match_heading>
409
  
473
  
410
  <!-- General subdivision -->
474
  <!-- General subdivision -->
411
  <kohaidx:index_heading tag="180" subfields="vxyz" subdivisions="vxyz">
475
  <kohaidx:index_heading tag="180" subfields="vxyz" subdivisions="vxyz">
(-)a/etc/zebradb/marc_defs/marc21/authorities/authority-zebra-indexdefs.xsl (-56 / +481 lines)
Lines 1101-1110 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1101
    </z:index>
1101
    </z:index>
1102
  </xslo:template>
1102
  </xslo:template>
1103
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='100']">
1103
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='100']">
1104
    <z:index name="Match-heading:p Match-heading:s">
1104
    <z:index name="Match:w Match:p Match-heading:p Match-heading:s">
1105
      <xslo:variable name="raw_heading">
1105
      <xslo:variable name="raw_heading">
1106
        <xslo:for-each select="marc:subfield">
1106
        <xslo:for-each select="marc:subfield">
1107
          <xslo:if test="contains('abcdefghjklmnopqrstvxyz', @code)" name="Match-heading:p Match-heading:s">
1107
          <xslo:if test="contains('abcdefghjklmnopqrstvxyz', @code)" name="Match:w Match:p Match-heading:p Match-heading:s">
1108
            <xslo:if test="position() &gt; 1">
1108
            <xslo:if test="position() &gt; 1">
1109
              <xslo:choose>
1109
              <xslo:choose>
1110
                <xslo:when test="contains('vxyz', @code)">
1110
                <xslo:when test="contains('vxyz', @code)">
Lines 1128-1134 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1128
                </xslo:otherwise>
1128
                </xslo:otherwise>
1129
              </xslo:choose>
1129
              </xslo:choose>
1130
            </xslo:if>
1130
            </xslo:if>
1131
            <xslo:value-of select="."/>
1131
            <xslo:call-template name="chopPunctuation">
1132
              <xslo:with-param name="chopString">
1133
                <xslo:value-of select="."/>
1134
              </xslo:with-param>
1135
            </xslo:call-template>
1132
          </xslo:if>
1136
          </xslo:if>
1133
        </xslo:for-each>
1137
        </xslo:for-each>
1134
      </xslo:variable>
1138
      </xslo:variable>
Lines 1136-1145 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1136
    </z:index>
1140
    </z:index>
1137
  </xslo:template>
1141
  </xslo:template>
1138
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='400']">
1142
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='400']">
1139
    <z:index name="Match-heading-see-from:p Match-heading-see-from:s">
1143
    <z:index name="Match:w Match:p Match-heading-see-from:p Match-heading-see-from:s">
1140
      <xslo:variable name="raw_heading">
1144
      <xslo:variable name="raw_heading">
1141
        <xslo:for-each select="marc:subfield">
1145
        <xslo:for-each select="marc:subfield">
1142
          <xslo:if test="contains('abcdefghjklmnopqrstvxyz', @code)" name="Match-heading-see-from:p Match-heading-see-from:s">
1146
          <xslo:if test="contains('abcdefghjklmnopqrstvxyz', @code)" name="Match:w Match:p Match-heading-see-from:p Match-heading-see-from:s">
1143
            <xslo:if test="position() &gt; 1">
1147
            <xslo:if test="position() &gt; 1">
1144
              <xslo:choose>
1148
              <xslo:choose>
1145
                <xslo:when test="contains('vxyz', @code)">
1149
                <xslo:when test="contains('vxyz', @code)">
Lines 1163-1169 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1163
                </xslo:otherwise>
1167
                </xslo:otherwise>
1164
              </xslo:choose>
1168
              </xslo:choose>
1165
            </xslo:if>
1169
            </xslo:if>
1166
            <xslo:value-of select="."/>
1170
            <xslo:call-template name="chopPunctuation">
1171
              <xslo:with-param name="chopString">
1172
                <xslo:value-of select="."/>
1173
              </xslo:with-param>
1174
            </xslo:call-template>
1175
          </xslo:if>
1176
        </xslo:for-each>
1177
      </xslo:variable>
1178
      <xslo:value-of select="normalize-space($raw_heading)"/>
1179
    </z:index>
1180
  </xslo:template>
1181
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='500']">
1182
    <z:index name="Match:w Match:p">
1183
      <xslo:variable name="raw_heading">
1184
        <xslo:for-each select="marc:subfield">
1185
          <xslo:if test="contains('abcdefghjklmnopqrstvxyz', @code)" name="Match:w Match:p">
1186
            <xslo:if test="position() &gt; 1">
1187
              <xslo:choose>
1188
                <xslo:when test="contains('vxyz', @code)">
1189
                  <xslo:choose>
1190
                    <xslo:when test="@code = $general_subdivision_subfield">
1191
                      <xslo:text> generalsubdiv </xslo:text>
1192
                    </xslo:when>
1193
                    <xslo:when test="@code = $form_subdivision_subfield">
1194
                      <xslo:text> formsubdiv </xslo:text>
1195
                    </xslo:when>
1196
                    <xslo:when test="@code = $chronological_subdivision_subfield">
1197
                      <xslo:text> chronologicalsubdiv </xslo:text>
1198
                    </xslo:when>
1199
                    <xslo:when test="@code = $geographic_subdivision_subfield">
1200
                      <xslo:text> geographicsubdiv </xslo:text>
1201
                    </xslo:when>
1202
                  </xslo:choose>
1203
                </xslo:when>
1204
                <xslo:otherwise>
1205
                  <xslo:value-of select="substring(' ', 1, 1)"/>
1206
                </xslo:otherwise>
1207
              </xslo:choose>
1208
            </xslo:if>
1209
            <xslo:call-template name="chopPunctuation">
1210
              <xslo:with-param name="chopString">
1211
                <xslo:value-of select="."/>
1212
              </xslo:with-param>
1213
            </xslo:call-template>
1167
          </xslo:if>
1214
          </xslo:if>
1168
        </xslo:for-each>
1215
        </xslo:for-each>
1169
      </xslo:variable>
1216
      </xslo:variable>
Lines 1171-1180 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1171
    </z:index>
1218
    </z:index>
1172
  </xslo:template>
1219
  </xslo:template>
1173
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='110']">
1220
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='110']">
1174
    <z:index name="Match-heading:p Match-heading:s">
1221
    <z:index name="Match:w Match:p Match-heading:p Match-heading:s">
1175
      <xslo:variable name="raw_heading">
1222
      <xslo:variable name="raw_heading">
1176
        <xslo:for-each select="marc:subfield">
1223
        <xslo:for-each select="marc:subfield">
1177
          <xslo:if test="contains('abcdefghklmnoprstvxyz', @code)" name="Match-heading:p Match-heading:s">
1224
          <xslo:if test="contains('abcdefghklmnoprstvxyz', @code)" name="Match:w Match:p Match-heading:p Match-heading:s">
1178
            <xslo:if test="position() &gt; 1">
1225
            <xslo:if test="position() &gt; 1">
1179
              <xslo:choose>
1226
              <xslo:choose>
1180
                <xslo:when test="contains('vxyz', @code)">
1227
                <xslo:when test="contains('vxyz', @code)">
Lines 1198-1204 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1198
                </xslo:otherwise>
1245
                </xslo:otherwise>
1199
              </xslo:choose>
1246
              </xslo:choose>
1200
            </xslo:if>
1247
            </xslo:if>
1201
            <xslo:value-of select="."/>
1248
            <xslo:call-template name="chopPunctuation">
1249
              <xslo:with-param name="chopString">
1250
                <xslo:value-of select="."/>
1251
              </xslo:with-param>
1252
            </xslo:call-template>
1202
          </xslo:if>
1253
          </xslo:if>
1203
        </xslo:for-each>
1254
        </xslo:for-each>
1204
      </xslo:variable>
1255
      </xslo:variable>
Lines 1206-1215 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1206
    </z:index>
1257
    </z:index>
1207
  </xslo:template>
1258
  </xslo:template>
1208
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='410']">
1259
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='410']">
1209
    <z:index name="Match-heading-see-from:p Match-heading-see-from:s">
1260
    <z:index name="Match:w Match:p Match-heading-see-from:p Match-heading-see-from:s">
1210
      <xslo:variable name="raw_heading">
1261
      <xslo:variable name="raw_heading">
1211
        <xslo:for-each select="marc:subfield">
1262
        <xslo:for-each select="marc:subfield">
1212
          <xslo:if test="contains('abcdefghklmnoprstvxyz', @code)" name="Match-heading-see-from:p Match-heading-see-from:s">
1263
          <xslo:if test="contains('abcdefghklmnoprstvxyz', @code)" name="Match:w Match:p Match-heading-see-from:p Match-heading-see-from:s">
1213
            <xslo:if test="position() &gt; 1">
1264
            <xslo:if test="position() &gt; 1">
1214
              <xslo:choose>
1265
              <xslo:choose>
1215
                <xslo:when test="contains('vxyz', @code)">
1266
                <xslo:when test="contains('vxyz', @code)">
Lines 1233-1239 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1233
                </xslo:otherwise>
1284
                </xslo:otherwise>
1234
              </xslo:choose>
1285
              </xslo:choose>
1235
            </xslo:if>
1286
            </xslo:if>
1236
            <xslo:value-of select="."/>
1287
            <xslo:call-template name="chopPunctuation">
1288
              <xslo:with-param name="chopString">
1289
                <xslo:value-of select="."/>
1290
              </xslo:with-param>
1291
            </xslo:call-template>
1292
          </xslo:if>
1293
        </xslo:for-each>
1294
      </xslo:variable>
1295
      <xslo:value-of select="normalize-space($raw_heading)"/>
1296
    </z:index>
1297
  </xslo:template>
1298
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='510']">
1299
    <z:index name="Match:w Match:p">
1300
      <xslo:variable name="raw_heading">
1301
        <xslo:for-each select="marc:subfield">
1302
          <xslo:if test="contains('abcdefghklmnoprstvxyz', @code)" name="Match:w Match:p">
1303
            <xslo:if test="position() &gt; 1">
1304
              <xslo:choose>
1305
                <xslo:when test="contains('vxyz', @code)">
1306
                  <xslo:choose>
1307
                    <xslo:when test="@code = $general_subdivision_subfield">
1308
                      <xslo:text> generalsubdiv </xslo:text>
1309
                    </xslo:when>
1310
                    <xslo:when test="@code = $form_subdivision_subfield">
1311
                      <xslo:text> formsubdiv </xslo:text>
1312
                    </xslo:when>
1313
                    <xslo:when test="@code = $chronological_subdivision_subfield">
1314
                      <xslo:text> chronologicalsubdiv </xslo:text>
1315
                    </xslo:when>
1316
                    <xslo:when test="@code = $geographic_subdivision_subfield">
1317
                      <xslo:text> geographicsubdiv </xslo:text>
1318
                    </xslo:when>
1319
                  </xslo:choose>
1320
                </xslo:when>
1321
                <xslo:otherwise>
1322
                  <xslo:value-of select="substring(' ', 1, 1)"/>
1323
                </xslo:otherwise>
1324
              </xslo:choose>
1325
            </xslo:if>
1326
            <xslo:call-template name="chopPunctuation">
1327
              <xslo:with-param name="chopString">
1328
                <xslo:value-of select="."/>
1329
              </xslo:with-param>
1330
            </xslo:call-template>
1237
          </xslo:if>
1331
          </xslo:if>
1238
        </xslo:for-each>
1332
        </xslo:for-each>
1239
      </xslo:variable>
1333
      </xslo:variable>
Lines 1241-1250 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1241
    </z:index>
1335
    </z:index>
1242
  </xslo:template>
1336
  </xslo:template>
1243
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='111']">
1337
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='111']">
1244
    <z:index name="Match-heading:p Match-heading:s">
1338
    <z:index name="Match:w Match:p Match-heading:p Match-heading:s">
1245
      <xslo:variable name="raw_heading">
1339
      <xslo:variable name="raw_heading">
1246
        <xslo:for-each select="marc:subfield">
1340
        <xslo:for-each select="marc:subfield">
1247
          <xslo:if test="contains('acdefghjklnpqstvxyz', @code)" name="Match-heading:p Match-heading:s">
1341
          <xslo:if test="contains('acdefghjklnpqstvxyz', @code)" name="Match:w Match:p Match-heading:p Match-heading:s">
1248
            <xslo:if test="position() &gt; 1">
1342
            <xslo:if test="position() &gt; 1">
1249
              <xslo:choose>
1343
              <xslo:choose>
1250
                <xslo:when test="contains('vxyz', @code)">
1344
                <xslo:when test="contains('vxyz', @code)">
Lines 1268-1274 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1268
                </xslo:otherwise>
1362
                </xslo:otherwise>
1269
              </xslo:choose>
1363
              </xslo:choose>
1270
            </xslo:if>
1364
            </xslo:if>
1271
            <xslo:value-of select="."/>
1365
            <xslo:call-template name="chopPunctuation">
1366
              <xslo:with-param name="chopString">
1367
                <xslo:value-of select="."/>
1368
              </xslo:with-param>
1369
            </xslo:call-template>
1272
          </xslo:if>
1370
          </xslo:if>
1273
        </xslo:for-each>
1371
        </xslo:for-each>
1274
      </xslo:variable>
1372
      </xslo:variable>
Lines 1276-1285 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1276
    </z:index>
1374
    </z:index>
1277
  </xslo:template>
1375
  </xslo:template>
1278
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='411']">
1376
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='411']">
1279
    <z:index name="Match-heading-see-from:p Match-heading-see-from:s">
1377
    <z:index name="Match:w Match:p Match-heading-see-from:p Match-heading-see-from:s">
1280
      <xslo:variable name="raw_heading">
1378
      <xslo:variable name="raw_heading">
1281
        <xslo:for-each select="marc:subfield">
1379
        <xslo:for-each select="marc:subfield">
1282
          <xslo:if test="contains('acdefghjklnpqstvxyz', @code)" name="Match-heading-see-from:p Match-heading-see-from:s">
1380
          <xslo:if test="contains('acdefghjklnpqstvxyz', @code)" name="Match:w Match:p Match-heading-see-from:p Match-heading-see-from:s">
1283
            <xslo:if test="position() &gt; 1">
1381
            <xslo:if test="position() &gt; 1">
1284
              <xslo:choose>
1382
              <xslo:choose>
1285
                <xslo:when test="contains('vxyz', @code)">
1383
                <xslo:when test="contains('vxyz', @code)">
Lines 1303-1309 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1303
                </xslo:otherwise>
1401
                </xslo:otherwise>
1304
              </xslo:choose>
1402
              </xslo:choose>
1305
            </xslo:if>
1403
            </xslo:if>
1306
            <xslo:value-of select="."/>
1404
            <xslo:call-template name="chopPunctuation">
1405
              <xslo:with-param name="chopString">
1406
                <xslo:value-of select="."/>
1407
              </xslo:with-param>
1408
            </xslo:call-template>
1409
          </xslo:if>
1410
        </xslo:for-each>
1411
      </xslo:variable>
1412
      <xslo:value-of select="normalize-space($raw_heading)"/>
1413
    </z:index>
1414
  </xslo:template>
1415
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='511']">
1416
    <z:index name="Match:w Match:p">
1417
      <xslo:variable name="raw_heading">
1418
        <xslo:for-each select="marc:subfield">
1419
          <xslo:if test="contains('acdefghjklnpqstvxyz', @code)" name="Match:w Match:p">
1420
            <xslo:if test="position() &gt; 1">
1421
              <xslo:choose>
1422
                <xslo:when test="contains('vxyz', @code)">
1423
                  <xslo:choose>
1424
                    <xslo:when test="@code = $general_subdivision_subfield">
1425
                      <xslo:text> generalsubdiv </xslo:text>
1426
                    </xslo:when>
1427
                    <xslo:when test="@code = $form_subdivision_subfield">
1428
                      <xslo:text> formsubdiv </xslo:text>
1429
                    </xslo:when>
1430
                    <xslo:when test="@code = $chronological_subdivision_subfield">
1431
                      <xslo:text> chronologicalsubdiv </xslo:text>
1432
                    </xslo:when>
1433
                    <xslo:when test="@code = $geographic_subdivision_subfield">
1434
                      <xslo:text> geographicsubdiv </xslo:text>
1435
                    </xslo:when>
1436
                  </xslo:choose>
1437
                </xslo:when>
1438
                <xslo:otherwise>
1439
                  <xslo:value-of select="substring(' ', 1, 1)"/>
1440
                </xslo:otherwise>
1441
              </xslo:choose>
1442
            </xslo:if>
1443
            <xslo:call-template name="chopPunctuation">
1444
              <xslo:with-param name="chopString">
1445
                <xslo:value-of select="."/>
1446
              </xslo:with-param>
1447
            </xslo:call-template>
1307
          </xslo:if>
1448
          </xslo:if>
1308
        </xslo:for-each>
1449
        </xslo:for-each>
1309
      </xslo:variable>
1450
      </xslo:variable>
Lines 1311-1320 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1311
    </z:index>
1452
    </z:index>
1312
  </xslo:template>
1453
  </xslo:template>
1313
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='130']">
1454
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='130']">
1314
    <z:index name="Match-heading:p Match-heading:s">
1455
    <z:index name="Match:w Match:p Match-heading:p Match-heading:s">
1315
      <xslo:variable name="raw_heading">
1456
      <xslo:variable name="raw_heading">
1316
        <xslo:for-each select="marc:subfield">
1457
        <xslo:for-each select="marc:subfield">
1317
          <xslo:if test="contains('adfghklmnoprstvxyz', @code)" name="Match-heading:p Match-heading:s">
1458
          <xslo:if test="contains('adfghklmnoprstvxyz', @code)" name="Match:w Match:p Match-heading:p Match-heading:s">
1318
            <xslo:if test="position() &gt; 1">
1459
            <xslo:if test="position() &gt; 1">
1319
              <xslo:choose>
1460
              <xslo:choose>
1320
                <xslo:when test="contains('vxyz', @code)">
1461
                <xslo:when test="contains('vxyz', @code)">
Lines 1338-1344 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1338
                </xslo:otherwise>
1479
                </xslo:otherwise>
1339
              </xslo:choose>
1480
              </xslo:choose>
1340
            </xslo:if>
1481
            </xslo:if>
1341
            <xslo:value-of select="."/>
1482
            <xslo:call-template name="chopPunctuation">
1483
              <xslo:with-param name="chopString">
1484
                <xslo:value-of select="."/>
1485
              </xslo:with-param>
1486
            </xslo:call-template>
1342
          </xslo:if>
1487
          </xslo:if>
1343
        </xslo:for-each>
1488
        </xslo:for-each>
1344
      </xslo:variable>
1489
      </xslo:variable>
Lines 1346-1355 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1346
    </z:index>
1491
    </z:index>
1347
  </xslo:template>
1492
  </xslo:template>
1348
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='430']">
1493
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='430']">
1349
    <z:index name="Match-heading-see-from:p Match-heading-see-from:s">
1494
    <z:index name="Match:w Match:p Match-heading-see-from:p Match-heading-see-from:s">
1350
      <xslo:variable name="raw_heading">
1495
      <xslo:variable name="raw_heading">
1351
        <xslo:for-each select="marc:subfield">
1496
        <xslo:for-each select="marc:subfield">
1352
          <xslo:if test="contains('adfghklmnoprstvxyz', @code)" name="Match-heading-see-from:p Match-heading-see-from:s">
1497
          <xslo:if test="contains('adfghklmnoprstvxyz', @code)" name="Match:w Match:p Match-heading-see-from:p Match-heading-see-from:s">
1353
            <xslo:if test="position() &gt; 1">
1498
            <xslo:if test="position() &gt; 1">
1354
              <xslo:choose>
1499
              <xslo:choose>
1355
                <xslo:when test="contains('vxyz', @code)">
1500
                <xslo:when test="contains('vxyz', @code)">
Lines 1373-1379 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1373
                </xslo:otherwise>
1518
                </xslo:otherwise>
1374
              </xslo:choose>
1519
              </xslo:choose>
1375
            </xslo:if>
1520
            </xslo:if>
1376
            <xslo:value-of select="."/>
1521
            <xslo:call-template name="chopPunctuation">
1522
              <xslo:with-param name="chopString">
1523
                <xslo:value-of select="."/>
1524
              </xslo:with-param>
1525
            </xslo:call-template>
1526
          </xslo:if>
1527
        </xslo:for-each>
1528
      </xslo:variable>
1529
      <xslo:value-of select="normalize-space($raw_heading)"/>
1530
    </z:index>
1531
  </xslo:template>
1532
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='530']">
1533
    <z:index name="Match:w Match:p">
1534
      <xslo:variable name="raw_heading">
1535
        <xslo:for-each select="marc:subfield">
1536
          <xslo:if test="contains('adfghklmnoprstvxyz', @code)" name="Match:w Match:p">
1537
            <xslo:if test="position() &gt; 1">
1538
              <xslo:choose>
1539
                <xslo:when test="contains('vxyz', @code)">
1540
                  <xslo:choose>
1541
                    <xslo:when test="@code = $general_subdivision_subfield">
1542
                      <xslo:text> generalsubdiv </xslo:text>
1543
                    </xslo:when>
1544
                    <xslo:when test="@code = $form_subdivision_subfield">
1545
                      <xslo:text> formsubdiv </xslo:text>
1546
                    </xslo:when>
1547
                    <xslo:when test="@code = $chronological_subdivision_subfield">
1548
                      <xslo:text> chronologicalsubdiv </xslo:text>
1549
                    </xslo:when>
1550
                    <xslo:when test="@code = $geographic_subdivision_subfield">
1551
                      <xslo:text> geographicsubdiv </xslo:text>
1552
                    </xslo:when>
1553
                  </xslo:choose>
1554
                </xslo:when>
1555
                <xslo:otherwise>
1556
                  <xslo:value-of select="substring(' ', 1, 1)"/>
1557
                </xslo:otherwise>
1558
              </xslo:choose>
1559
            </xslo:if>
1560
            <xslo:call-template name="chopPunctuation">
1561
              <xslo:with-param name="chopString">
1562
                <xslo:value-of select="."/>
1563
              </xslo:with-param>
1564
            </xslo:call-template>
1377
          </xslo:if>
1565
          </xslo:if>
1378
        </xslo:for-each>
1566
        </xslo:for-each>
1379
      </xslo:variable>
1567
      </xslo:variable>
Lines 1381-1390 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1381
    </z:index>
1569
    </z:index>
1382
  </xslo:template>
1570
  </xslo:template>
1383
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='148']">
1571
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='148']">
1384
    <z:index name="Match-heading:p Match-heading:s">
1572
    <z:index name="Match:w Match:p Match-heading:p Match-heading:s">
1385
      <xslo:variable name="raw_heading">
1573
      <xslo:variable name="raw_heading">
1386
        <xslo:for-each select="marc:subfield">
1574
        <xslo:for-each select="marc:subfield">
1387
          <xslo:if test="contains('avxyz', @code)" name="Match-heading:p Match-heading:s">
1575
          <xslo:if test="contains('avxyz', @code)" name="Match:w Match:p Match-heading:p Match-heading:s">
1388
            <xslo:if test="position() &gt; 1">
1576
            <xslo:if test="position() &gt; 1">
1389
              <xslo:choose>
1577
              <xslo:choose>
1390
                <xslo:when test="contains('vxyz', @code)">
1578
                <xslo:when test="contains('vxyz', @code)">
Lines 1408-1414 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1408
                </xslo:otherwise>
1596
                </xslo:otherwise>
1409
              </xslo:choose>
1597
              </xslo:choose>
1410
            </xslo:if>
1598
            </xslo:if>
1411
            <xslo:value-of select="."/>
1599
            <xslo:call-template name="chopPunctuation">
1600
              <xslo:with-param name="chopString">
1601
                <xslo:value-of select="."/>
1602
              </xslo:with-param>
1603
            </xslo:call-template>
1412
          </xslo:if>
1604
          </xslo:if>
1413
        </xslo:for-each>
1605
        </xslo:for-each>
1414
      </xslo:variable>
1606
      </xslo:variable>
Lines 1416-1425 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1416
    </z:index>
1608
    </z:index>
1417
  </xslo:template>
1609
  </xslo:template>
1418
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='448']">
1610
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='448']">
1419
    <z:index name="Match-heading-see-from:p Match-heading-see-from:s">
1611
    <z:index name="Match:w Match:p Match-heading-see-from:p Match-heading-see-from:s">
1420
      <xslo:variable name="raw_heading">
1612
      <xslo:variable name="raw_heading">
1421
        <xslo:for-each select="marc:subfield">
1613
        <xslo:for-each select="marc:subfield">
1422
          <xslo:if test="contains('avxyz', @code)" name="Match-heading-see-from:p Match-heading-see-from:s">
1614
          <xslo:if test="contains('avxyz', @code)" name="Match:w Match:p Match-heading-see-from:p Match-heading-see-from:s">
1423
            <xslo:if test="position() &gt; 1">
1615
            <xslo:if test="position() &gt; 1">
1424
              <xslo:choose>
1616
              <xslo:choose>
1425
                <xslo:when test="contains('vxyz', @code)">
1617
                <xslo:when test="contains('vxyz', @code)">
Lines 1443-1449 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1443
                </xslo:otherwise>
1635
                </xslo:otherwise>
1444
              </xslo:choose>
1636
              </xslo:choose>
1445
            </xslo:if>
1637
            </xslo:if>
1446
            <xslo:value-of select="."/>
1638
            <xslo:call-template name="chopPunctuation">
1639
              <xslo:with-param name="chopString">
1640
                <xslo:value-of select="."/>
1641
              </xslo:with-param>
1642
            </xslo:call-template>
1643
          </xslo:if>
1644
        </xslo:for-each>
1645
      </xslo:variable>
1646
      <xslo:value-of select="normalize-space($raw_heading)"/>
1647
    </z:index>
1648
  </xslo:template>
1649
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='548']">
1650
    <z:index name="Match:w Match:p">
1651
      <xslo:variable name="raw_heading">
1652
        <xslo:for-each select="marc:subfield">
1653
          <xslo:if test="contains('avxyz', @code)" name="Match:w Match:p">
1654
            <xslo:if test="position() &gt; 1">
1655
              <xslo:choose>
1656
                <xslo:when test="contains('vxyz', @code)">
1657
                  <xslo:choose>
1658
                    <xslo:when test="@code = $general_subdivision_subfield">
1659
                      <xslo:text> generalsubdiv </xslo:text>
1660
                    </xslo:when>
1661
                    <xslo:when test="@code = $form_subdivision_subfield">
1662
                      <xslo:text> formsubdiv </xslo:text>
1663
                    </xslo:when>
1664
                    <xslo:when test="@code = $chronological_subdivision_subfield">
1665
                      <xslo:text> chronologicalsubdiv </xslo:text>
1666
                    </xslo:when>
1667
                    <xslo:when test="@code = $geographic_subdivision_subfield">
1668
                      <xslo:text> geographicsubdiv </xslo:text>
1669
                    </xslo:when>
1670
                  </xslo:choose>
1671
                </xslo:when>
1672
                <xslo:otherwise>
1673
                  <xslo:value-of select="substring(' ', 1, 1)"/>
1674
                </xslo:otherwise>
1675
              </xslo:choose>
1676
            </xslo:if>
1677
            <xslo:call-template name="chopPunctuation">
1678
              <xslo:with-param name="chopString">
1679
                <xslo:value-of select="."/>
1680
              </xslo:with-param>
1681
            </xslo:call-template>
1447
          </xslo:if>
1682
          </xslo:if>
1448
        </xslo:for-each>
1683
        </xslo:for-each>
1449
      </xslo:variable>
1684
      </xslo:variable>
Lines 1451-1460 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1451
    </z:index>
1686
    </z:index>
1452
  </xslo:template>
1687
  </xslo:template>
1453
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='150']">
1688
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='150']">
1454
    <z:index name="Match-heading:p Match-heading:s">
1689
    <z:index name="Match:w Match:p Match-heading:p Match-heading:s">
1455
      <xslo:variable name="raw_heading">
1690
      <xslo:variable name="raw_heading">
1456
        <xslo:for-each select="marc:subfield">
1691
        <xslo:for-each select="marc:subfield">
1457
          <xslo:if test="contains('abvxyz', @code)" name="Match-heading:p Match-heading:s">
1692
          <xslo:if test="contains('abvxyz', @code)" name="Match:w Match:p Match-heading:p Match-heading:s">
1458
            <xslo:if test="position() &gt; 1">
1693
            <xslo:if test="position() &gt; 1">
1459
              <xslo:choose>
1694
              <xslo:choose>
1460
                <xslo:when test="contains('vxyz', @code)">
1695
                <xslo:when test="contains('vxyz', @code)">
Lines 1478-1484 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1478
                </xslo:otherwise>
1713
                </xslo:otherwise>
1479
              </xslo:choose>
1714
              </xslo:choose>
1480
            </xslo:if>
1715
            </xslo:if>
1481
            <xslo:value-of select="."/>
1716
            <xslo:call-template name="chopPunctuation">
1717
              <xslo:with-param name="chopString">
1718
                <xslo:value-of select="."/>
1719
              </xslo:with-param>
1720
            </xslo:call-template>
1482
          </xslo:if>
1721
          </xslo:if>
1483
        </xslo:for-each>
1722
        </xslo:for-each>
1484
      </xslo:variable>
1723
      </xslo:variable>
Lines 1486-1495 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1486
    </z:index>
1725
    </z:index>
1487
  </xslo:template>
1726
  </xslo:template>
1488
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='450']">
1727
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='450']">
1489
    <z:index name="Match-heading-see-from:p Match-heading-see-from:s">
1728
    <z:index name="Match:w Match:p Match-heading-see-from:p Match-heading-see-from:s">
1490
      <xslo:variable name="raw_heading">
1729
      <xslo:variable name="raw_heading">
1491
        <xslo:for-each select="marc:subfield">
1730
        <xslo:for-each select="marc:subfield">
1492
          <xslo:if test="contains('abvxyz', @code)" name="Match-heading-see-from:p Match-heading-see-from:s">
1731
          <xslo:if test="contains('abvxyz', @code)" name="Match:w Match:p Match-heading-see-from:p Match-heading-see-from:s">
1493
            <xslo:if test="position() &gt; 1">
1732
            <xslo:if test="position() &gt; 1">
1494
              <xslo:choose>
1733
              <xslo:choose>
1495
                <xslo:when test="contains('vxyz', @code)">
1734
                <xslo:when test="contains('vxyz', @code)">
Lines 1513-1519 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1513
                </xslo:otherwise>
1752
                </xslo:otherwise>
1514
              </xslo:choose>
1753
              </xslo:choose>
1515
            </xslo:if>
1754
            </xslo:if>
1516
            <xslo:value-of select="."/>
1755
            <xslo:call-template name="chopPunctuation">
1756
              <xslo:with-param name="chopString">
1757
                <xslo:value-of select="."/>
1758
              </xslo:with-param>
1759
            </xslo:call-template>
1760
          </xslo:if>
1761
        </xslo:for-each>
1762
      </xslo:variable>
1763
      <xslo:value-of select="normalize-space($raw_heading)"/>
1764
    </z:index>
1765
  </xslo:template>
1766
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='550']">
1767
    <z:index name="Match:w Match:p">
1768
      <xslo:variable name="raw_heading">
1769
        <xslo:for-each select="marc:subfield">
1770
          <xslo:if test="contains('abvxyz', @code)" name="Match:w Match:p">
1771
            <xslo:if test="position() &gt; 1">
1772
              <xslo:choose>
1773
                <xslo:when test="contains('vxyz', @code)">
1774
                  <xslo:choose>
1775
                    <xslo:when test="@code = $general_subdivision_subfield">
1776
                      <xslo:text> generalsubdiv </xslo:text>
1777
                    </xslo:when>
1778
                    <xslo:when test="@code = $form_subdivision_subfield">
1779
                      <xslo:text> formsubdiv </xslo:text>
1780
                    </xslo:when>
1781
                    <xslo:when test="@code = $chronological_subdivision_subfield">
1782
                      <xslo:text> chronologicalsubdiv </xslo:text>
1783
                    </xslo:when>
1784
                    <xslo:when test="@code = $geographic_subdivision_subfield">
1785
                      <xslo:text> geographicsubdiv </xslo:text>
1786
                    </xslo:when>
1787
                  </xslo:choose>
1788
                </xslo:when>
1789
                <xslo:otherwise>
1790
                  <xslo:value-of select="substring(' ', 1, 1)"/>
1791
                </xslo:otherwise>
1792
              </xslo:choose>
1793
            </xslo:if>
1794
            <xslo:call-template name="chopPunctuation">
1795
              <xslo:with-param name="chopString">
1796
                <xslo:value-of select="."/>
1797
              </xslo:with-param>
1798
            </xslo:call-template>
1517
          </xslo:if>
1799
          </xslo:if>
1518
        </xslo:for-each>
1800
        </xslo:for-each>
1519
      </xslo:variable>
1801
      </xslo:variable>
Lines 1521-1530 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1521
    </z:index>
1803
    </z:index>
1522
  </xslo:template>
1804
  </xslo:template>
1523
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='151']">
1805
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='151']">
1524
    <z:index name="Match-heading:p Match-heading:s">
1806
    <z:index name="Match:w Match:p Match-heading:p Match-heading:s">
1525
      <xslo:variable name="raw_heading">
1807
      <xslo:variable name="raw_heading">
1526
        <xslo:for-each select="marc:subfield">
1808
        <xslo:for-each select="marc:subfield">
1527
          <xslo:if test="contains('avxyz', @code)" name="Match-heading:p Match-heading:s">
1809
          <xslo:if test="contains('avxyz', @code)" name="Match:w Match:p Match-heading:p Match-heading:s">
1528
            <xslo:if test="position() &gt; 1">
1810
            <xslo:if test="position() &gt; 1">
1529
              <xslo:choose>
1811
              <xslo:choose>
1530
                <xslo:when test="contains('vxyz', @code)">
1812
                <xslo:when test="contains('vxyz', @code)">
Lines 1548-1554 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1548
                </xslo:otherwise>
1830
                </xslo:otherwise>
1549
              </xslo:choose>
1831
              </xslo:choose>
1550
            </xslo:if>
1832
            </xslo:if>
1551
            <xslo:value-of select="."/>
1833
            <xslo:call-template name="chopPunctuation">
1834
              <xslo:with-param name="chopString">
1835
                <xslo:value-of select="."/>
1836
              </xslo:with-param>
1837
            </xslo:call-template>
1552
          </xslo:if>
1838
          </xslo:if>
1553
        </xslo:for-each>
1839
        </xslo:for-each>
1554
      </xslo:variable>
1840
      </xslo:variable>
Lines 1556-1565 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1556
    </z:index>
1842
    </z:index>
1557
  </xslo:template>
1843
  </xslo:template>
1558
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='451']">
1844
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='451']">
1559
    <z:index name="Match-heading-see-from:p Match-heading-see-from:s">
1845
    <z:index name="Match:w Match:p Match-heading-see-from:p Match-heading-see-from:s">
1560
      <xslo:variable name="raw_heading">
1846
      <xslo:variable name="raw_heading">
1561
        <xslo:for-each select="marc:subfield">
1847
        <xslo:for-each select="marc:subfield">
1562
          <xslo:if test="contains('avxyz', @code)" name="Match-heading-see-from:p Match-heading-see-from:s">
1848
          <xslo:if test="contains('avxyz', @code)" name="Match:w Match:p Match-heading-see-from:p Match-heading-see-from:s">
1563
            <xslo:if test="position() &gt; 1">
1849
            <xslo:if test="position() &gt; 1">
1564
              <xslo:choose>
1850
              <xslo:choose>
1565
                <xslo:when test="contains('vxyz', @code)">
1851
                <xslo:when test="contains('vxyz', @code)">
Lines 1583-1589 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1583
                </xslo:otherwise>
1869
                </xslo:otherwise>
1584
              </xslo:choose>
1870
              </xslo:choose>
1585
            </xslo:if>
1871
            </xslo:if>
1586
            <xslo:value-of select="."/>
1872
            <xslo:call-template name="chopPunctuation">
1873
              <xslo:with-param name="chopString">
1874
                <xslo:value-of select="."/>
1875
              </xslo:with-param>
1876
            </xslo:call-template>
1877
          </xslo:if>
1878
        </xslo:for-each>
1879
      </xslo:variable>
1880
      <xslo:value-of select="normalize-space($raw_heading)"/>
1881
    </z:index>
1882
  </xslo:template>
1883
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='551']">
1884
    <z:index name="Match:w Match:p">
1885
      <xslo:variable name="raw_heading">
1886
        <xslo:for-each select="marc:subfield">
1887
          <xslo:if test="contains('avxyz', @code)" name="Match:w Match:p">
1888
            <xslo:if test="position() &gt; 1">
1889
              <xslo:choose>
1890
                <xslo:when test="contains('vxyz', @code)">
1891
                  <xslo:choose>
1892
                    <xslo:when test="@code = $general_subdivision_subfield">
1893
                      <xslo:text> generalsubdiv </xslo:text>
1894
                    </xslo:when>
1895
                    <xslo:when test="@code = $form_subdivision_subfield">
1896
                      <xslo:text> formsubdiv </xslo:text>
1897
                    </xslo:when>
1898
                    <xslo:when test="@code = $chronological_subdivision_subfield">
1899
                      <xslo:text> chronologicalsubdiv </xslo:text>
1900
                    </xslo:when>
1901
                    <xslo:when test="@code = $geographic_subdivision_subfield">
1902
                      <xslo:text> geographicsubdiv </xslo:text>
1903
                    </xslo:when>
1904
                  </xslo:choose>
1905
                </xslo:when>
1906
                <xslo:otherwise>
1907
                  <xslo:value-of select="substring(' ', 1, 1)"/>
1908
                </xslo:otherwise>
1909
              </xslo:choose>
1910
            </xslo:if>
1911
            <xslo:call-template name="chopPunctuation">
1912
              <xslo:with-param name="chopString">
1913
                <xslo:value-of select="."/>
1914
              </xslo:with-param>
1915
            </xslo:call-template>
1587
          </xslo:if>
1916
          </xslo:if>
1588
        </xslo:for-each>
1917
        </xslo:for-each>
1589
      </xslo:variable>
1918
      </xslo:variable>
Lines 1591-1600 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1591
    </z:index>
1920
    </z:index>
1592
  </xslo:template>
1921
  </xslo:template>
1593
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='155']">
1922
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='155']">
1594
    <z:index name="Match-heading:p Match-heading:s">
1923
    <z:index name="Match:w Match:p Match-heading:p Match-heading:s">
1595
      <xslo:variable name="raw_heading">
1924
      <xslo:variable name="raw_heading">
1596
        <xslo:for-each select="marc:subfield">
1925
        <xslo:for-each select="marc:subfield">
1597
          <xslo:if test="contains('avxyz', @code)" name="Match-heading:p Match-heading:s">
1926
          <xslo:if test="contains('avxyz', @code)" name="Match:w Match:p Match-heading:p Match-heading:s">
1598
            <xslo:if test="position() &gt; 1">
1927
            <xslo:if test="position() &gt; 1">
1599
              <xslo:choose>
1928
              <xslo:choose>
1600
                <xslo:when test="contains('vxyz', @code)">
1929
                <xslo:when test="contains('vxyz', @code)">
Lines 1618-1624 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1618
                </xslo:otherwise>
1947
                </xslo:otherwise>
1619
              </xslo:choose>
1948
              </xslo:choose>
1620
            </xslo:if>
1949
            </xslo:if>
1621
            <xslo:value-of select="."/>
1950
            <xslo:call-template name="chopPunctuation">
1951
              <xslo:with-param name="chopString">
1952
                <xslo:value-of select="."/>
1953
              </xslo:with-param>
1954
            </xslo:call-template>
1622
          </xslo:if>
1955
          </xslo:if>
1623
        </xslo:for-each>
1956
        </xslo:for-each>
1624
      </xslo:variable>
1957
      </xslo:variable>
Lines 1626-1635 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1626
    </z:index>
1959
    </z:index>
1627
  </xslo:template>
1960
  </xslo:template>
1628
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='455']">
1961
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='455']">
1629
    <z:index name="Match-heading-see-from:p Match-heading-see-from:s">
1962
    <z:index name="Match:w Match:p Match-heading-see-from:p Match-heading-see-from:s">
1630
      <xslo:variable name="raw_heading">
1963
      <xslo:variable name="raw_heading">
1631
        <xslo:for-each select="marc:subfield">
1964
        <xslo:for-each select="marc:subfield">
1632
          <xslo:if test="contains('avxyz', @code)" name="Match-heading-see-from:p Match-heading-see-from:s">
1965
          <xslo:if test="contains('avxyz', @code)" name="Match:w Match:p Match-heading-see-from:p Match-heading-see-from:s">
1633
            <xslo:if test="position() &gt; 1">
1966
            <xslo:if test="position() &gt; 1">
1634
              <xslo:choose>
1967
              <xslo:choose>
1635
                <xslo:when test="contains('vxyz', @code)">
1968
                <xslo:when test="contains('vxyz', @code)">
Lines 1653-1659 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1653
                </xslo:otherwise>
1986
                </xslo:otherwise>
1654
              </xslo:choose>
1987
              </xslo:choose>
1655
            </xslo:if>
1988
            </xslo:if>
1656
            <xslo:value-of select="."/>
1989
            <xslo:call-template name="chopPunctuation">
1990
              <xslo:with-param name="chopString">
1991
                <xslo:value-of select="."/>
1992
              </xslo:with-param>
1993
            </xslo:call-template>
1994
          </xslo:if>
1995
        </xslo:for-each>
1996
      </xslo:variable>
1997
      <xslo:value-of select="normalize-space($raw_heading)"/>
1998
    </z:index>
1999
  </xslo:template>
2000
  <xslo:template mode="index_match_heading" match="marc:datafield[@tag='555']">
2001
    <z:index name="Match:w Match:p">
2002
      <xslo:variable name="raw_heading">
2003
        <xslo:for-each select="marc:subfield">
2004
          <xslo:if test="contains('avxyz', @code)" name="Match:w Match:p">
2005
            <xslo:if test="position() &gt; 1">
2006
              <xslo:choose>
2007
                <xslo:when test="contains('vxyz', @code)">
2008
                  <xslo:choose>
2009
                    <xslo:when test="@code = $general_subdivision_subfield">
2010
                      <xslo:text> generalsubdiv </xslo:text>
2011
                    </xslo:when>
2012
                    <xslo:when test="@code = $form_subdivision_subfield">
2013
                      <xslo:text> formsubdiv </xslo:text>
2014
                    </xslo:when>
2015
                    <xslo:when test="@code = $chronological_subdivision_subfield">
2016
                      <xslo:text> chronologicalsubdiv </xslo:text>
2017
                    </xslo:when>
2018
                    <xslo:when test="@code = $geographic_subdivision_subfield">
2019
                      <xslo:text> geographicsubdiv </xslo:text>
2020
                    </xslo:when>
2021
                  </xslo:choose>
2022
                </xslo:when>
2023
                <xslo:otherwise>
2024
                  <xslo:value-of select="substring(' ', 1, 1)"/>
2025
                </xslo:otherwise>
2026
              </xslo:choose>
2027
            </xslo:if>
2028
            <xslo:call-template name="chopPunctuation">
2029
              <xslo:with-param name="chopString">
2030
                <xslo:value-of select="."/>
2031
              </xslo:with-param>
2032
            </xslo:call-template>
1657
          </xslo:if>
2033
          </xslo:if>
1658
        </xslo:for-each>
2034
        </xslo:for-each>
1659
      </xslo:variable>
2035
      </xslo:variable>
Lines 1688-1694 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1688
                </xslo:otherwise>
2064
                </xslo:otherwise>
1689
              </xslo:choose>
2065
              </xslo:choose>
1690
            </xslo:if>
2066
            </xslo:if>
1691
            <xslo:value-of select="."/>
2067
            <xslo:call-template name="chopPunctuation">
2068
              <xslo:with-param name="chopString">
2069
                <xslo:value-of select="."/>
2070
              </xslo:with-param>
2071
            </xslo:call-template>
1692
          </xslo:if>
2072
          </xslo:if>
1693
        </xslo:for-each>
2073
        </xslo:for-each>
1694
      </xslo:variable>
2074
      </xslo:variable>
Lines 1723-1729 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1723
                </xslo:otherwise>
2103
                </xslo:otherwise>
1724
              </xslo:choose>
2104
              </xslo:choose>
1725
            </xslo:if>
2105
            </xslo:if>
1726
            <xslo:value-of select="."/>
2106
            <xslo:call-template name="chopPunctuation">
2107
              <xslo:with-param name="chopString">
2108
                <xslo:value-of select="."/>
2109
              </xslo:with-param>
2110
            </xslo:call-template>
1727
          </xslo:if>
2111
          </xslo:if>
1728
        </xslo:for-each>
2112
        </xslo:for-each>
1729
      </xslo:variable>
2113
      </xslo:variable>
Lines 1758-1764 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1758
                </xslo:otherwise>
2142
                </xslo:otherwise>
1759
              </xslo:choose>
2143
              </xslo:choose>
1760
            </xslo:if>
2144
            </xslo:if>
1761
            <xslo:value-of select="."/>
2145
            <xslo:call-template name="chopPunctuation">
2146
              <xslo:with-param name="chopString">
2147
                <xslo:value-of select="."/>
2148
              </xslo:with-param>
2149
            </xslo:call-template>
1762
          </xslo:if>
2150
          </xslo:if>
1763
        </xslo:for-each>
2151
        </xslo:for-each>
1764
      </xslo:variable>
2152
      </xslo:variable>
Lines 1793-1799 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1793
                </xslo:otherwise>
2181
                </xslo:otherwise>
1794
              </xslo:choose>
2182
              </xslo:choose>
1795
            </xslo:if>
2183
            </xslo:if>
1796
            <xslo:value-of select="."/>
2184
            <xslo:call-template name="chopPunctuation">
2185
              <xslo:with-param name="chopString">
2186
                <xslo:value-of select="."/>
2187
              </xslo:with-param>
2188
            </xslo:call-template>
1797
          </xslo:if>
2189
          </xslo:if>
1798
        </xslo:for-each>
2190
        </xslo:for-each>
1799
      </xslo:variable>
2191
      </xslo:variable>
Lines 1828-1834 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1828
                </xslo:otherwise>
2220
                </xslo:otherwise>
1829
              </xslo:choose>
2221
              </xslo:choose>
1830
            </xslo:if>
2222
            </xslo:if>
1831
            <xslo:value-of select="."/>
2223
            <xslo:call-template name="chopPunctuation">
2224
              <xslo:with-param name="chopString">
2225
                <xslo:value-of select="."/>
2226
              </xslo:with-param>
2227
            </xslo:call-template>
1832
          </xslo:if>
2228
          </xslo:if>
1833
        </xslo:for-each>
2229
        </xslo:for-each>
1834
      </xslo:variable>
2230
      </xslo:variable>
Lines 1863-1869 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1863
                </xslo:otherwise>
2259
                </xslo:otherwise>
1864
              </xslo:choose>
2260
              </xslo:choose>
1865
            </xslo:if>
2261
            </xslo:if>
1866
            <xslo:value-of select="."/>
2262
            <xslo:call-template name="chopPunctuation">
2263
              <xslo:with-param name="chopString">
2264
                <xslo:value-of select="."/>
2265
              </xslo:with-param>
2266
            </xslo:call-template>
1867
          </xslo:if>
2267
          </xslo:if>
1868
        </xslo:for-each>
2268
        </xslo:for-each>
1869
      </xslo:variable>
2269
      </xslo:variable>
Lines 1898-1904 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1898
                </xslo:otherwise>
2298
                </xslo:otherwise>
1899
              </xslo:choose>
2299
              </xslo:choose>
1900
            </xslo:if>
2300
            </xslo:if>
1901
            <xslo:value-of select="."/>
2301
            <xslo:call-template name="chopPunctuation">
2302
              <xslo:with-param name="chopString">
2303
                <xslo:value-of select="."/>
2304
              </xslo:with-param>
2305
            </xslo:call-template>
1902
          </xslo:if>
2306
          </xslo:if>
1903
        </xslo:for-each>
2307
        </xslo:for-each>
1904
      </xslo:variable>
2308
      </xslo:variable>
Lines 1933-1939 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1933
                </xslo:otherwise>
2337
                </xslo:otherwise>
1934
              </xslo:choose>
2338
              </xslo:choose>
1935
            </xslo:if>
2339
            </xslo:if>
1936
            <xslo:value-of select="."/>
2340
            <xslo:call-template name="chopPunctuation">
2341
              <xslo:with-param name="chopString">
2342
                <xslo:value-of select="."/>
2343
              </xslo:with-param>
2344
            </xslo:call-template>
1937
          </xslo:if>
2345
          </xslo:if>
1938
        </xslo:for-each>
2346
        </xslo:for-each>
1939
      </xslo:variable>
2347
      </xslo:variable>
Lines 1999-2002 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
1999
      <xslo:value-of select="."/>
2407
      <xslo:value-of select="."/>
2000
    </z:index>
2408
    </z:index>
2001
  </xslo:template>
2409
  </xslo:template>
2410
  <xslo:template name="chopPunctuation">
2411
    <xslo:param name="chopString"/>
2412
    <xslo:variable name="length" select="string-length($chopString)"/>
2413
    <xslo:choose>
2414
      <xslo:when test="$length=0"/>
2415
      <xslo:when test="contains('-,.:=;!%/', substring($chopString,$length,1))">
2416
        <xslo:call-template name="chopPunctuation">
2417
          <xslo:with-param name="chopString" select="substring($chopString,1,$length - 1)"/>
2418
        </xslo:call-template>
2419
      </xslo:when>
2420
      <xslo:when test="not($chopString)"/>
2421
      <xslo:otherwise>
2422
        <xslo:value-of select="$chopString"/>
2423
      </xslo:otherwise>
2424
    </xslo:choose>
2425
    <xslo:text/>
2426
  </xslo:template>
2002
</xslo:stylesheet>
2427
</xslo:stylesheet>
(-)a/etc/zebradb/marc_defs/marc21/authorities/koha-indexdefs-to-zebra.xsl (-1 / +20 lines)
Lines 67-72 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
67
                    <xslo:value-of select="."/>
67
                    <xslo:value-of select="."/>
68
                </z:index>
68
                </z:index>
69
            </xslo:template>
69
            </xslo:template>
70
            <xslo:template name="chopPunctuation">
71
            <xslo:param name="chopString"/>
72
                <xslo:variable name="length" select="string-length($chopString)"/>
73
                <xslo:choose>
74
                <xslo:when test="$length=0"/>
75
                <xslo:when test="contains('-,.:=;!%/', substring($chopString,$length,1))">
76
                    <xslo:call-template name="chopPunctuation">
77
                    <xslo:with-param name="chopString" select="substring($chopString,1,$length - 1)"/>
78
                    </xslo:call-template>
79
                </xslo:when>
80
                <xslo:when test="not($chopString)"/>
81
                <xslo:otherwise><xslo:value-of select="$chopString"/></xslo:otherwise>
82
                </xslo:choose>
83
                <xslo:text> </xslo:text>
84
            </xslo:template>
70
        </xslo:stylesheet>
85
        </xslo:stylesheet>
71
    </xsl:template>
86
    </xsl:template>
72
87
Lines 368-374 authority-zebra-indexdefs.xsl` (substituting the appropriate file names). Link Here
368
                                </xslo:otherwise>
383
                                </xslo:otherwise>
369
                            </xslo:choose>
384
                            </xslo:choose>
370
                        </xslo:if>
385
                        </xslo:if>
371
                        <xslo:value-of select="."/>
386
                        <xslo:call-template name="chopPunctuation">
387
                            <xslo:with-param name="chopString">
388
                                <xslo:value-of select="."/>
389
                            </xslo:with-param>
390
                        </xslo:call-template>
372
                    </xslo:if>
391
                    </xslo:if>
373
                </xslo:for-each>
392
                </xslo:for-each>
374
            </xslo:variable>
393
            </xslo:variable>
(-)a/etc/zebradb/marc_defs/unimarc/authorities/record.abs (-60 / +60 lines)
Lines 16-104 melm 942$a authtype Link Here
16
melm 152$b authtype:w,authtype:p
16
melm 152$b authtype:w,authtype:p
17
17
18
# Personal Name
18
# Personal Name
19
melm 200$a Personal-name-heading:w,Personal-name-heading:p,Personal-name-heading:s,Personal-name:w,Personal-name:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s
19
melm 200$a Personal-name-heading:w,Personal-name-heading:p,Personal-name-heading:s,Personal-name:w,Personal-name:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s,Match:w,Match:p
20
melm 200 Personal-name:w,Personal-name:p,Heading:w,Heading:p
20
melm 200 Personal-name:w,Personal-name:p,Heading:w,Heading:p,Match:w,Match:p
21
melm 400 Personal-name-see:w,Personal-name-see:p,See:w,See:p
21
melm 400 Personal-name-see:w,Personal-name-see:p,See:w,See:p,Match:w,Match:p
22
melm 500 Personal-name-see-also:w,Personal-name-see-also:p,See-also:w,See-also:p
22
melm 500 Personal-name-see-also:w,Personal-name-see-also:p,See-also:w,See-also:p,Match:w,Match:p
23
melm 700$a Personal-name-parallel:w,Personal-name-parallel:p,Parallel:w,Parallel:p
23
melm 700$a Personal-name-parallel:w,Personal-name-parallel:p,Parallel:w,Parallel:p,Match:w,Match:p
24
24
25
# Corporate Name
25
# Corporate Name
26
melm 210$a Corporate-name-heading:w,Corporate-name-heading:p,Corporate-name-heading:s,Corporate-name:w,Corporate-name:p,Conference-name-heading:w,Conference-name-heading:p,Conference-name-heading:s,Conference-name:w,Conference-name:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s
26
melm 210$a Corporate-name-heading:w,Corporate-name-heading:p,Corporate-name-heading:s,Corporate-name:w,Corporate-name:p,Conference-name-heading:w,Conference-name-heading:p,Conference-name-heading:s,Conference-name:w,Conference-name:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s,Match:w,Match:p
27
melm 210 Corporate-name:w,Corporate-name:p,Conference-name:w,Conference-name:p,Heading:w,Heading:p
27
melm 210 Corporate-name:w,Corporate-name:p,Conference-name:w,Conference-name:p,Heading:w,Heading:p,Match:w,Match:p
28
melm 410 Corporate-name-see:w,Corporate-name-see:p,Conference-name-see:w,Conference-name-see:p,See:w,See:p
28
melm 410 Corporate-name-see:w,Corporate-name-see:p,Conference-name-see:w,Conference-name-see:p,See:w,See:p,Match:w,Match:p
29
melm 510 Corporate-name-see-also:w,Corporate-name-see-also:p,Conference-name-see-also:w,Conference-name-see-also:p,See-also:w,See-also:p
29
melm 510 Corporate-name-see-also:w,Corporate-name-see-also:p,Conference-name-see-also:w,Conference-name-see-also:p,See-also:w,See-also:p,Match:w,Match:p
30
melm 710 Corporate-name-parallel:w,Corporate-name-parallel:p,Parallel:w,Parallel:p
30
melm 710 Corporate-name-parallel:w,Corporate-name-parallel:p,Parallel:w,Parallel:p,Match:w,Match:p
31
31
32
32
33
# Geographic & Geographic Name
33
# Geographic & Geographic Name
34
melm 215$a Name-geographic-heading:w,Name-geographic-heading:w,Name-geographic-heading:s,Name-geographic:w,Name-geographic:p,Term-geographic-heading:w,Term-geographic-heading:p,Term-geographic-heading:s,Term-geographic:w,Term-geographic:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s
34
melm 215$a Name-geographic-heading:w,Name-geographic-heading:w,Name-geographic-heading:s,Name-geographic:w,Name-geographic:p,Term-geographic-heading:w,Term-geographic-heading:p,Term-geographic-heading:s,Term-geographic:w,Term-geographic:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s,Match:w,Match:p
35
melm 215 Name-geographic-heading:w,Name-geographic-heading:w,Name-geographic-heading:s,Name-geographic:w,Name-geographic:p,Term-geographic:w,Term-geographic:p,Term-geographic:s,Heading:w,Heading:p,Heading:s
35
melm 215 Name-geographic-heading:w,Name-geographic-heading:w,Name-geographic-heading:s,Name-geographic:w,Name-geographic:p,Term-geographic:w,Term-geographic:p,Term-geographic:s,Heading:w,Heading:p,Heading:s,Match:w,Match:p
36
melm 415 Name-geographic-see:w,Name-geographic-see:p,Term-geographic-see:w,Term-geographic-see:p,Term-geographic-see:s,See:w,See:p,See:s
36
melm 415 Name-geographic-see:w,Name-geographic-see:p,Term-geographic-see:w,Term-geographic-see:p,Term-geographic-see:s,See:w,See:p,See:s,Match:w,Match:p
37
melm 515 Name-geographic-see-also:w,Name-geographic-see-also:p,Term-geographic-see-also:w,Term-geographic-see-also:p,Term-geographic-see-also:s,See-also:w,See-also:p,See-also:s
37
melm 515 Name-geographic-see-also:w,Name-geographic-see-also:p,Term-geographic-see-also:w,Term-geographic-see-also:p,Term-geographic-see-also:s,See-also:w,See-also:p,See-also:s,Match:w,Match:p
38
melm 715 Name-geographic-parallel:w,Name-geographic-parallel:p,Term-geographic-parallel:w,Term-geographic-parallel:p,Term-geographic-parallel:s,Parallel:w,Parallel:p,Parallel:s
38
melm 715 Name-geographic-parallel:w,Name-geographic-parallel:p,Term-geographic-parallel:w,Term-geographic-parallel:p,Term-geographic-parallel:s,Parallel:w,Parallel:p,Parallel:s,Match:w,Match:p
39
39
40
# Trademark
40
# Trademark
41
melm 216$a Trademark-heading:w,Trademark-heading:p,Trademark-heading:s,Trademark:w,Trademark:p,Conference-name-heading:w,Conference-name-heading:p,Conference-name-heading:s,Conference-name:w,Conference-name:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s
41
melm 216$a Trademark-heading:w,Trademark-heading:p,Trademark-heading:s,Trademark:w,Trademark:p,Conference-name-heading:w,Conference-name-heading:p,Conference-name-heading:s,Conference-name:w,Conference-name:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s,Match:w,Match:p
42
melm 216 Trademark:w,Trademark:p,Conference-name:w,Conference-name:p,Heading:w,Heading:p
42
melm 216 Trademark:w,Trademark:p,Conference-name:w,Conference-name:p,Heading:w,Heading:p,Match:w,Match:p
43
melm 416 Trademark-see:w,Trademark-see:p,Conference-name-see:w,Conference-name-see:p,See:w,See:p
43
melm 416 Trademark-see:w,Trademark-see:p,Conference-name-see:w,Conference-name-see:p,See:w,See:p,Match:w,Match:p
44
melm 516 Trademark-see-also:w,Trademark-see-also:p,Conference-name-see-also:w,Conference-name-see-also:p,See-also:w,See-also:p
44
melm 516 Trademark-see-also:w,Trademark-see-also:p,Conference-name-see-also:w,Conference-name-see-also:p,See-also:w,See-also:p,Match:w,Match:p
45
melm 716 Trademark-parallel:w,Trademark-parallel:p,Parallel:w,Parallel:p
45
melm 716 Trademark-parallel:w,Trademark-parallel:p,Parallel:w,Parallel:p,Match:w,Match:p
46
46
47
# Family Name
47
# Family Name
48
melm 220$a Name-heading:w,Name-heading:p,Name-heading:s,Name:w,Name:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s
48
melm 220$a Name-heading:w,Name-heading:p,Name-heading:s,Name:w,Name:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s,Match:w,Match:p
49
melm 220 Name:w,Name:p,Name:s,Heading:w,Heading:p,Heading:s
49
melm 220 Name:w,Name:p,Name:s,Heading:w,Heading:p,Heading:s,Match:w,Match:p
50
melm 420 Name-see:w,Name-see:p,Name-see:s,See:w,See:p,See:s
50
melm 420 Name-see:w,Name-see:p,Name-see:s,See:w,See:p,See:s,Match:w,Match:p
51
melm 520 Name-see-also:w,Name-see-also:p,Name-see-also:s,See-also:w,See-also:p,See-also:s
51
melm 520 Name-see-also:w,Name-see-also:p,Name-see-also:s,See-also:w,See-also:p,See-also:s,Match:w,Match:p
52
melm 720 Name-parallel:w,Name-parallel:p,Name-parallel:s,Parallel:w,Parallel:p,Parallel:s
52
melm 720 Name-parallel:w,Name-parallel:p,Name-parallel:s,Parallel:w,Parallel:p,Parallel:s,Match:w,Match:p
53
53
54
# Uniform Title
54
# Uniform Title
55
melm 230$a Title-uniform-heading:w,Title-uniform-heading:p,Title-uniform-heading:s,Title-uniform:w,Title-uniform:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s
55
melm 230$a Title-uniform-heading:w,Title-uniform-heading:p,Title-uniform-heading:s,Title-uniform:w,Title-uniform:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s,Match:w,Match:p
56
melm 230 Title-uniform:w,Title-uniform:p,Heading:w,Heading:p
56
melm 230 Title-uniform:w,Title-uniform:p,Heading:w,Heading:p,Match:w,Match:p
57
melm 430 Title-uniform-see:w,Title-uniform-see:p,See:w,See:p
57
melm 430 Title-uniform-see:w,Title-uniform-see:p,See:w,See:p,Match:w,Match:p
58
melm 530 Title-uniform-see-also:w,Title-uniform-see-also:p,See-also:w,See-also:p
58
melm 530 Title-uniform-see-also:w,Title-uniform-see-also:p,See-also:w,See-also:p,Match:w,Match:p
59
melm 730$a Title-uniform-parallel:w,Title-uniform-parallel:p,Parallel:w,Parallel:p
59
melm 730$a Title-uniform-parallel:w,Title-uniform-parallel:p,Parallel:w,Parallel:p,Match:w,Match:p
60
60
61
# Second area for uniform titles in UNIMARC?
61
# Second area for uniform titles in UNIMARC?
62
melm 235$a Title-uniform-heading:w,Title-uniform-heading:p,Title-uniform-heading:s,Title-uniform:w,Title-uniform:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s
62
melm 235$a Title-uniform-heading:w,Title-uniform-heading:p,Title-uniform-heading:s,Title-uniform:w,Title-uniform:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s,Match:w,Match:p
63
melm 235 Title-uniform:w,Title-uniform:p,Heading:w,Heading:p
63
melm 235 Title-uniform:w,Title-uniform:p,Heading:w,Heading:p,Match:w,Match:p
64
melm 435 Title-uniform-see:w,Title-uniform-see:p,See:w,See:p
64
melm 435 Title-uniform-see:w,Title-uniform-see:p,See:w,See:p,Match:w,Match:p
65
melm 535 Title-uniform-see-also:w,Title-uniform-see-also:p,See-also:w,See-also:p
65
melm 535 Title-uniform-see-also:w,Title-uniform-see-also:p,See-also:w,See-also:p,Match:w,Match:p
66
melm 735$a Title-uniform-parallel:w,Title-uniform-parallel:p,Parallel:w,Parallel:p
66
melm 735$a Title-uniform-parallel:w,Title-uniform-parallel:p,Parallel:w,Parallel:p,Match:w,Match:p
67
67
68
# Uniform Title
68
# Uniform Title
69
melm 240$a Name-Title-heading:w,Name-Title-heading:p,Name-Title-heading:s,Name-Title:w,Name-Title:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s
69
melm 240$a Name-Title-heading:w,Name-Title-heading:p,Name-Title-heading:s,Name-Title:w,Name-Title:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s,Match:w,Match:p
70
melm 240 Name-Title:w,Name-Title:p,Heading:w,Heading:p
70
melm 240 Name-Title:w,Name-Title:p,Heading:w,Heading:p,Match:w,Match:p
71
melm 440 Name-Title-see:w,Name-Title-see:p,See:w,See:p
71
melm 440 Name-Title-see:w,Name-Title-see:p,See:w,See:p,Match:w,Match:p
72
melm 540 Name-Title-see-also:w,Name-Title-see-also:p,See-also:w,See-also:p
72
melm 540 Name-Title-see-also:w,Name-Title-see-also:p,See-also:w,See-also:p,Match:w,Match:p
73
melm 740$a Name-Title-parallel:w,Name-Title-parallel:p,Parallel:w,Parallel:p
73
melm 740$a Name-Title-parallel:w,Name-Title-parallel:p,Parallel:w,Parallel:p,Match:w,Match:p
74
74
75
# Second area for uniform titles in UNIMARC?
75
# Second area for uniform titles in UNIMARC?
76
melm 245$a Title-uniform-heading:w,Title-uniform-heading:p,Title-uniform-heading:s,Title-uniform:w,Title-uniform:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s
76
melm 245$a Title-uniform-heading:w,Title-uniform-heading:p,Title-uniform-heading:s,Title-uniform:w,Title-uniform:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s,Match:w,Match:p
77
melm 245 Title-uniform:w,Title-uniform:p,Heading:w,Heading:p
77
melm 245 Title-uniform:w,Title-uniform:p,Heading:w,Heading:p,Match:w,Match:p
78
melm 445 Title-uniform-see:w,Title-uniform-see:p,See:w,See:p
78
melm 445 Title-uniform-see:w,Title-uniform-see:p,See:w,See:p,Match:w,Match:p
79
melm 545 Title-uniform-see-also:w,Title-uniform-see-also:p,See-also:w,See-also:p
79
melm 545 Title-uniform-see-also:w,Title-uniform-see-also:p,See-also:w,See-also:p,Match:w,Match:p
80
melm 745$a Title-uniform-parallel:w,Title-uniform-parallel:p,Parallel:w,Parallel:p
80
melm 745$a Title-uniform-parallel:w,Title-uniform-parallel:p,Parallel:w,Parallel:p,Match:w,Match:p
81
81
82
# Topical Term
82
# Topical Term
83
melm 250$a Subject-heading:w,Subject-heading:p,Subject-heading:s,Subject:w,Subject:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s
83
melm 250$a Subject-heading:w,Subject-heading:p,Subject-heading:s,Subject:w,Subject:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s,Match:w,Match:p
84
melm 250 Subject:w,Subject:p,Heading:w,Heading:p,Subject-heading:w,Subject-heading:p,Subject-heading:s
84
melm 250 Subject:w,Subject:p,Heading:w,Heading:p,Subject-heading:w,Subject-heading:p,Subject-heading:s,Match:w,Match:p
85
melm 450 Subject-see:w,Subject-see:p,See:w,See:p
85
melm 450 Subject-see:w,Subject-see:p,See:w,See:p,Match:w,Match:p
86
melm 550 Subject-see-also:w,Subject-see-also:p,See-also:w,See-also:p
86
melm 550 Subject-see-also:w,Subject-see-also:p,See-also:w,See-also:p,Match:w,Match:p
87
melm 750$a Subject-parallel:w,Subject-parallel:p,Parallel:w,Parallel:p
87
melm 750$a Subject-parallel:w,Subject-parallel:p,Parallel:w,Parallel:p,Match:w,Match:p
88
88
89
# Place Access
89
# Place Access
90
melm 260$a Place-heading:w,Place-heading:p,Place-heading:s,Place:w,Place:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s
90
melm 260$a Place-heading:w,Place-heading:p,Place-heading:s,Place:w,Place:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s,Match:w,Match:p
91
melm 260 Place:w,Place:p,Heading:w,Heading:p,Place-heading:w,Place-heading:p,Place-heading:s
91
melm 260 Place:w,Place:p,Heading:w,Heading:p,Place-heading:w,Place-heading:p,Place-heading:s,Match:w,Match:p
92
melm 460 Place-see:w,Place-see:p,See:w,See:p
92
melm 460 Place-see:w,Place-see:p,See:w,See:p,Match:w,Match:p
93
melm 560 Place-see-also:w,Place-see-also:p,See-also:w,See-also:p
93
melm 560 Place-see-also:w,Place-see-also:p,See-also:w,See-also:p,Match:w,Match:p
94
melm 760$a Place-parallel:w,Place-parallel:p,Parallel:w,Parallel:p
94
melm 760$a Place-parallel:w,Place-parallel:p,Parallel:w,Parallel:p,Match:w,Match:p
95
95
96
# Form Genre
96
# Form Genre
97
melm 280$a Form-heading:w,Form-heading:p,Form-heading:s,Form:w,Form:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s
97
melm 280$a Form-heading:w,Form-heading:p,Form-heading:s,Form:w,Form:p,Heading:w,Heading:p,Heading:s,Heading-Main:w,Heading-Main:p,Heading-Main:s,Match:w,Match:p
98
melm 280 Form:w,Form:p,Heading:w,Heading:p,Form-heading:w,Form-heading:p,Form-heading:s
98
melm 280 Form:w,Form:p,Heading:w,Heading:p,Form-heading:w,Form-heading:p,Form-heading:s,Match:w,Match:p
99
melm 480 Form-see:w,Form-see:p,See:w,See:p
99
melm 480 Form-see:w,Form-see:p,See:w,See:p,Match:w,Match:p
100
melm 580 Form-see-also:w,Form-see-also:p,See-also:w,See-also:p
100
melm 580 Form-see-also:w,Form-see-also:p,See-also:w,See-also:p,Match:w,Match:p
101
melm 780$a Form-parallel:w,Form-parallel:p,Parallel:w,Parallel:p
101
melm 780$a Form-parallel:w,Form-parallel:p,Parallel:w,Parallel:p,Match:w,Match:p
102
102
103
103
104
# NOTE: subdivisions management missing from Koha
104
# NOTE: subdivisions management missing from Koha
(-)a/installer/data/mysql/atomicupdate/bug_7284_authority_linking_pt1 (+21 lines)
Line 0 Link Here
1
#! /usr/bin/perl
2
use strict;
3
use warnings;
4
use C4::Context;
5
my $dbh = C4::Context->dbh;
6
$dbh->do(
7
"INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('LinkerModule','Default','Chooses which linker module to use (see documentation).','Default|FirstMatchLastMatch','Choice');"
8
);
9
$dbh->do(
10
"INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('LinkerOptions','','A pipe-separated list of options for the linker.','','free');"
11
);
12
$dbh->do(
13
"INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('LinkerRelink',1,'If ON the authority linker will relink headings that have previously been linked every time it runs.',NULL,'YesNo');"
14
);
15
$dbh->do(
16
"INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('LinkerKeepStale',0,'If ON the authority linker will keep existing authority links for headings where it is unable to find a match.',NULL,'YesNo');"
17
);
18
$dbh->do(
19
"INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('AutoCreateAuthorities',0,'Automatically create authorities that do not exist when cataloging records.',NULL,'YesNo');"
20
);
21
print "Upgrade done (Configured bug 7284, improved authority matching)\n";
(-)a/installer/data/mysql/sysprefs.sql (+5 lines)
Lines 330-332 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES Link Here
330
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('EasyAnalyticalRecords','0','If on, display in the catalogue screens tools to easily setup analytical record relationships','','YesNo');
330
INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('EasyAnalyticalRecords','0','If on, display in the catalogue screens tools to easily setup analytical record relationships','','YesNo');
331
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacShowRecentComments',0,'If ON a link to recent comments will appear in the OPAC masthead',NULL,'YesNo');
331
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpacShowRecentComments',0,'If ON a link to recent comments will appear in the OPAC masthead',NULL,'YesNo');
332
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('CircAutoPrintQuickSlip', '1', 'Choose what should happen when an empty barcode field is submitted in circulation: Display a print quick slip window or Clear the screen.',NULL,'YesNo');
332
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('CircAutoPrintQuickSlip', '1', 'Choose what should happen when an empty barcode field is submitted in circulation: Display a print quick slip window or Clear the screen.',NULL,'YesNo');
333
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('AutoCreateAuthorities',0,'Automatically create authorities that do not exist when cataloging records.',NULL,'YesNo');
334
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('LinkerModule','Default','Chooses which linker module to use (see documentation).','Default|FirstMatch|LastMatch','Choice');
335
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('LinkerOptions','','A pipe-separated list of options for the linker.','','free');
336
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('LinkerRelink',1,'If ON the authority linker will relink headings that have previously been linked every time it runs.',NULL,'YesNo');
337
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('LinkerKeepStale',0,'If ON the authority linker will keep existing authority links for headings where it is unable to find a match.',NULL,'YesNo');
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/auth-finder-search.inc (-1 / +13 lines)
Lines 33-39 Link Here
33
                </li>
33
                </li>
34
                <li>
34
                <li>
35
                    <label for="marclist">Anywhere</label>
35
                    <label for="marclist">Anywhere</label>
36
                    <input type="hidden" name="marclist" value="" />
36
                    <input type="hidden" name="marclist" value="any" />
37
                    <input type="hidden" name="and_or" value="and" />
37
                    <input type="hidden" name="and_or" value="and" />
38
                    <input type="hidden" name="excluding" value="" />
38
                    <input type="hidden" name="excluding" value="" />
39
                    <select name="operator" id="marclist">
39
                    <select name="operator" id="marclist">
Lines 43-48 Link Here
43
                    </select>
43
                    </select>
44
                    <input type="text" name="value_any" value="[% value_any |html %]" />
44
                    <input type="text" name="value_any" value="[% value_any |html %]" />
45
                </li>
45
                </li>
46
                <li>
47
                    <label for="marclist">Heading match</label>
48
                    <input type="hidden" name="marclist" value="match" />
49
                    <input type="hidden" name="and_or" value="and" />
50
                    <input type="hidden" name="excluding" value="" />
51
                    <select name="operator" id="marclist">
52
                        <option value="contains">contains</option>
53
                        <option value="start">starts with</option>
54
                        <option value="is">is exactly</option>
55
                    </select>
56
                    <input type="text" name="value_match" value="[% value_match |html %]" />
57
                </li>
46
		<li>
58
		<li>
47
		<label for="orderby">Sort by </label>
59
		<label for="orderby">Sort by </label>
48
		<select name="orderby" id="orderby">
60
		<select name="orderby" id="orderby">
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/authorities.pref (-28 / +66 lines)
Lines 1-29 Link Here
1
Authorities:
1
Authorities:
2
    -
2
    General:
3
        - When editing records,
3
        -
4
        - pref: BiblioAddsAuthorities
4
            - When editing records,
5
          default: no
5
            - pref: BiblioAddsAuthorities
6
          choices:
6
              default: no
7
              yes: allow
7
              choices:
8
              no: "don't allow"
8
                  yes: allow
9
        - them to automatically create new authority records if needed, rather than having to reference existing authorities.
9
                  no: "don't allow"
10
    -
10
            - them to automatically create new authority records if needed, rather than having to reference existing authorities.
11
        - pref: dontmerge
11
        -
12
          default: yes
12
            - When editing records,
13
          choices:
13
            - pref: AutoCreateAuthorities
14
              yes: "Don't"
14
              default: yes
15
              no: Do
15
              choices:
16
        - automatically update attached biblios when changing an authority record. If this is off, please ask your administrator to enable the merge_authority.pl cronjob.
16
                  yes: generate
17
    -
17
                  no: "do not generate"
18
        - Use the following text for the contents of MARC authority control field 008 position 06-39 (fixed length data elements). Do NOT include the date (position 00-05).
18
            - authority records that are missing (BiblioAddsAuthorities must be set to "allow" for this to have any effect).
19
        - pref: MARCAuthorityControlField008
19
        -
20
          default: "|| aca||aabn           | a|a     d"
20
            - pref: dontmerge
21
          type: textarea
21
              default: yes
22
          class: code
22
              choices:
23
    -
23
                  yes: "Don't"
24
        - pref: UseAuthoritiesForTracings
24
                  no: Do
25
          default: yes
25
            - automatically update attached biblios when changing an authority record. If this is off, please ask your administrator to enable the merge_authority.pl cronjob.
26
          choices:
26
        -
27
              yes: Use
27
            - Use the following text for the contents of MARC authority control field 008 position 06-39 (fixed length data elements). Do NOT include the date (position 00-05).
28
              no: "Don't use"
28
            - pref: MARCAuthorityControlField008
29
        - authority record numbers instead of text strings for searches from subject tracings.
29
              default: "|| aca||aabn           | a|a     d"
30
              type: textarea
31
              class: code
32
        -
33
            - pref: UseAuthoritiesForTracings
34
              default: yes
35
              choices:
36
                  yes: Use
37
                  no: "Don't use"
38
            - authority record numbers instead of text strings for searches from subject tracings.
39
    Linker:
40
        -
41
            - Use the
42
            - pref: LinkerModule
43
              default: Default
44
              choices:
45
                  Default: Default
46
                  FirstMatch: "First Match"
47
                  LastMatch: "Last Match"
48
            - linker module for matching headings to authority records.
49
        -
50
            - Set the following options for the authority linker
51
            - pref: LinkerOptions
52
              class: multi
53
            - (separate options with |)
54
        -
55
            - pref: LinkerRelink
56
              default: yes
57
              choices:
58
                  yes: Do
59
                  no: "Do not"
60
            - relink headings that have previously been linked to authority records.
61
        -
62
            - pref: LinkerKeepStale
63
              default: no
64
              choices:
65
                  yes: Do
66
                  no: "Do not"
67
            - keep existing links to authority records for headings where the linker is unable to find a match.
(-)a/misc/link_bibs_to_authorities.pl (-51 / +218 lines)
Lines 2-8 Link Here
2
2
3
use strict;
3
use strict;
4
use warnings;
4
use warnings;
5
5
BEGIN {
6
BEGIN {
7
6
    # find Koha's Perl modules
8
    # find Koha's Perl modules
7
    # test carefully before changing this
9
    # test carefully before changing this
8
    use FindBin;
10
    use FindBin;
Lines 12-97 BEGIN { Link Here
12
use C4::Context;
14
use C4::Context;
13
use C4::Biblio;
15
use C4::Biblio;
14
use Getopt::Long;
16
use Getopt::Long;
17
use Pod::Usage;
18
use Data::Dumper;
19
20
sub usage {
21
    pod2usage( -verbose => 2 );
22
    exit;
23
}
15
24
16
$| = 1;
25
$| = 1;
17
26
18
# command-line parameters
27
# command-line parameters
19
my $verbose   = 0;
28
my $verbose     = 0;
20
my $test_only = 0;
29
my $link_report = 0;
21
my $want_help = 0;
30
my $test_only   = 0;
31
my $want_help   = 0;
32
my $auth_limit;
33
my $bib_limit;
34
my $commit = 100;
22
35
23
my $result = GetOptions(
36
my $result = GetOptions(
24
    'verbose'       => \$verbose,
37
    'v|verbose'      => \$verbose,
25
    'test'          => \$test_only,
38
    't|test'         => \$test_only,
26
    'h|help'        => \$want_help
39
    'l|link-report'  => \$link_report,
40
    'a|auth-limit=s' => \$auth_limit,
41
    'b|bib-limit=s'  => \$bib_limit,
42
    'c|commit=i'     => \$commit,
43
    'h|help'         => \$want_help
27
);
44
);
28
45
29
if (not $result or $want_help) {
46
binmode( STDOUT, ":utf8" );
30
    print_usage();
47
31
    exit 0;
48
if ( not $result or $want_help ) {
49
    usage();
50
}
51
52
my $linker_module =
53
  "C4::Linker::" . ( C4::Context->preference("LinkerModule") || 'Default' );
54
eval { eval "require $linker_module"; };
55
if ($@) {
56
    $linker_module = 'C4::Linker::Default';
57
    eval "require $linker_module";
58
}
59
if ($@) {
60
    die "Unable to load linker module. Aborting.";
32
}
61
}
33
62
63
my $linker = $linker_module->new(
64
    {
65
        'auth_limit' => $auth_limit,
66
        'options'    => C4::Context->preference("LinkerOptions")
67
    }
68
);
69
34
my $num_bibs_processed = 0;
70
my $num_bibs_processed = 0;
35
my $num_bibs_modified = 0;
71
my $num_bibs_modified  = 0;
36
my $num_bad_bibs = 0;
72
my $num_bad_bibs       = 0;
73
my %unlinked_headings;
74
my %linked_headings;
75
my %fuzzy_headings;
37
my $dbh = C4::Context->dbh;
76
my $dbh = C4::Context->dbh;
38
$dbh->{AutoCommit} = 0;
77
$dbh->{AutoCommit} = 0;
39
process_bibs();
78
process_bibs( $linker, $bib_limit, $auth_limit, $commit );
40
$dbh->commit();
79
$dbh->commit();
41
80
42
exit 0;
81
exit 0;
43
82
44
sub process_bibs {
83
sub process_bibs {
45
    my $sql = "SELECT biblionumber FROM biblio ORDER BY biblionumber ASC";
84
    my ( $linker, $bib_limit, $auth_limit, $commit ) = @_;
85
    my $bib_where = '';
86
    if ($bib_limit) {
87
        $bib_where = "WHERE $bib_limit";
88
    }
89
    my $sql =
90
      "SELECT biblionumber FROM biblio $bib_where ORDER BY biblionumber ASC";
46
    my $sth = $dbh->prepare($sql);
91
    my $sth = $dbh->prepare($sql);
47
    $sth->execute();
92
    $sth->execute();
48
    while (my ($biblionumber) = $sth->fetchrow_array()) {
93
    while ( my ($biblionumber) = $sth->fetchrow_array() ) {
49
        $num_bibs_processed++;
94
        $num_bibs_processed++;
50
        process_bib($biblionumber);
95
        process_bib( $linker, $biblionumber );
51
96
52
        if (not $test_only and ($num_bibs_processed % 100) == 0) {
97
        if ( not $test_only and ( $num_bibs_processed % $commit ) == 0 ) {
53
            print_progress_and_commit($num_bibs_processed);
98
            print_progress_and_commit($num_bibs_processed);
54
        }
99
        }
55
    }
100
    }
56
101
57
    if (not $test_only) {
102
    if ( not $test_only ) {
58
        $dbh->commit;
103
        $dbh->commit;
59
    }
104
    }
60
105
106
    my $headings_linked   = 0;
107
    my $headings_unlinked = 0;
108
    my $headings_fuzzy    = 0;
109
    for ( values %linked_headings )   { $headings_linked   += $_; }
110
    for ( values %unlinked_headings ) { $headings_unlinked += $_; }
111
    for ( values %fuzzy_headings )    { $headings_fuzzy    += $_; }
112
61
    print <<_SUMMARY_;
113
    print <<_SUMMARY_;
62
114
63
Bib authority heading linking report
115
Bib authority heading linking report
64
------------------------------------
116
=======================================================
65
Number of bibs checked:       $num_bibs_processed
117
Linker module:                          $linker_module
66
Number of bibs modified:      $num_bibs_modified
118
Number of bibs checked:                 $num_bibs_processed
67
Number of bibs with errors:   $num_bad_bibs
119
Number of bibs modified:                $num_bibs_modified
120
Number of bibs with errors:             $num_bad_bibs
121
Number of headings linked:              $headings_linked
122
Number of headings unlinked:            $headings_unlinked
123
Number of headings fuzzily linked:      $headings_fuzzy
68
_SUMMARY_
124
_SUMMARY_
125
    print "****  Ran in test mode only  ****\n" if $test_only;
126
127
    if ($link_report) {
128
        my @keys;
129
        print <<_LINKED_HEADER_;
130
131
Linked headings (from most frequent to least):
132
-------------------------------------------------------
133
134
_LINKED_HEADER_
135
136
        @keys = sort {
137
            $linked_headings{$b} <=> $linked_headings{$a} or "\L$a" cmp "\L$b"
138
        } keys %linked_headings;
139
        foreach my $key (@keys) {
140
            print "$key:\t" . $linked_headings{$key} . " occurrences\n";
141
        }
142
143
        print <<_UNLINKED_HEADER_;
144
145
Unlinked headings (from most frequent to least):
146
-------------------------------------------------------
147
148
_UNLINKED_HEADER_
149
150
        @keys = sort {
151
            $unlinked_headings{$b} <=> $unlinked_headings{$a}
152
              or "\L$a" cmp "\L$b"
153
        } keys %unlinked_headings;
154
        foreach my $key (@keys) {
155
            print "$key:\t" . $unlinked_headings{$key} . " occurrences\n";
156
        }
157
158
        print <<_FUZZY_HEADER_;
159
160
Fuzzily-matched headings (from most frequent to least):
161
-------------------------------------------------------
162
163
_FUZZY_HEADER_
164
165
        @keys = sort {
166
            $fuzzy_headings{$b} <=> $fuzzy_headings{$a} or "\L$a" cmp "\L$b"
167
        } keys %fuzzy_headings;
168
        foreach my $key (@keys) {
169
            print "$key:\t" . $fuzzy_headings{$key} . " occurrences\n";
170
        }
171
        print <<_SUMMARY2_;
172
173
174
Printing out summary report again since your link
175
report may have been very long...
176
177
Bib authority heading linking report (duplicate)
178
=======================================================
179
Linker module:                          $linker_module
180
Number of bibs checked:                 $num_bibs_processed
181
Number of bibs modified:                $num_bibs_modified
182
Number of bibs with errors:             $num_bad_bibs
183
Number of headings linked:              $headings_linked
184
Number of headings unlinked:            $headings_unlinked
185
Number of headings fuzzily linked:      $headings_fuzzy
186
_SUMMARY2_
187
        print "****  Ran in test mode only  ****\n" if $test_only;
188
    }
69
}
189
}
70
190
71
sub process_bib {
191
sub process_bib {
192
    my $linker       = shift;
72
    my $biblionumber = shift;
193
    my $biblionumber = shift;
73
194
74
    my $bib = GetMarcBiblio($biblionumber);
195
    my $bib = GetMarcBiblio($biblionumber);
75
    unless (defined $bib) {
196
    unless ( defined $bib ) {
76
        print "\nCould not retrieve bib $biblionumber from the database - record is corrupt.\n";
197
        print
198
"\nCould not retrieve bib $biblionumber from the database - record is corrupt.\n";
77
        $num_bad_bibs++;
199
        $num_bad_bibs++;
78
        return;
200
        return;
79
    }
201
    }
80
202
81
    my $headings_changed = LinkBibHeadingsToAuthorities($bib);
203
    my ( $headings_changed, $results ) =
204
      LinkBibHeadingsToAuthorities( $linker, $bib,
205
        GetFrameworkCode($biblionumber) );
206
    foreach my $key ( keys %{ $results->{'unlinked'} } ) {
207
        $unlinked_headings{$key} += $results->{'unlinked'}->{$key};
208
    }
209
    foreach my $key ( keys %{ $results->{'linked'} } ) {
210
        $linked_headings{$key} += $results->{'linked'}->{$key};
211
    }
212
    foreach my $key ( keys %{ $results->{'fuzzy'} } ) {
213
        $fuzzy_headings{$key} += $results->{'fuzzy'}->{$key};
214
    }
82
215
83
    if ($headings_changed) {   
216
    if ($headings_changed) {
84
        if ($verbose) {
217
        if ($verbose) {
85
            my $title = substr($bib->title, 0, 20);
218
            my $title = substr( $bib->title, 0, 20 );
86
            print "Bib $biblionumber ($title): $headings_changed headings changed\n";
219
            print
220
"Bib $biblionumber ($title): $headings_changed headings changed\n";
87
        }
221
        }
88
        if (not $test_only) {
222
        if ( not $test_only ) {
89
            # delete any item tags
223
            ModBiblio( $bib, $biblionumber, GetFrameworkCode($biblionumber) );
90
            my ($itemtag, $itemsubfield) = GetMarcFromKohaField("items.itemnumber", '');
91
            foreach my $field ($bib->field($itemtag)) {
92
                $bib->delete_field($field);
93
            }
94
            ModBiblio($bib, $biblionumber, GetFrameworkCode($biblionumber));
95
            $num_bibs_modified++;
224
            $num_bibs_modified++;
96
        }
225
        }
97
    }
226
    }
Lines 103-122 sub print_progress_and_commit { Link Here
103
    print "... processed $recs records\n";
232
    print "... processed $recs records\n";
104
}
233
}
105
234
106
sub print_usage {
235
=head1 NAME
107
    print <<_USAGE_;
236
108
$0: link headings in bib records to authorities.
237
link_bibs_to_authorities.pl
109
238
110
This batch job checks each bib record in the Koha
239
=head1 SYNOPSIS
111
database and attempts to link each of its headings
240
112
to the matching authority record.
241
  link_bibs_to_authorities.pl
113
242
  link_bibs_to_authorities.pl -v
114
Parameters:
243
  link_bibs_to_authorities.pl -l
115
    --verbose               print the number of headings changed
244
  link_bibs_to_authorities.pl --commit=1000
116
                            for each bib
245
  link_bibs_to_authorities.pl --auth-limit=STRING
117
    --test                  only test the authority linking
246
  link_bibs_to_authorities.pl --bib-limit=STRING
118
                            and report the results; do not
247
119
                            change the bib records.
248
=head1 DESCRIPTION
120
    --help or -h            show this message.
249
121
_USAGE_
250
This batch job checks each bib record in the Koha database and attempts to link
122
}
251
each of its headings to the matching authority record.
252
253
=over 8
254
255
=item B<--help>
256
257
Prints this help
258
259
=item B<-v|--verbose>
260
261
Provide verbose log information (print the number of headings changed for each
262
bib record).
263
264
=item B<-l|--link-report>
265
266
Provide a report of all the headings that were processed: which were matched,
267
which were not, etc.
268
269
=item B<--auth-limit=S>
270
271
Only process those headings which match an authority record that matches the
272
user-specified WHERE clause.
273
274
=item B<--bib-limit=S>
275
276
Only process those bib records that match the user-specified WHERE clause.
277
278
=item B<--commit=N>
279
280
Commit the results to the database after every N records are processed.
281
282
=item B<--test>
283
284
Only test the authority linking and report the results; do not change the bib
285
records.
286
287
=back
288
289
=cut
(-)a/t/Heading_MARC21.t (-2 / +6 lines)
Lines 6-14 Link Here
6
use strict;
6
use strict;
7
use warnings;
7
use warnings;
8
8
9
use Test::More tests => 1;
9
use Test::More tests => 3;
10
10
11
BEGIN {
11
BEGIN {
12
        use_ok('C4::External::Amazon');
12
        use_ok('C4::Heading');
13
}
13
}
14
14
15
my $field = MARC::Field->new( '650', ' ', '0', a => 'Uncles', x => 'Fiction' );
16
my $heading = C4::Heading->new_from_bib_field($field);
17
is($heading->display_form(), 'Uncles--Fiction', 'Display form generation');
18
is($heading->search_form(), 'Uncles generalsubdiv Fiction', 'Search form generation');
(-)a/t/db_dependent/Linker_FirstMatch.t (+46 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
#
3
# This Koha test module is a stub!
4
# Add more tests here!!!
5
6
use strict;
7
use warnings;
8
use Test::More tests => 3;
9
use C4::Context;
10
use C4::Heading;
11
use MARC::Record;
12
use MARC::Field;
13
use C4::Linker::FirstMatch;
14
15
16
BEGIN {
17
        use_ok('C4::Linker');
18
}
19
my $dbh = C4::Context->dbh;
20
21
my $query = "SELECT authid, marc FROM auth_header LIMIT 1;";
22
my $sth = $dbh->prepare($query);
23
$sth->execute();
24
my ($authid, $marc) = $sth->fetchrow_array();
25
SKIP: {
26
    skip "No authorities", 2 unless defined $authid;
27
    my $linker = C4::Linker::FirstMatch->new();
28
    my $auth = MARC::Record->new_from_usmarc($marc);
29
    my $fieldmatch;
30
    if (C4::Context->preference('MARCFlavour') eq 'UNIMARC') {
31
        $fieldmatch = '2..';
32
    } else {
33
        $fieldmatch = '1..';
34
    }
35
    my $bibfield = $auth->field($fieldmatch);
36
    my $tag = $bibfield->tag();
37
    $tag =~ s/^./6/;
38
    $bibfield->update(tag => $tag);
39
    my $heading;
40
    ok(defined ($heading = C4::Heading->new_from_bib_field($bibfield, '')), "Creating heading from bib field");
41
42
    my $authmatch;
43
    my $fuzzy;
44
    ($authmatch, $fuzzy) = $linker->get_link($heading);
45
    is($authmatch, $authid, "Matched existing heading");
46
}
(-)a/t/db_dependent/lib/KohaTest/AuthoritiesMarc.pm (-2 lines)
Lines 24-30 sub methods : Test( 1 ) { Link Here
24
                      GetAuthorityXML 
24
                      GetAuthorityXML 
25
                      GetAuthority 
25
                      GetAuthority 
26
                      GetAuthType 
26
                      GetAuthType 
27
                      AUTHhtml2marc 
28
                      FindDuplicateAuthority 
27
                      FindDuplicateAuthority 
29
                      BuildSummary
28
                      BuildSummary
30
                      BuildUnimarcHierarchies
29
                      BuildUnimarcHierarchies
31
- 

Return to bug 7284