package C4::Ris; # Original script : ## marc2ris: converts MARC21 and UNIMARC datasets to RIS format ## See comments below for compliance with other MARC dialects ## ## usage: perl marc2ris < infile.marc > outfile.ris ## ## Dependencies: perl 5.6.0 or later ## MARC::Record ## MARC::Charset ## ## markus@mhoenicka.de 2002-11-16 ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## Some background about MARC as understood by this script ## The default input format used in this script is MARC21, which ## superseded USMARC and CANMARC. The specification can be found at: ## http://lcweb.loc.gov/marc/ ## UNIMARC follows the specification at: ## http://www.ifla.org/VI/3/p1996-1/sec-uni.htm ## UKMARC support is a bit shaky because there is no specification available ## for free. The wisdom used in this script was taken from a PDF document ## comparing UKMARC to MARC21 found at: ## www.bl.uk/services/bibliographic/marcchange.pdf # Modified 2008 by BibLibre for Koha # Modified 2011 by Catalyst # Modified 2011 by Equinox Software, Inc. # Modified 2016 by Universidad de El Salvador # # This file is part of Koha. # # Koha is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # Koha is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Koha; if not, see . # # use Modern::Perl; use List::MoreUtils qw( uniq ); use Encode; use vars qw(@ISA @EXPORT); use Koha::SimpleMARC qw( read_field ); @ISA = qw(Exporter); # only export API methods @EXPORT = qw( marc2ris ); our $marcprint = 0; # Debug flag; =head1 marc2bibtex - Convert from UNIMARC to RIS my ($ris) = marc2ris($record); Returns a RIS scalar C<$record> - a MARC::Record object =cut sub marc2ris { my ($record) = @_; my $marcflavour = C4::Context->preference("marcflavour"); my $intype = lc($marcflavour); # Let's redirect stdout open my $oldout, qw{>&}, "STDOUT"; my $outvar; close STDOUT; open STDOUT, '>:encoding(utf8)', \$outvar; ## First we should check the character encoding. This may be ## MARC-8 or UTF-8. The former is indicated by a blank, the latter ## by 'a' at position 09 (zero-based) of the leader my $leader = $record->leader(); if ( $intype eq "marc21" ) { if ( $leader =~ /^.{9}a/ ) { print "---\r\nUTF-8 data\r\n" if $marcprint; } else { print "---\r\nMARC-8 data\r\n" if $marcprint; } } ## else: other MARC formats do not specify the character encoding ## we assume it's *not* UTF-8 my $ris_additional_fields = C4::Context->yaml_preference('RisExportAdditionalFields'); ## start RIS dataset if ( $ris_additional_fields && $ris_additional_fields->{TY} ) { my ( $f, $sf ) = split( /\$/, $ris_additional_fields->{TY} ); my ($type) = read_field( { record => $record, field => $f, subfield => $sf, field_numbers => [1] } ); if ($type) { print "TY - $type\r\n"; } else { &print_typetag($leader); } } else { &print_typetag($leader); } ## retrieve all author fields and collect them in a list my @author_fields; if ( $intype eq "unimarc" ) { ## Fields 700, 701, and 702 can contain author names @author_fields = ( $record->field('700'), $record->field('701'), $record->field('702') ); } else { ## marc21, ukmarc ## Field 100 sometimes carries main author ## Field(s) 700 carry added entries - personal names @author_fields = ( $record->field('100'), $record->field('700') ); } ## loop over all author fields foreach my $field (@author_fields) { if ( length($field) ) { my $author = &get_author($field); print "AU - ", $author, "\r\n"; } } # ToDo: should we specify anonymous as author if we didn't find # one? or use one of the corporate/meeting names below? ## add corporate names or meeting names as editors ?? my @editor_fields; if ( $intype eq "unimarc" ) { ## Fields 710, 711, and 712 can carry corporate names ## Field(s) 720, 721, 722, 730 have additional candidates @editor_fields = ( $record->field('710'), $record->field('711'), $record->field('712'), $record->field('720'), $record->field('721'), $record->field('722'), $record->field('730') ); } else { ## marc21, ukmarc ## Fields 110 and 111 carry the main entries - corporate name and ## meeting name, respectively ## Field(s) 710, 711 carry added entries - personal names @editor_fields = ( $record->field('110'), $record->field('111'), $record->field('710'), $record->field('711') ); } ## loop over all editor fields foreach my $field (@editor_fields) { if ( length($field) ) { my $editor = &get_editor($field); print "ED - ", $editor, "\r\n"; } } ## get info from the title field if ( $intype eq "unimarc" ) { &print_title( $record->field('200') ); } else { ## marc21, ukmarc &print_title( $record->field('245') ); } ## series title if ( $intype eq "unimarc" ) { &print_stitle( $record->field('225') ); } else { ## marc21, ukmarc &print_stitle( $record->field('490') ); } ## ISBN/ISSN if ( $intype eq "unimarc" ) { &print_isbn( $record->field('010') ); &print_issn( $record->field('011') ); } elsif ( $intype eq "ukmarc" ) { &print_isbn( $record->field('021') ); ## this is just an assumption &print_issn( $record->field('022') ); } else { ## assume marc21 &print_isbn( $record->field('020') ); &print_issn( $record->field('022') ); } if ( $intype eq "marc21" ) { &print_loc_callno( $record->field('050') ); &print_dewey( $record->field('082') ); } ## else: unimarc, ukmarc do not seem to store call numbers? ## publication info if ( $intype eq "unimarc" ) { &print_pubinfo( $record->field('210') ); } else { ## marc21, ukmarc if ( $record->field('264') ) { &print_pubinfo( $record->field('264') ); } else { &print_pubinfo( $record->field('260') ); } } ## 6XX fields contain KW candidates. We add all of them to a my @field_list; if ( $intype eq "unimarc" ) { @field_list = ( '600', '601', '602', '604', '605', '606', '607', '608', '610', '615', '620', '660', '661', '670', '675', '676', '680', '686' ); } elsif ( $intype eq "ukmarc" ) { @field_list = ( '600', '610', '611', '630', '650', '651', '653', '655', '660', '661', '668', '690', '691', '692', '695' ); } else { ## assume marc21 @field_list = ( '600', '610', '611', '630', '650', '651', '653', '654', '655', '656', '657', '658' ); } my @kwpool; for my $f (@field_list) { my @fields = $record->field($f); push @kwpool, ( get_keywords( "$f", $record->field($f) ) ); } # Remove duplicate @kwpool = uniq @kwpool; for my $kw (@kwpool) { print "KW - ", $kw, "\r\n"; } ## 5XX have various candidates for notes and abstracts. We pool ## all notes-like stuff in one list. my @notepool; ## these fields have notes candidates if ( $intype eq "unimarc" ) { foreach ( '300', '301', '302', '303', '304', '305', '306', '307', '308', '310', '311', '312', '313', '314', '315', '316', '317', '318', '320', '321', '322', '323', '324', '325', '326', '327', '328', '332', '333', '336', '337', '345' ) { &pool_subx( \@notepool, $_, $record->field($_) ); } } elsif ( $intype eq "ukmarc" ) { foreach ( '500', '501', '502', '503', '504', '505', '506', '508', '514', '515', '516', '521', '524', '525', '528', '530', '531', '532', '533', '534', '535', '537', '538', '540', '541', '542', '544', '554', '555', '556', '557', '561', '563', '580', '583', '584', '586' ) { &pool_subx( \@notepool, $_, $record->field($_) ); } } else { ## assume marc21 foreach ( '500', '501', '502', '504', '505', '506', '507', '508', '510', '511', '513', '514', '515', '516', '518', '521', '522', '524', '525', '526', '530', '533', '534', '535' ) { &pool_subx( \@notepool, $_, $record->field($_) ); } } my $allnotes = join "; ", @notepool; if ( length($allnotes) > 0 ) { print "N1 - ", $allnotes, "\r\n"; } ## 320/520 have the abstract if ( $intype eq "unimarc" ) { &print_abstract( $record->field('320') ); } elsif ( $intype eq "ukmarc" ) { &print_abstract( $record->field('512'), $record->field('513') ); } else { ## assume marc21 &print_abstract( $record->field('520') ); } # 856u has the URI if ( $record->field('856') ) { print_uri( $record->field('856') ); } if ($ris_additional_fields) { foreach my $ris_tag ( keys %$ris_additional_fields ) { next if $ris_tag eq 'TY'; my @fields = ref( $ris_additional_fields->{$ris_tag} ) eq 'ARRAY' ? @{ $ris_additional_fields->{$ris_tag} } : $ris_additional_fields->{$ris_tag}; for my $tag (@fields) { my ( $f, $sf ) = split( /\$/, $tag ); my @values = read_field( { record => $record, field => $f, subfield => $sf } ); foreach my $v (@values) { print "$ris_tag - $v\r\n"; } } } } ## end RIS dataset print "ER - \r\n"; # Let's re-redirect stdout close STDOUT; open STDOUT, ">&", $oldout; return $outvar; } ##******************************************************************** ## print_typetag(): prints the first line of a RIS dataset including ## the preceding newline ## Argument: the leader of a MARC dataset ## Returns: the value at leader position 06 ##******************************************************************** sub print_typetag { my ($leader) = @_; ## the keys of typehash are the allowed values at position 06 ## of the leader of a MARC record, the values are the RIS types ## that might appropriately represent these types. my %ustypehash = ( "a" => "BOOK", "c" => "MUSIC", "d" => "MUSIC", "e" => "MAP", "f" => "MAP", "g" => "ADVS", "i" => "SOUND", "j" => "SOUND", "k" => "ART", "m" => "DATA", "o" => "GEN", "p" => "GEN", "r" => "ART", "t" => "MANSCPT", ); my %unitypehash = ( "a" => "BOOK", "b" => "MANSCPT", "c" => "MUSIC", "d" => "MUSIC", "e" => "MAP", "f" => "MAP", "g" => "ADVS", "i" => "SOUND", "j" => "SOUND", "k" => "ART", "l" => "ELEC", "m" => "GEN", "r" => "ART", ); ## The type of a MARC record is found at position 06 of the leader my $typeofrecord = defined($leader) && length $leader >= 6 ? substr( $leader, 6, 1 ) : undef; ## Pos 07 == Bibliographic level my $biblevel = defined($leader) && length $leader >= 7 ? substr( $leader, 7, 1 ) : ''; ## TODO: for books, field 008 positions 24-27 might have a few more ## hints my %typehash; my $marcflavour = C4::Context->preference("marcflavour"); my $intype = lc($marcflavour); if ( $intype eq "unimarc" ) { %typehash = %unitypehash; } else { %typehash = %ustypehash; } if ( !defined $typeofrecord || !exists $typehash{$typeofrecord} ) { print "TY - GEN\r\n"; ## most reasonable default warn("no type found - assume GEN") if $marcprint; } elsif ( $typeofrecord =~ "a" ) { if ( $biblevel eq 'a' ) { print "TY - GEN\r\n"; ## monographic component part } elsif ( $biblevel eq 'b' || $biblevel eq 's' ) { print "TY - SER\r\n"; ## serial or serial component part } elsif ( $biblevel eq 'm' ) { print "TY - $typehash{$typeofrecord}\r\n"; ## book } elsif ( $biblevel eq 'c' || $biblevel eq 'd' ) { print "TY - GEN\r\n"; ## collections, part of collections or made-up collections } elsif ( $biblevel eq 'i' ) { print "TY - DATA\r\n"; ## updating loose-leafe as Dataset } } else { print "TY - $typehash{$typeofrecord}\r\n"; } ## use $typeofrecord as the return value, just in case $typeofrecord; } ##******************************************************************** ## normalize_author(): normalizes an authorname ## Arguments: authorname subfield a ## authorname subfield b ## authorname subfield c ## name type if known: 0=direct order ## 1=only surname or full name in ## inverted order ## 3=family, clan, dynasty name ## Returns: the normalized authorname ##******************************************************************** sub normalize_author { my ( $rawauthora, $rawauthorb, $rawauthorc, $nametype ) = @_; if ( $nametype == 0 ) { # ToDo: convert every input to Last[,(F.|First)[ (M.|Middle)[,Suffix]]] warn("name >>$rawauthora<< in direct order - leave as is") if $marcprint; return $rawauthora; } elsif ( $nametype == 1 ) { ## start munging subfield a (the real name part) ## remove spaces after separators $rawauthora =~ s%([,.]+) *%$1%g; ## remove trailing separators after spaces $rawauthora =~ s% *[,;:/]*$%%; ## remove periods after a non-abbreviated name $rawauthora =~ s%(\w{2,})\.%$1%g; ## start munging subfield b (something like the suffix) ## remove trailing separators after spaces $rawauthorb =~ s% *[,;:/]*$%%; ## we currently ignore subfield c until someone complains if ( length($rawauthorb) > 0 ) { return join ", ", ( $rawauthora, $rawauthorb ); } else { return $rawauthora; } } elsif ( $nametype == 3 ) { return $rawauthora; } } ##******************************************************************** ## get_author(): gets authorname info from MARC fields 100, 700 ## Argument: field (100 or 700) ## Returns: an author string in the format found in the record ##******************************************************************** sub get_author { my ($authorfield) = @_; my ($indicator); ## the sequence of the name parts is encoded either in indicator ## 1 (marc21) or 2 (unimarc) my $marcflavour = C4::Context->preference("marcflavour"); my $intype = lc($marcflavour); if ( $intype eq "unimarc" ) { $indicator = 2; } else { ## assume marc21 $indicator = 1; } print ":Author(Ind$indicator): ", $authorfield->indicator("$indicator"), "\r\n" if $marcprint; print ":Author(\$a): ", $authorfield->subfield('a'), "\r\n" if $marcprint; print ":Author(\$b): ", $authorfield->subfield('b'), "\r\n" if $marcprint; print ":Author(\$c): ", $authorfield->subfield('c'), "\r\n" if $marcprint; print ":Author(\$h): ", $authorfield->subfield('h'), "\r\n" if $marcprint; if ( $intype eq "ukmarc" ) { my $authorname = $authorfield->subfield('a') . "," . $authorfield->subfield('h'); normalize_author( $authorname, $authorfield->subfield('b'), $authorfield->subfield('c'), $authorfield->indicator("$indicator") ); } else { normalize_author( $authorfield->subfield('a') // '', $authorfield->subfield('b') // '', $authorfield->subfield('c') // '', $authorfield->indicator("$indicator") ); } } ##******************************************************************** ## get_editor(): gets editor info from MARC fields 110, 111, 710, 711 ## Argument: field (110, 111, 710, or 711) ## Returns: an author string in the format found in the record ##******************************************************************** sub get_editor { my ($editorfield) = @_; if ( !$editorfield ) { return; } else { print "Editor(\$a): ", $editorfield->subfield('a'), "\r\n" if $marcprint; print "Editor(\$b): ", $editorfield->subfield('b'), "\r\n" if $marcprint; print "editor(\$c): ", $editorfield->subfield('c'), "\r\n" if $marcprint; return $editorfield->subfield('a'); } } ##******************************************************************** ## print_title(): gets info from MARC field 245 ## Arguments: field (245) ## Returns: ##******************************************************************** sub print_title { my ($titlefield) = @_; if ( !$titlefield ) { print "empty title field (245)\r\n" if $marcprint; warn("empty title field (245)") if $marcprint; } else { print "Title(\$a): ", $titlefield->subfield('a'), "\r\n" if $marcprint; print "Title(\$b): ", $titlefield->subfield('b'), "\r\n" if $marcprint; print "Title(\$c): ", $titlefield->subfield('c'), "\r\n" if $marcprint; ## The title is usually written in a very odd notation. The title ## proper ($a) often ends with a space followed by a separator like ## a slash or a colon. The subtitle ($b) doesn't start with a space ## so simple concatenation looks odd. We have to conditionally remove ## the separator and make sure there's a space between title and ## subtitle my $clean_title = $titlefield->subfield('a'); my $clean_subtitle = $titlefield->subfield('b'); $clean_subtitle ||= q{}; $clean_title =~ s% *[/:;.]$%%; $clean_subtitle =~ s%^ *(.*) *[/:;.]$%$1%; my $marcflavour = C4::Context->preference("marcflavour"); my $intype = lc($marcflavour); if ( length($clean_title) > 0 || ( length($clean_subtitle) > 0 && $intype ne "unimarc" ) ) { print "TI - ", $clean_title; ## subfield $b is relevant only for marc21/ukmarc if ( length($clean_subtitle) > 0 && $intype ne "unimarc" ) { print ": ", $clean_subtitle; } print "\r\n"; } ## The statement of responsibility is just this: horrors. There is ## no formal definition how authors, editors and the like should ## be written and designated. The field is free-form and resistant ## to all parsing efforts, so this information is lost on me } return; } ##******************************************************************** ## print_stitle(): prints info from series title field ## Arguments: field ## Returns: ##******************************************************************** sub print_stitle { my ($titlefield) = @_; if ( !$titlefield ) { print "empty series title field\r\n" if $marcprint; } else { print "Series title(\$a): ", $titlefield->subfield('a'), "\r\n" if $marcprint; my $clean_title = $titlefield->subfield('a'); $clean_title =~ s% *[/:;.]$%%; if ( length($clean_title) > 0 ) { print "T2 - ", $clean_title, "\r\n"; } my $marcflavour = C4::Context->preference("marcflavour"); my $intype = lc($marcflavour); if ( $intype eq "unimarc" ) { print "Series vol(\$v): ", $titlefield->subfield('v'), "\r\n" if $marcprint; if ( length( $titlefield->subfield('v') ) > 0 ) { print "VL - ", $titlefield->subfield('v'), "\r\n"; } } } return; } ##******************************************************************** ## print_isbn(): gets info from MARC field 020 ## Arguments: field (020) ##******************************************************************** sub print_isbn { my ($isbnfield) = @_; if ( !$isbnfield || length( $isbnfield->subfield('a') ) == 0 ) { print "no isbn found (020\$a)\r\n" if $marcprint; warn("no isbn found") if $marcprint; } else { if ( length( $isbnfield->subfield('a') ) < 10 ) { print "truncated isbn (020\$a)\r\n" if $marcprint; warn("truncated isbn") if $marcprint; } my $isbn = $isbnfield->subfield('a'); print "SN - ", $isbn, "\r\n"; } } ##******************************************************************** ## print_issn(): gets info from MARC field 022 ## Arguments: field (022) ##******************************************************************** sub print_issn { my ($issnfield) = @_; if ( !$issnfield || length( $issnfield->subfield('a') ) == 0 ) { print "no issn found (022\$a)\r\n" if $marcprint; warn("no issn found") if $marcprint; } else { if ( length( $issnfield->subfield('a') ) < 9 ) { print "truncated issn (022\$a)\r\n" if $marcprint; warn("truncated issn") if $marcprint; } my $issn = substr( $issnfield->subfield('a'), 0, 9 ); print "SN - ", $issn, "\r\n"; } } ### # print_uri() prints info from 856 u ### sub print_uri { my @f856s = @_; foreach my $f856 (@f856s) { if ( my $uri = $f856->subfield('u') ) { print "UR - ", $uri, "\r\n"; } } } ##******************************************************************** ## print_loc_callno(): gets info from MARC field 050 ## Arguments: field (050) ##******************************************************************** sub print_loc_callno { my ($callnofield) = @_; if ( !$callnofield || length( $callnofield->subfield('a') ) == 0 ) { print "no LOC call number found (050\$a)\r\n" if $marcprint; warn("no LOC call number found") if $marcprint; } else { print "AV - ", $callnofield->subfield('a'), " ", $callnofield->subfield('b'), "\r\n"; } } ##******************************************************************** ## print_dewey(): gets info from MARC field 082 ## Arguments: field (082) ##******************************************************************** sub print_dewey { my ($deweyfield) = @_; if ( !$deweyfield || length( $deweyfield->subfield('a') ) == 0 ) { print "no Dewey number found (082\$a)\r\n" if $marcprint; warn("no Dewey number found") if $marcprint; } else { print "U1 - ", $deweyfield->subfield('a'), " ", $deweyfield->subfield('2'), "\r\n"; } } ##******************************************************************** ## print_pubinfo(): gets info from MARC field 260 ## Arguments: field (260) ##******************************************************************** sub print_pubinfo { my ($pubinfofield) = @_; if ( !$pubinfofield ) { print "no publication information found (260/264)\r\n" if $marcprint; warn("no publication information found") if $marcprint; } else { ## the following information is available in MARC21: ## $a place -> CY ## $b publisher -> PB ## $c date -> PY ## the corresponding subfields for UNIMARC: ## $a place -> CY ## $c publisher -> PB ## $d date -> PY ## all of them are repeatable. We pool all places into a ## comma-separated list in CY. We also pool all publishers ## into a comma-separated list in PB. We break the rule with ## the date field because this wouldn't make much sense. In ## this case, we use the first occurrence for PY, the second ## for Y2, and ignore the rest my @pubsubfields = $pubinfofield->subfields(); my @cities; my @publishers; my $pycounter = 0; my $pubsub_place; my $pubsub_publisher; my $pubsub_date; my $marcflavour = C4::Context->preference("marcflavour"); my $intype = lc($marcflavour); if ( $intype eq "unimarc" ) { $pubsub_place = "a"; $pubsub_publisher = "c"; $pubsub_date = "d"; } else { ## assume marc21 $pubsub_place = "a"; $pubsub_publisher = "b"; $pubsub_date = "c"; } ## loop over all subfield list entries for my $tuple (@pubsubfields) { ## each tuple consists of the subfield code and the value if ( @$tuple[0] eq $pubsub_place ) { ## strip any trailing crap $_ = @$tuple[1]; s% *[,;:/]$%%; ## pool all occurrences in a list push( @cities, $_ ); } elsif ( @$tuple[0] eq $pubsub_publisher ) { ## strip any trailing crap $_ = @$tuple[1]; s% *[,;:/]$%%; ## pool all occurrences in a list push( @publishers, $_ ); } elsif ( @$tuple[0] eq $pubsub_date ) { ## the dates are free-form, so we want to extract ## a four-digit year and leave the rest as ## "other info" my $protoyear = @$tuple[1]; print "Year (260\$c): $protoyear\r\n" if $marcprint; ## strip any separator chars at the end $protoyear =~ s% *[\.;:/]*$%%; ## isolate a four-digit year. We discard anything ## preceding the year, but keep everything after ## the year as other info. $protoyear =~ s%\D*([0-9\-]{4})(.*)%$1///$2%; ## check what we've got. If there is no four-digit ## year, make it up. If digits are replaced by '-', ## replace those with 0s if ( index( $protoyear, "/" ) == 4 ) { ## have year info ## replace all '-' in the four-digit year ## by '0' substr( $protoyear, 0, 4 ) =~ s!-!0!g; } else { ## have no year info print "no four-digit year found, use 0000\r\n" if $marcprint; $protoyear = "0000///$protoyear"; warn("no four-digit year found, use 0000") if $marcprint; } if ( $pycounter == 0 && length($protoyear) ) { print "PY - $protoyear\r\n"; } elsif ( $pycounter == 1 && length($_) ) { print "Y2 - $protoyear\r\n"; } ## else: discard } ## else: discard } ## now dump the collected CY and PB lists if ( @cities > 0 ) { print "CY - ", join( ", ", @cities ), "\r\n"; } if ( @publishers > 0 ) { print "PB - ", join( ", ", @publishers ), "\r\n"; } } } ##******************************************************************** ## get_keywords(): prints info from MARC fields 6XX ## Arguments: list of fields (6XX) ##******************************************************************** sub get_keywords { my ( $fieldname, @keywords ) = @_; my @kw; ## a list of all possible subfields my @subfields = ( 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'x', 'y', 'z', '2', '3', '4' ); ## loop over all 6XX fields foreach my $kwfield (@keywords) { if ( defined $kwfield ) { ## authornames get special treatment if ( $fieldname eq "600" ) { my $val = normalize_author( $kwfield->subfield('a'), $kwfield->subfield('b'), $kwfield->subfield('c'), $kwfield->indicator('1') ); push @kw, $val; print "Field $kwfield subfield a:", $kwfield->subfield('a'), "\r\nField $kwfield subfield b:", $kwfield->subfield('b'), "\r\nField $kwfield subfield c:", $kwfield->subfield('c'), "\r\n" if $marcprint; } else { ## retrieve all available subfields my @kwsubfields = $kwfield->subfields(); ## loop over all available subfield tuples foreach my $kwtuple (@kwsubfields) { ## loop over all subfields to check foreach my $subfield (@subfields) { ## [0] contains subfield code if ( @$kwtuple[0] eq $subfield ) { ## [1] contains value, remove trailing separators @$kwtuple[1] =~ s% *[,;.:/]*$%%; if ( length( @$kwtuple[1] ) > 0 ) { push @kw, @$kwtuple[1]; print "Field $fieldname subfield $subfield:", @$kwtuple[1], "\r\n" if $marcprint; } ## we can leave the subfields loop here last; } } } } } } return @kw; } ##******************************************************************** ## pool_subx(): adds contents of several subfields to a list ## Arguments: reference to a list ## field name ## list of fields (5XX) ##******************************************************************** sub pool_subx { my ( $aref, $fieldname, @notefields ) = @_; ## we use a list that contains the interesting subfields ## for each field # ToDo: this is apparently correct only for marc21 my @subfields; if ( $fieldname eq "500" ) { @subfields = ('a'); } elsif ( $fieldname eq "501" ) { @subfields = ('a'); } elsif ( $fieldname eq "502" ) { @subfields = ('a'); } elsif ( $fieldname eq "504" ) { @subfields = ( 'a', 'b' ); } elsif ( $fieldname eq "505" ) { @subfields = ( 'a', 'g', 'r', 't', 'u' ); } elsif ( $fieldname eq "506" ) { @subfields = ( 'a', 'b', 'c', 'd', 'e' ); } elsif ( $fieldname eq "507" ) { @subfields = ( 'a', 'b' ); } elsif ( $fieldname eq "508" ) { @subfields = ('a'); } elsif ( $fieldname eq "510" ) { @subfields = ( 'a', 'b', 'c', 'x', '3' ); } elsif ( $fieldname eq "511" ) { @subfields = ('a'); } elsif ( $fieldname eq "513" ) { @subfields = ( 'a', 'b' ); } elsif ( $fieldname eq "514" ) { @subfields = ( 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'u', 'z' ); } elsif ( $fieldname eq "515" ) { @subfields = ('a'); } elsif ( $fieldname eq "516" ) { @subfields = ('a'); } elsif ( $fieldname eq "518" ) { @subfields = ( 'a', '3' ); } elsif ( $fieldname eq "521" ) { @subfields = ( 'a', 'b', '3' ); } elsif ( $fieldname eq "522" ) { @subfields = ('a'); } elsif ( $fieldname eq "524" ) { @subfields = ( 'a', '2', '3' ); } elsif ( $fieldname eq "525" ) { @subfields = ('a'); } elsif ( $fieldname eq "526" ) { @subfields = ( 'a', 'b', 'c', 'd', 'i', 'x', 'z', '5' ); } elsif ( $fieldname eq "530" ) { @subfields = ( 'a', 'b', 'c', 'd', 'u', '3' ); } elsif ( $fieldname eq "533" ) { @subfields = ( 'a', 'b', 'c', 'd', 'e', 'f', 'm', 'n', '3' ); } elsif ( $fieldname eq "534" ) { @subfields = ( 'a', 'b', 'c', 'e', 'f', 'k', 'l', 'm', 'n', 'p', 't', 'x', 'z' ); } elsif ( $fieldname eq "535" ) { @subfields = ( 'a', 'b', 'c', 'd', 'g', '3' ); } ## loop over all notefields foreach my $notefield (@notefields) { if ( defined $notefield ) { ## retrieve all available subfield tuples my @notesubfields = $notefield->subfields(); ## loop over all subfield tuples foreach my $notetuple (@notesubfields) { ## loop over all subfields to check foreach my $subfield (@subfields) { ## [0] contains subfield code if ( @$notetuple[0] eq $subfield ) { ## [1] contains value, remove trailing separators print "field $fieldname subfield $subfield: ", @$notetuple[1], "\r\n" if $marcprint; @$notetuple[1] =~ s% *[,;.:/]*$%%; if ( length( @$notetuple[1] ) > 0 ) { ## add to list push @{$aref}, @$notetuple[1]; } last; } } } } } } ##******************************************************************** ## print_abstract(): prints abstract fields ## Arguments: list of fields (520) ##******************************************************************** sub print_abstract { # ToDo: take care of repeatable subfields my (@abfields) = @_; ## we check the following subfields my @subfields = ( 'a', 'b' ); ## we generate a list for all useful strings my @abstrings; ## loop over all abfields foreach my $abfield (@abfields) { foreach my $field (@subfields) { if ( length( $abfield->subfield($field) ) > 0 ) { my $ab = $abfield->subfield($field); print "field 520 subfield $field: $ab\r\n" if $marcprint; ## strip trailing separators $ab =~ s% *[;,:./]*$%%; ## add string to the list push( @abstrings, $ab ); } } } my $allabs = join "; ", @abstrings; if ( length($allabs) > 0 ) { print "N2 - ", $allabs, "\r\n"; } } 1;