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 (-16 / +127 lines)
Lines 38-43 use C4::Charset; Link Here
38
require C4::Heading;
38
require C4::Heading;
39
require C4::Serials;
39
require C4::Serials;
40
require C4::Items;
40
require C4::Items;
41
use C4::Linker;
41
42
42
use vars qw($VERSION @ISA @EXPORT);
43
use vars qw($VERSION @ISA @EXPORT);
43
44
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 458-466 sub DelBiblio { Link Here
458
    return;
460
    return;
459
}
461
}
460
462
463
464
=head2 BiblioAutoLink
465
466
  my $headings_linked = BiblioAutoLink($record, $frameworkcode)
467
468
Automatically links headings in a bib record to authorities.
469
470
=cut
471
472
sub BiblioAutoLink {
473
    my $record        = shift;
474
    my $frameworkcode = shift;
475
    my ( $num_headings_changed, %results );
476
477
    my $linker_module =
478
      "C4::Linker::" . ( C4::Context->preference("LinkerModule") || 'Default' );
479
    eval { eval "require $linker_module"; };
480
    if ($@) {
481
        $linker_module = 'C4::Linker::Default';
482
        eval "require $linker_module";
483
    }
484
    if ($@) {
485
        return 0, 0;
486
    }
487
488
    my $linker = $linker_module->new(
489
        { 'options' => C4::Context->preference("LinkerOptions") } );
490
    my ( $headings_changed, undef ) =
491
      LinkBibHeadingsToAuthorities( $linker, $record, $frameworkcode, C4::Context->preference("CatalogModuleRelink") || '' );
492
    # By default we probably don't want to relink things when cataloging
493
    return $headings_changed;
494
}
495
461
=head2 LinkBibHeadingsToAuthorities
496
=head2 LinkBibHeadingsToAuthorities
462
497
463
  my $headings_linked = LinkBibHeadingsToAuthorities($marc);
498
  my $num_headings_changed, %results = LinkBibHeadingsToAuthorities($linker, $marc, $frameworkcode, [$allowrelink]);
464
499
465
Links bib headings to authority records by checking
500
Links bib headings to authority records by checking
466
each authority-controlled field in the C<MARC::Record>
501
each authority-controlled field in the C<MARC::Record>
Lines 468-476 object C<$marc>, looking for a matching authority record, Link Here
468
and setting the linking subfield $9 to the ID of that
503
and setting the linking subfield $9 to the ID of that
469
authority record.  
504
authority record.  
470
505
471
If no matching authority exists, or if multiple
506
If $allowrelink is false, existing authids will never be
472
authorities match, no $9 will be added, and any 
507
replaced, regardless of the values of LinkerKeepStale and
473
existing one inthe field will be deleted.
508
LinkerRelink.
474
509
475
Returns the number of heading links changed in the
510
Returns the number of heading links changed in the
476
MARC record.
511
MARC record.
Lines 478-514 MARC record. Link Here
478
=cut
513
=cut
479
514
480
sub LinkBibHeadingsToAuthorities {
515
sub LinkBibHeadingsToAuthorities {
481
    my $bib = shift;
516
    my $linker        = shift;
517
    my $bib           = shift;
518
    my $frameworkcode = shift;
519
    my $allowrelink = shift;
520
    my %results;
521
    require C4::Heading;
522
    require C4::AuthoritiesMarc;
482
523
524
    $allowrelink = 1 unless defined $allowrelink;
483
    my $num_headings_changed = 0;
525
    my $num_headings_changed = 0;
484
    foreach my $field ( $bib->fields() ) {
526
    foreach my $field ( $bib->fields() ) {
485
        my $heading = C4::Heading->new_from_bib_field($field);
527
        my $heading = C4::Heading->new_from_bib_field( $field, $frameworkcode );
486
        next unless defined $heading;
528
        next unless defined $heading;
487
529
488
        # check existing $9
530
        # check existing $9
489
        my $current_link = $field->subfield('9');
531
        my $current_link = $field->subfield('9');
490
532
491
        # look for matching authorities
533
        if ( defined $current_link && (!$allowrelink || !C4::Context->preference('LinkerRelink')) )
492
        my $authorities = $heading->authorities();
534
        {
535
            $results{'linked'}->{ $heading->display_form() }++;
536
            next;
537
        }
493
538
494
        # want only one exact match
539
        my ( $authid, $fuzzy ) = $linker->get_link($heading);
495
        if ( $#{$authorities} == 0 ) {
540
        if ($authid) {
496
            my $authority = MARC::Record->new_from_usmarc( $authorities->[0] );
541
            $results{ $fuzzy ? 'fuzzy' : 'linked' }
497
            my $authid    = $authority->field('001')->data();
542
              ->{ $heading->display_form() }++;
498
            next if defined $current_link and $current_link eq $authid;
543
            next if defined $current_link and $current_link == $authid;
499
544
500
            $field->delete_subfield( code => '9' ) if defined $current_link;
545
            $field->delete_subfield( code => '9' ) if defined $current_link;
501
            $field->add_subfields( '9', $authid );
546
            $field->add_subfields( '9', $authid );
502
            $num_headings_changed++;
547
            $num_headings_changed++;
503
        } else {
548
        }
504
            if ( defined $current_link ) {
549
        else {
550
            if ( defined $current_link
551
                && (!$allowrelink || C4::Context->preference('LinkerKeepStale')) )
552
            {
553
                $results{'fuzzy'}->{ $heading->display_form() }++;
554
            }
555
            elsif ( C4::Context->preference('AutoCreateAuthorities') ) {
556
                my $authtypedata =
557
                  C4::AuthoritiesMarc::GetAuthType( $heading->auth_type() );
558
                my $marcrecordauth = MARC::Record->new();
559
                if ( C4::Context->preference('marcflavour') eq 'MARC21' ) {
560
                    $marcrecordauth->leader('     nz  a22     o  4500');
561
                    SetMarcUnicodeFlag( $marcrecordauth, 'MARC21' );
562
                }
563
                my $authfield =
564
                  MARC::Field->new( $authtypedata->{auth_tag_to_report},
565
                    '', '', "a" => "" . $field->subfield('a') );
566
                map {
567
                    $authfield->add_subfields( $_->[0] => $_->[1] )
568
                      if ( $_->[0] =~ /[A-z]/ && $_->[0] ne "a" )
569
                } $field->subfields();
570
                $marcrecordauth->insert_fields_ordered($authfield);
571
572
# bug 2317: ensure new authority knows it's using UTF-8; currently
573
# only need to do this for MARC21, as MARC::Record->as_xml_record() handles
574
# automatically for UNIMARC (by not transcoding)
575
# FIXME: AddAuthority() instead should simply explicitly require that the MARC::Record
576
# use UTF-8, but as of 2008-08-05, did not want to introduce that kind
577
# of change to a core API just before the 3.0 release.
578
579
                if ( C4::Context->preference('marcflavour') eq 'MARC21' ) {
580
                    $marcrecordauth->insert_fields_ordered(
581
                        MARC::Field->new(
582
                            '667', '', '',
583
                            'a' => "Machine generated authority record."
584
                        )
585
                    );
586
                    my $cite =
587
                        $bib->author() . ", "
588
                      . $bib->title_proper() . ", "
589
                      . $bib->publication_date() . " ";
590
                    $cite =~ s/^[\s\,]*//;
591
                    $cite =~ s/[\s\,]*$//;
592
                    $cite =
593
                        "Work cat.: ("
594
                      . C4::Context->preference('MARCOrgCode') . ")"
595
                      . $bib->subfield( '999', 'c' ) . ": "
596
                      . $cite;
597
                    $marcrecordauth->insert_fields_ordered(
598
                        MARC::Field->new( '670', '', '', 'a' => $cite ) );
599
                }
600
601
           #          warn "AUTH RECORD ADDED : ".$marcrecordauth->as_formatted;
602
603
                $authid =
604
                  C4::AuthoritiesMarc::AddAuthority( $marcrecordauth, '',
605
                    $heading->auth_type() );
606
                $field->add_subfields( '9', $authid );
607
                $num_headings_changed++;
608
                $results{'added'}->{ $heading->display_form() }++;
609
            }
610
            elsif ( defined $current_link ) {
505
                $field->delete_subfield( code => '9' );
611
                $field->delete_subfield( code => '9' );
506
                $num_headings_changed++;
612
                $num_headings_changed++;
613
                $results{'unlinked'}->{ $heading->display_form() }++;
614
            }
615
            else {
616
                $results{'unlinked'}->{ $heading->display_form() }++;
507
            }
617
            }
508
        }
618
        }
509
619
510
    }
620
    }
511
    return $num_headings_changed;
621
    return $num_headings_changed, \%results;
512
}
622
}
513
623
514
=head2 GetRecordValue
624
=head2 GetRecordValue
Lines 1872-1877 sub PrepHostMarcField { Link Here
1872
    my ($hostbiblionumber,$hostitemnumber, $marcflavour) = @_;
1982
    my ($hostbiblionumber,$hostitemnumber, $marcflavour) = @_;
1873
    $marcflavour ||="MARC21";
1983
    $marcflavour ||="MARC21";
1874
    
1984
    
1985
    require C4::Items;
1875
    my $hostrecord = GetMarcBiblio($hostbiblionumber);
1986
    my $hostrecord = GetMarcBiblio($hostbiblionumber);
1876
	my $item = C4::Items::GetItem($hostitemnumber);
1987
	my $item = C4::Items::GetItem($hostitemnumber);
1877
	
1988
	
(-)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 Module::Load;
26
use C4::Search;
27
use Carp;
26
use Carp;
28
27
29
our $VERSION = 3.00;
28
our $VERSION = 3.00;
Lines 35-45 C4::Heading Link Here
35
=head1 SYNOPSIS
34
=head1 SYNOPSIS
36
35
37
 use C4::Heading;
36
 use C4::Heading;
38
 my $heading = C4::Heading->new_from_bib_field($field);
37
 my $heading = C4::Heading->new_from_bib_field($field, $frameworkcode);
39
 my $thesaurus = $heading->thesaurus();
38
 my $thesaurus = $heading->thesaurus();
40
 my $type = $heading->type();
39
 my $type = $heading->type();
41
 my $display_heading = $heading->display();
40
 my $display_heading = $heading->display_form();
42
 my $search_string = $heading->search_string();
41
 my $search_form = $heading->search_form();
43
42
44
=head1 DESCRIPTION
43
=head1 DESCRIPTION
45
44
Lines 50-56 headings found in bibliographic and authority records. Link Here
50
49
51
=head2 new_from_bib_field
50
=head2 new_from_bib_field
52
51
53
  my $heading = C4::Heading->new_from_bib_field($field[, $marc_flavour]);
52
  my $heading = C4::Heading->new_from_bib_field($field, $frameworkcode, [, $marc_flavour]);
54
53
55
Given a C<MARC::Field> object containing a heading from a 
54
Given a C<MARC::Field> object containing a heading from a 
56
bib record, create a C<C4::Heading> object.
55
bib record, create a C<C4::Heading> object.
Lines 65-88 is returned. Link Here
65
=cut
64
=cut
66
65
67
sub new_from_bib_field {
66
sub new_from_bib_field {
68
    my $class = shift;
67
    my $class         = shift;
69
    my $field = shift;
68
    my $field         = shift;
70
    my $marcflavour = @_ ? shift : C4::Context->preference('marcflavour');
69
    my $frameworkcode = shift;
70
    my $marcflavour   = @_ ? shift : C4::Context->preference('marcflavour');
71
71
72
    my $marc_handler = _marc_format_handler($marcflavour);
72
    my $marc_handler = _marc_format_handler($marcflavour);
73
73
74
    my $tag = $field->tag();
74
    my $tag = $field->tag();
75
    return unless $marc_handler->valid_bib_heading_tag($tag);
75
    return unless $marc_handler->valid_bib_heading_tag( $tag, $frameworkcode );
76
    my $self = {};
76
    my $self = {};
77
   
77
78
    ($self->{'auth_type'}, $self->{'subject_added_entry'}, $self->{'series_added_entry'}, $self->{'main_entry'},
78
    $self->{'field'} = $field;
79
     $self->{'thesaurus'}, $self->{'search_form'}, $self->{'display_form'}) =
79
    (
80
        $marc_handler->parse_heading($field);
80
        $self->{'auth_type'},   $self->{'thesaurus'},
81
        $self->{'search_form'}, $self->{'display_form'},
82
        $self->{'match_type'}
83
    ) = $marc_handler->parse_heading($field);
81
84
82
    bless $self, $class;
85
    bless $self, $class;
83
    return $self;
86
    return $self;
84
}
87
}
85
88
89
=head2 auth_type
90
91
  my $auth_type = $heading->auth_type();
92
93
Return the auth_type of the heading.
94
95
=cut
96
97
sub auth_type {
98
    my $self = shift;
99
    return $self->{'auth_type'};
100
}
101
102
=head2 field
103
104
  my $field = $heading->field();
105
106
Return the MARC::Field the heading is based on.
107
108
=cut
109
110
sub field {
111
    my $self = shift;
112
    return $self->{'field'};
113
}
114
86
=head2 display_form
115
=head2 display_form
87
116
88
  my $display = $heading->display_form();
117
  my $display = $heading->display_form();
Lines 96-118 sub display_form { Link Here
96
    return $self->{'display_form'};
125
    return $self->{'display_form'};
97
}
126
}
98
127
128
=head2 search_form
129
130
  my $search_form = $heading->search_form();
131
132
Return the "canonical" search form of the heading.
133
134
=cut
135
136
sub search_form {
137
    my $self = shift;
138
    return $self->{'search_form'};
139
}
140
99
=head2 authorities
141
=head2 authorities
100
142
101
  my $authorities = $heading->authorities;
143
  my $authorities = $heading->authorities([$skipmetadata]);
102
144
103
Return a list of authority records for this 
145
Return a list of authority records for this 
104
heading.
146
heading. If passed a true value for $skipmetadata,
147
SearchAuthorities will return only authids.
105
148
106
=cut
149
=cut
107
150
108
sub authorities {
151
sub authorities {
109
    my $self = shift;
152
    my $self         = shift;
110
    my $query = qq(Match-heading,do-not-truncate,ext="$self->{'search_form'}");
153
    my $skipmetadata = shift;
111
    $query .= $self->_query_limiters();
154
    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;
155
    return $results;
117
}
156
}
118
157
Lines 127-162 that are a preferred form of the heading. Link Here
127
166
128
sub preferred_authorities {
167
sub preferred_authorities {
129
    my $self = shift;
168
    my $self = shift;
130
    my $query = "Match-heading-see-from,do-not-truncate,ext='$self->{'search_form'}'";
169
    my $skipmetadata = shift || undef;
131
    $query .= $self->_query_limiters();
170
    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;
171
    return $results;
137
}
172
}
138
173
139
=head1 INTERNAL METHODS
174
=head1 INTERNAL METHODS
140
175
141
=head2 _query_limiters
176
=head2 _search
142
177
143
=cut
178
=cut
144
179
145
sub _query_limiters {
180
sub _search {
146
    my $self = shift;
181
    my $self         = shift;
147
182
    my $index        = shift || undef;
148
    my $limiters = " AND at='$self->{'auth_type'}'";
183
    my $skipmetadata = shift || undef;
149
    if ($self->{'subject_added_entry'}) {
184
    my @marclist;
150
        $limiters .= " AND Heading-use-subject-added-entry=a"; # FIXME -- is this properly in C4::Heading::MARC21?
185
    my @and_or;
151
        $limiters .= " AND Subject-heading-thesaurus=$self->{'thesaurus'}";
186
    my @excluding = [];
152
    }
187
    my @operator;
153
    if ($self->{'series_added_entry'}) {
188
    my @value;
154
        $limiters .= " AND Heading-use-series-added-entry=a"; # FIXME -- is this properly in C4::Heading::MARC21?
189
155
    }
190
    if ($index) {
156
    if (not $self->{'subject_added_entry'} and not $self->{'series_added_entry'}) {
191
        push @marclist, $index;
157
        $limiters .= " AND Heading-use-main-or-added-entry=a" # FIXME -- is this properly in C4::Heading::MARC21?
192
        push @and_or,   'and';
193
        push @operator, $self->{'match_type'};
194
        push @value,    $self->{'search_form'};
158
    }
195
    }
159
    return $limiters;
196
197
    #    if ($self->{'thesaurus'}) {
198
    #        push @marclist, 'thesaurus';
199
    #        push @and_or, 'and';
200
    #        push @excluding, '';
201
    #        push @operator, 'is';
202
    #        push @value, $self->{'thesaurus'};
203
    #    }
204
    require C4::AuthoritiesMarc;
205
    return C4::AuthoritiesMarc::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 (+121 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
Function to be called by subclasses to handle authority record limits.
90
91
=cut
92
93
sub _handle_auth_limit {
94
    my $self   = shift;
95
    my $authid = shift;
96
97
    if ( defined $self->{'auths_to_link'} && defined $authid && !grep { $_ == $authid }
98
        @{ $self->{'auths_to_link'} } )
99
    {
100
        undef $authid;
101
    }
102
    return $authid;
103
}
104
105
=head2 EXPORT
106
107
None by default.
108
109
=head1 SEE ALSO
110
111
C4::Linker::Default
112
113
=head1 AUTHOR
114
115
Jared Camins-Esakov, C & P Bibliography Services, E<lt>jcamins@cpbibliography.comE<gt>
116
117
=cut
118
119
1;
120
121
__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 70-78 This module provides searching functions for Koha's bibliographic databases Link Here
70
  &NZgetRecords
70
  &NZgetRecords
71
  &AddSearchHistory
71
  &AddSearchHistory
72
  &GetDistinctValues
72
  &GetDistinctValues
73
  &BiblioAddAuthorities
74
);
73
);
75
#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)
76
74
77
# make all your functions, whether exported or not;
75
# make all your functions, whether exported or not;
78
76
Lines 2656-2760 sub z3950_search_args { Link Here
2656
    return $array;
2654
    return $array;
2657
}
2655
}
2658
2656
2659
=head2 BiblioAddAuthorities
2660
2661
( $countlinked, $countcreated ) = BiblioAddAuthorities($record, $frameworkcode);
2662
2663
this function finds the authorities linked to the biblio
2664
    * search in the authority DB for the same authid (in $9 of the biblio)
2665
    * search in the authority DB for the same 001 (in $3 of the biblio in UNIMARC)
2666
    * search in the authority DB for the same values (exactly) (in all subfields of the biblio)
2667
OR adds a new authority record
2668
2669
=over 2
2670
2671
=item C<input arg:>
2672
2673
    * $record is the MARC record in question (marc blob)
2674
    * $frameworkcode is the bibliographic framework to use (if it is "" it uses the default framework)
2675
2676
=item C<Output arg:>
2677
2678
    * $countlinked is the number of authorities records that are linked to this authority
2679
    * $countcreated
2680
2681
=item C<BUGS>
2682
    * 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)
2683
2684
=back
2685
2686
=cut
2687
2688
2689
sub BiblioAddAuthorities{
2690
  my ( $record, $frameworkcode ) = @_;
2691
  my $dbh=C4::Context->dbh;
2692
  my $query=$dbh->prepare(qq|
2693
SELECT authtypecode,tagfield
2694
FROM marc_subfield_structure
2695
WHERE frameworkcode=?
2696
AND (authtypecode IS NOT NULL AND authtypecode<>\"\")|);
2697
# SELECT authtypecode,tagfield
2698
# FROM marc_subfield_structure
2699
# WHERE frameworkcode=?
2700
# AND (authtypecode IS NOT NULL OR authtypecode<>\"\")|);
2701
  $query->execute($frameworkcode);
2702
  my ($countcreated,$countlinked);
2703
  while (my $data=$query->fetchrow_hashref){
2704
    foreach my $field ($record->field($data->{tagfield})){
2705
      next if ($field->subfield('3')||$field->subfield('9'));
2706
      # No authorities id in the tag.
2707
      # Search if there is any authorities to link to.
2708
      my $query='at='.$data->{authtypecode}.' ';
2709
      map {$query.= ' and he,ext="'.$_->[1].'"' if ($_->[0]=~/[A-z]/)}  $field->subfields();
2710
      my ($error, $results, $total_hits)=SimpleSearch( $query, undef, undef, [ "authorityserver" ] );
2711
    # there is only 1 result
2712
          if ( $error ) {
2713
        warn "BIBLIOADDSAUTHORITIES: $error";
2714
            return (0,0) ;
2715
          }
2716
      if ( @{$results} == 1 ) {
2717
        my $marcrecord = MARC::File::USMARC::decode($results->[0]);
2718
        $field->add_subfields('9'=>$marcrecord->field('001')->data);
2719
        $countlinked++;
2720
      } elsif ( @{$results} > 1 ) {
2721
   #More than One result
2722
   #This can comes out of a lack of a subfield.
2723
#         my $marcrecord = MARC::File::USMARC::decode($results->[0]);
2724
#         $record->field($data->{tagfield})->add_subfields('9'=>$marcrecord->field('001')->data);
2725
  $countlinked++;
2726
      } else {
2727
  #There are no results, build authority record, add it to Authorities, get authid and add it to 9
2728
  ###NOTICE : This is only valid if a subfield is linked to one and only one authtypecode
2729
  ###NOTICE : This can be a problem. We should also look into other types and rejected forms.
2730
         my $authtypedata=C4::AuthoritiesMarc::GetAuthType($data->{authtypecode});
2731
         next unless $authtypedata;
2732
         my $marcrecordauth=MARC::Record->new();
2733
         my $authfield=MARC::Field->new($authtypedata->{auth_tag_to_report},'','',"a"=>"".$field->subfield('a'));
2734
         map { $authfield->add_subfields($_->[0]=>$_->[1]) if ($_->[0]=~/[A-z]/ && $_->[0] ne "a" )}  $field->subfields();
2735
         $marcrecordauth->insert_fields_ordered($authfield);
2736
2737
         # bug 2317: ensure new authority knows it's using UTF-8; currently
2738
         # only need to do this for MARC21, as MARC::Record->as_xml_record() handles
2739
         # automatically for UNIMARC (by not transcoding)
2740
         # FIXME: AddAuthority() instead should simply explicitly require that the MARC::Record
2741
         # use UTF-8, but as of 2008-08-05, did not want to introduce that kind
2742
         # of change to a core API just before the 3.0 release.
2743
         if (C4::Context->preference('marcflavour') eq 'MARC21') {
2744
            SetMarcUnicodeFlag($marcrecordauth, 'MARC21');
2745
         }
2746
2747
#          warn "AUTH RECORD ADDED : ".$marcrecordauth->as_formatted;
2748
2749
         my $authid=AddAuthority($marcrecordauth,'',$data->{authtypecode});
2750
         $countcreated++;
2751
         $field->add_subfields('9'=>$authid);
2752
      }
2753
    }
2754
  }
2755
  return ($countlinked,$countcreated);
2756
}
2757
2758
=head2 GetDistinctValues($field);
2657
=head2 GetDistinctValues($field);
2759
2658
2760
C<$field> is a reference to the fields array
2659
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 723-817 sub build_tabs { Link Here
723
    $template->param( BIG_LOOP => \@BIG_LOOP );
723
    $template->param( BIG_LOOP => \@BIG_LOOP );
724
}
724
}
725
725
726
#
727
# sub that tries to find authorities linked to the biblio
728
# the sub :
729
#   - search in the authority DB for the same authid (in $9 of the biblio)
730
#   - search in the authority DB for the same 001 (in $3 of the biblio in UNIMARC)
731
#   - search in the authority DB for the same values (exactly) (in all subfields of the biblio)
732
# if the authority is found, the biblio is modified accordingly to be connected to the authority.
733
# if the authority is not found, it's added, and the biblio is then modified to be connected to the authority.
734
#
735
736
sub BiblioAddAuthorities{
737
  my ( $record, $frameworkcode ) = @_;
738
  my $dbh=C4::Context->dbh;
739
  my $query=$dbh->prepare(qq|
740
SELECT authtypecode,tagfield
741
FROM marc_subfield_structure 
742
WHERE frameworkcode=? 
743
AND (authtypecode IS NOT NULL AND authtypecode<>\"\")|);
744
# SELECT authtypecode,tagfield
745
# FROM marc_subfield_structure 
746
# WHERE frameworkcode=? 
747
# AND (authtypecode IS NOT NULL OR authtypecode<>\"\")|);
748
  $query->execute($frameworkcode);
749
  my ($countcreated,$countlinked);
750
  while (my $data=$query->fetchrow_hashref){
751
    foreach my $field ($record->field($data->{tagfield})){
752
      next if ($field->subfield('3') || $field->subfield('9'));
753
      # No authorities id in the tag.
754
      # Search if there is any authorities to link to.
755
      my $query='at='.$data->{authtypecode}.' ';
756
      map {$query.= ' and he,ext="'.$_->[1].'"' if ($_->[0]=~/[A-z]/)}  $field->subfields();
757
      my ($error, $results, $total_hits)=SimpleSearch( $query, undef, undef, [ "authorityserver" ] );
758
    # there is only 1 result 
759
	  if ( $error ) {
760
        warn "BIBLIOADDSAUTHORITIES: $error";
761
	    return (0,0) ;
762
	  }
763
      if ( @{$results} == 1) {
764
        my $marcrecord = MARC::File::USMARC::decode($results->[0]);
765
        $field->add_subfields('9'=>$marcrecord->field('001')->data);
766
        $countlinked++;
767
      } elsif (@{$results} > 1) {
768
   #More than One result 
769
   #This can comes out of a lack of a subfield.
770
#         my $marcrecord = MARC::File::USMARC::decode($results->[0]);
771
#         $record->field($data->{tagfield})->add_subfields('9'=>$marcrecord->field('001')->data);
772
        $countlinked++;
773
      } else {
774
  #There are no results, build authority record, add it to Authorities, get authid and add it to 9
775
  ###NOTICE : This is only valid if a subfield is linked to one and only one authtypecode     
776
  ###NOTICE : This can be a problem. We should also look into other types and rejected forms.
777
         my $authtypedata=GetAuthType($data->{authtypecode});
778
         next unless $authtypedata;
779
         my $marcrecordauth=MARC::Record->new();
780
		if (C4::Context->preference('marcflavour') eq 'MARC21') {
781
			$marcrecordauth->leader('     nz  a22     o  4500');
782
			SetMarcUnicodeFlag($marcrecordauth, 'MARC21');
783
			}
784
         my $authfield=MARC::Field->new($authtypedata->{auth_tag_to_report},'','',"a"=>"".$field->subfield('a'));
785
         map { $authfield->add_subfields($_->[0]=>$_->[1]) if ($_->[0]=~/[A-z]/ && $_->[0] ne "a" )}  $field->subfields();
786
         $marcrecordauth->insert_fields_ordered($authfield);
787
788
         # bug 2317: ensure new authority knows it's using UTF-8; currently
789
         # only need to do this for MARC21, as MARC::Record->as_xml_record() handles
790
         # automatically for UNIMARC (by not transcoding)
791
         # FIXME: AddAuthority() instead should simply explicitly require that the MARC::Record
792
         # use UTF-8, but as of 2008-08-05, did not want to introduce that kind
793
         # of change to a core API just before the 3.0 release.
794
795
				if (C4::Context->preference('marcflavour') eq 'MARC21') {
796
					$marcrecordauth->insert_fields_ordered(MARC::Field->new('667','','','a'=>"Machine generated authority record."));
797
					my $cite = $record->author() . ", " .  $record->title_proper() . ", " . $record->publication_date() . " "; 
798
					$cite =~ s/^[\s\,]*//;
799
					$cite =~ s/[\s\,]*$//;
800
					$cite = "Work cat.: (" . C4::Context->preference('MARCOrgCode') . ")". $record->subfield('999','c') . ": " . $cite;
801
					$marcrecordauth->insert_fields_ordered(MARC::Field->new('670','','','a'=>$cite));
802
				}
803
804
#          warn "AUTH RECORD ADDED : ".$marcrecordauth->as_formatted;
805
806
         my $authid=AddAuthority($marcrecordauth,'',$data->{authtypecode});
807
         $countcreated++;
808
         $field->add_subfields('9'=>$authid);
809
      }
810
    }  
811
  }
812
  return ($countlinked,$countcreated);
813
}
814
815
# ========================
726
# ========================
816
#          MAIN
727
#          MAIN
817
#=========================
728
#=========================
Lines 944-950 if ( $op eq "addbiblio" ) { Link Here
944
        my $oldbibnum;
855
        my $oldbibnum;
945
        my $oldbibitemnum;
856
        my $oldbibitemnum;
946
        if (C4::Context->preference("BiblioAddsAuthorities")){
857
        if (C4::Context->preference("BiblioAddsAuthorities")){
947
          my ($countlinked,$countcreated)=BiblioAddAuthorities($record,$frameworkcode);
858
          my ($countlinked,$countcreated)=BiblioAutoLink($record,$frameworkcode);
948
        } 
859
        } 
949
        if ( $is_a_modif ) {
860
        if ( $is_a_modif ) {
950
            ModBiblioframework( $biblionumber, $frameworkcode ); 
861
            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,Match-heading:w,Match-heading: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,Match-heading:w,Match-heading: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,Match-heading-see-from:w,Match-heading-see-from: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,Match-heading:w,Match-heading: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,Match-heading:w,Match-heading: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,Match-heading-see-from:w,Match-heading-see-from: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,Match-heading:w,Match-heading: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,Match-heading:w,Match-heading: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,Match-heading-see-from:w,Match-heading-see-from: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,Match-heading:w,Match-heading: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,Match-heading:w,Match-heading: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,Match-heading-see-from:w,Match-heading-see-from: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,Match-heading:w,Match-heading: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,Match-heading:w,Match-heading: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,Match-heading-see-from:w,Match-heading-see-from: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,Match-heading:w,Match-heading: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,Match-heading:w,Match-heading: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,Match-heading-see-from:w,Match-heading-see-from: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,Match-heading:w,Match-heading: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,Match-heading:w,Match-heading: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,Match-heading-see-from:w,Match-heading-see-from: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,Match-heading:w,Match-heading: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,Match-heading:w,Match-heading: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,Match-heading-see-from:w,Match-heading-see-from: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,Match-heading:w,Match-heading: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,Match-heading:w,Match-heading: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,Match-heading-see-from:w,Match-heading-see-from: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,Match-heading:w,Match-heading: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,Match-heading:w,Match-heading: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,Match-heading-see-from:w,Match-heading-see-from: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,Match-heading:w,Match-heading: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,Match-heading-see-from:w,Match-heading-see-from: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,Match-heading:w,Match-heading: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,Match-heading:w,Match-heading: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,Match-heading-see-from:w,Match-heading-see-from: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/atomicupdate/bug_7284_authority_linking_pt2 (+9 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('CatalogModuleRelink',0,'If OFF the linker will never replace the authids that are set in the cataloging module.',NULL,'YesNo');"
8
);
9
print "Upgrade done (Configured bug 7284, added the )\n";
(-)a/installer/data/mysql/sysprefs.sql (+6 lines)
Lines 329-331 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES Link Here
329
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');
329
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('OpacShowRecentComments',0,'If ON a link to recent comments will appear in the OPAC masthead',NULL,'YesNo');
330
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,options,explanation,type) VALUES ('AllowItemsOnHoldCheckout',0,'Do not generate RESERVE_WAITING and RESERVED warning when checking out items reserved to someone else. This allows self checkouts for those items.','','YesNo');
331
INSERT INTO `systempreferences` (variable,value,options,explanation,type) VALUES ('AllowItemsOnHoldCheckout',0,'Do not generate RESERVE_WAITING and RESERVED warning when checking out items reserved to someone else. This allows self checkouts for those items.','','YesNo');
332
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('AutoCreateAuthorities',0,'Automatically create authorities that do not exist when cataloging records.',NULL,'YesNo');
333
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('LinkerModule','Default','Chooses which linker module to use (see documentation).','Default|FirstMatch|LastMatch','Choice');
334
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('LinkerOptions','','A pipe-separated list of options for the linker.','','free');
335
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');
336
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');
337
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('CatalogModuleRelink',0,'If OFF the linker will never replace the authids that are set in the cataloging module.',NULL,'YesNo');
(-)a/installer/data/mysql/updatedatabase.pl (+24 lines)
Lines 4607-4612 if (C4::Context->preference("Version") < TransformToNum($DBversion)) { Link Here
4607
    SetVersion ($DBversion);
4607
    SetVersion ($DBversion);
4608
}
4608
}
4609
4609
4610
$DBversion = "3.06.XX.XXX";
4611
if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
4612
    $dbh->do(
4613
    "INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('LinkerModule','Default','Chooses which linker module to use (see documentation).','Default|FirstMatchLastMatch','Choice');"
4614
    );
4615
    $dbh->do(
4616
    "INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('LinkerOptions','','A pipe-separated list of options for the linker.','','free');"
4617
    );
4618
    $dbh->do(
4619
    "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');"
4620
    );
4621
    $dbh->do(
4622
    "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');"
4623
    );
4624
    $dbh->do(
4625
    "INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('AutoCreateAuthorities',0,'Automatically create authorities that do not exist when cataloging records.',NULL,'YesNo');"
4626
    );
4627
    $dbh->do(
4628
    "INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('CatalogModuleRelink',0,'If OFF the linker will never replace the authids that are set in the cataloging module.',NULL,'YesNo');"
4629
    );
4630
    print "Upgrade to $DBversion done (Enhancement 7284, improved authority matching, see http://wiki.koha-community.org/wiki/Bug7284_authority_matching_improvement wiki page for configuration update needed)\n";
4631
    SetVersion($DBversion);
4632
}
4633
4610
=head1 FUNCTIONS
4634
=head1 FUNCTIONS
4611
4635
4612
=head2 DropAllForeignKeys($table)
4636
=head2 DropAllForeignKeys($table)
(-)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 / +73 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.
68
        -
69
            - pref: CatalogModuleRelink
70
              default: no
71
              choices:
72
                  yes: Do
73
                  no: "Do not"
74
            - automatically relink headings that have previously been linked when saving records in the cataloging module.
(-)a/misc/link_bibs_to_authorities.pl (-52 / +215 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
use Time::HiRes qw/time/;
20
use POSIX qw/strftime ceil/;
21
22
sub usage {
23
    pod2usage( -verbose => 2 );
24
    exit;
25
}
15
26
16
$| = 1;
27
$| = 1;
17
28
18
# command-line parameters
29
# command-line parameters
19
my $verbose   = 0;
30
my $verbose     = 0;
20
my $test_only = 0;
31
my $link_report = 0;
21
my $want_help = 0;
32
my $test_only   = 0;
33
my $want_help   = 0;
34
my $auth_limit;
35
my $bib_limit;
36
my $commit = 100;
22
37
23
my $result = GetOptions(
38
my $result = GetOptions(
24
    'verbose'       => \$verbose,
39
    'v|verbose'      => \$verbose,
25
    'test'          => \$test_only,
40
    't|test'         => \$test_only,
26
    'h|help'        => \$want_help
41
    'l|link-report'  => \$link_report,
42
    'a|auth-limit=s' => \$auth_limit,
43
    'b|bib-limit=s'  => \$bib_limit,
44
    'c|commit=i'     => \$commit,
45
    'h|help'         => \$want_help
27
);
46
);
28
47
29
if (not $result or $want_help) {
48
binmode( STDOUT, ":utf8" );
30
    print_usage();
49
31
    exit 0;
50
if ( not $result or $want_help ) {
51
    usage();
52
}
53
54
my $linker_module =
55
  "C4::Linker::" . ( C4::Context->preference("LinkerModule") || 'Default' );
56
eval { eval "require $linker_module"; };
57
if ($@) {
58
    $linker_module = 'C4::Linker::Default';
59
    eval "require $linker_module";
32
}
60
}
61
if ($@) {
62
    die "Unable to load linker module. Aborting.";
63
}
64
65
my $linker = $linker_module->new(
66
    {
67
        'auth_limit' => $auth_limit,
68
        'options'    => C4::Context->preference("LinkerOptions")
69
    }
70
);
33
71
34
my $num_bibs_processed = 0;
72
my $num_bibs_processed = 0;
35
my $num_bibs_modified = 0;
73
my $num_bibs_modified  = 0;
36
my $num_bad_bibs = 0;
74
my $num_bad_bibs       = 0;
75
my %unlinked_headings;
76
my %linked_headings;
77
my %fuzzy_headings;
37
my $dbh = C4::Context->dbh;
78
my $dbh = C4::Context->dbh;
38
$dbh->{AutoCommit} = 0;
79
$dbh->{AutoCommit} = 0;
39
process_bibs();
80
process_bibs( $linker, $bib_limit, $auth_limit, $commit );
40
$dbh->commit();
81
$dbh->commit();
41
82
42
exit 0;
83
exit 0;
43
84
44
sub process_bibs {
85
sub process_bibs {
45
    my $sql = "SELECT biblionumber FROM biblio ORDER BY biblionumber ASC";
86
    my ( $linker, $bib_limit, $auth_limit, $commit ) = @_;
87
    my $bib_where = '';
88
    my $starttime = time();
89
    if ($bib_limit) {
90
        $bib_where = "WHERE $bib_limit";
91
    }
92
    my $sql =
93
      "SELECT biblionumber FROM biblio $bib_where ORDER BY biblionumber ASC";
46
    my $sth = $dbh->prepare($sql);
94
    my $sth = $dbh->prepare($sql);
47
    $sth->execute();
95
    $sth->execute();
48
    while (my ($biblionumber) = $sth->fetchrow_array()) {
96
    while ( my ($biblionumber) = $sth->fetchrow_array() ) {
49
        $num_bibs_processed++;
97
        $num_bibs_processed++;
50
        process_bib($biblionumber);
98
        process_bib( $linker, $biblionumber );
51
99
52
        if (not $test_only and ($num_bibs_processed % 100) == 0) {
100
        if ( not $test_only and ( $num_bibs_processed % $commit ) == 0 ) {
53
            print_progress_and_commit($num_bibs_processed);
101
            print_progress_and_commit($num_bibs_processed);
54
        }
102
        }
55
    }
103
    }
56
104
57
    if (not $test_only) {
105
    if ( not $test_only ) {
58
        $dbh->commit;
106
        $dbh->commit;
59
    }
107
    }
60
108
61
    print <<_SUMMARY_;
109
    my $headings_linked   = 0;
110
    my $headings_unlinked = 0;
111
    my $headings_fuzzy    = 0;
112
    for ( values %linked_headings )   { $headings_linked   += $_; }
113
    for ( values %unlinked_headings ) { $headings_unlinked += $_; }
114
    for ( values %fuzzy_headings )    { $headings_fuzzy    += $_; }
115
116
    my $endtime = time();
117
    my $totaltime = ceil (($endtime - $starttime) * 1000);
118
    $starttime = strftime('%D %T', localtime($starttime));
119
    $endtime = strftime('%D %T', localtime($endtime));
120
121
    my $summary = <<_SUMMARY_;
62
122
63
Bib authority heading linking report
123
Bib authority heading linking report
64
------------------------------------
124
=======================================================
65
Number of bibs checked:       $num_bibs_processed
125
Linker module:                          $linker_module
66
Number of bibs modified:      $num_bibs_modified
126
Run started at:                         $starttime
67
Number of bibs with errors:   $num_bad_bibs
127
Run ended at:                           $endtime
128
Total run time:                         $totaltime ms
129
Number of bibs checked:                 $num_bibs_processed
130
Number of bibs modified:                $num_bibs_modified
131
Number of bibs with errors:             $num_bad_bibs
132
Number of headings linked:              $headings_linked
133
Number of headings unlinked:            $headings_unlinked
134
Number of headings fuzzily linked:      $headings_fuzzy
68
_SUMMARY_
135
_SUMMARY_
136
    $summary .= "\n****  Ran in test mode only  ****\n" if $test_only;
137
    print $summary;
138
139
    if ($link_report) {
140
        my @keys;
141
        print <<_LINKED_HEADER_;
142
143
Linked headings (from most frequent to least):
144
-------------------------------------------------------
145
146
_LINKED_HEADER_
147
148
        @keys = sort {
149
            $linked_headings{$b} <=> $linked_headings{$a} or "\L$a" cmp "\L$b"
150
        } keys %linked_headings;
151
        foreach my $key (@keys) {
152
            print "$key:\t" . $linked_headings{$key} . " occurrences\n";
153
        }
154
155
        print <<_UNLINKED_HEADER_;
156
157
Unlinked headings (from most frequent to least):
158
-------------------------------------------------------
159
160
_UNLINKED_HEADER_
161
162
        @keys = sort {
163
            $unlinked_headings{$b} <=> $unlinked_headings{$a}
164
              or "\L$a" cmp "\L$b"
165
        } keys %unlinked_headings;
166
        foreach my $key (@keys) {
167
            print "$key:\t" . $unlinked_headings{$key} . " occurrences\n";
168
        }
169
170
        print <<_FUZZY_HEADER_;
171
172
Fuzzily-matched headings (from most frequent to least):
173
-------------------------------------------------------
174
175
_FUZZY_HEADER_
176
177
        @keys = sort {
178
            $fuzzy_headings{$b} <=> $fuzzy_headings{$a} or "\L$a" cmp "\L$b"
179
        } keys %fuzzy_headings;
180
        foreach my $key (@keys) {
181
            print "$key:\t" . $fuzzy_headings{$key} . " occurrences\n";
182
        }
183
        print $summary;
184
    }
69
}
185
}
70
186
71
sub process_bib {
187
sub process_bib {
188
    my $linker       = shift;
72
    my $biblionumber = shift;
189
    my $biblionumber = shift;
73
190
74
    my $bib = GetMarcBiblio($biblionumber);
191
    my $bib = GetMarcBiblio($biblionumber);
75
    unless (defined $bib) {
192
    unless ( defined $bib ) {
76
        print "\nCould not retrieve bib $biblionumber from the database - record is corrupt.\n";
193
        print
194
"\nCould not retrieve bib $biblionumber from the database - record is corrupt.\n";
77
        $num_bad_bibs++;
195
        $num_bad_bibs++;
78
        return;
196
        return;
79
    }
197
    }
80
198
81
    my $headings_changed = LinkBibHeadingsToAuthorities($bib);
199
    my ( $headings_changed, $results ) =
200
      LinkBibHeadingsToAuthorities( $linker, $bib,
201
        GetFrameworkCode($biblionumber) );
202
    foreach my $key ( keys %{ $results->{'unlinked'} } ) {
203
        $unlinked_headings{$key} += $results->{'unlinked'}->{$key};
204
    }
205
    foreach my $key ( keys %{ $results->{'linked'} } ) {
206
        $linked_headings{$key} += $results->{'linked'}->{$key};
207
    }
208
    foreach my $key ( keys %{ $results->{'fuzzy'} } ) {
209
        $fuzzy_headings{$key} += $results->{'fuzzy'}->{$key};
210
    }
82
211
83
    if ($headings_changed) {   
212
    if ($headings_changed) {
84
        if ($verbose) {
213
        if ($verbose) {
85
            my $title = substr($bib->title, 0, 20);
214
            my $title = substr( $bib->title, 0, 20 );
86
            print "Bib $biblionumber ($title): $headings_changed headings changed\n";
215
            print
216
"Bib $biblionumber ($title): $headings_changed headings changed\n";
87
        }
217
        }
88
        if (not $test_only) {
218
        if ( not $test_only ) {
89
            # delete any item tags
219
            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++;
220
            $num_bibs_modified++;
96
        }
221
        }
97
    }
222
    }
Lines 103-122 sub print_progress_and_commit { Link Here
103
    print "... processed $recs records\n";
228
    print "... processed $recs records\n";
104
}
229
}
105
230
106
sub print_usage {
231
=head1 NAME
107
    print <<_USAGE_;
232
108
$0: link headings in bib records to authorities.
233
link_bibs_to_authorities.pl
109
234
110
This batch job checks each bib record in the Koha
235
=head1 SYNOPSIS
111
database and attempts to link each of its headings
236
112
to the matching authority record.
237
  link_bibs_to_authorities.pl
113
238
  link_bibs_to_authorities.pl -v
114
Parameters:
239
  link_bibs_to_authorities.pl -l
115
    --verbose               print the number of headings changed
240
  link_bibs_to_authorities.pl --commit=1000
116
                            for each bib
241
  link_bibs_to_authorities.pl --auth-limit=STRING
117
    --test                  only test the authority linking
242
  link_bibs_to_authorities.pl --bib-limit=STRING
118
                            and report the results; do not
243
119
                            change the bib records.
244
=head1 DESCRIPTION
120
    --help or -h            show this message.
245
121
_USAGE_
246
This batch job checks each bib record in the Koha database and attempts to link
122
}
247
each of its headings to the matching authority record.
248
249
=over 8
250
251
=item B<--help>
252
253
Prints this help
254
255
=item B<-v|--verbose>
256
257
Provide verbose log information (print the number of headings changed for each
258
bib record).
259
260
=item B<-l|--link-report>
261
262
Provide a report of all the headings that were processed: which were matched,
263
which were not, etc.
264
265
=item B<--auth-limit=S>
266
267
Only process those headings which match an authority record that matches the
268
user-specified WHERE clause.
269
270
=item B<--bib-limit=S>
271
272
Only process those bib records that match the user-specified WHERE clause.
273
274
=item B<--commit=N>
275
276
Commit the results to the database after every N records are processed.
277
278
=item B<--test>
279
280
Only test the authority linking and report the results; do not change the bib
281
records.
282
283
=back
284
285
=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