@@ -, +, @@ --- C4/Breeding.pm | 439 +++++++- acqui/z3950_search.pl | 320 +----- admin/z3950servers.pl | 57 +- cataloguing/z3950_search.pl | 297 +----- .../prog/en/modules/admin/z3950servers.tt | 2 + .../intranet-tmpl/prog/en/xslt/MARC21toUNIMARC.xsl | 1187 ++++++++++++++++++++ .../intranet-tmpl/prog/en/xslt/UNIMARCtoMARC21.xsl | 523 +++++++++ 7 files changed, 2283 insertions(+), 542 deletions(-) create mode 100644 koha-tmpl/intranet-tmpl/prog/en/xslt/MARC21toUNIMARC.xsl create mode 100644 koha-tmpl/intranet-tmpl/prog/en/xslt/UNIMARCtoMARC21.xsl --- a/C4/Breeding.pm +++ a/C4/Breeding.pm @@ -21,10 +21,14 @@ use strict; use warnings; use C4::Biblio; -use C4::Koha; use C4::Charset; -use MARC::File::USMARC; use C4::ImportBatch; +use C4::Koha; + +use MARC::File::USMARC; +use XML::LibXML; +use XML::LibXSLT; +use ZOOM; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); @@ -36,6 +40,21 @@ BEGIN { @EXPORT = qw(&ImportBreeding &BreedingSearch); } +#------------------------------------------------------------------------------- + +use constant MAX_RESULTS => 20; +use constant TO_UNIMARC_XSLT => 'MARC21toUNIMARC.xsl'; +use constant TO_MARC21_XSLT => 'UNIMARCtoMARC21.xsl'; + +my ($input,@oConnection,@oResult,@hServer,$zquery, $squery); +#zquery in z3950 format; squery general sru, needs server translation +my $xsltconv; #stylesheet for marc conversion +my $flavour; #system marc flavour + +my $DEBUG=0; #set to 1 for debug warnings + +#------------------------------------------------------------------------------- + =head1 NAME C4::Breeding : module to add biblios to import_records via @@ -154,7 +173,6 @@ sub ImportBreeding { return ($notmarcrecord,$alreadyindb,$alreadyinfarm,$imported,$breedingid); } - =head2 BreedingSearch ($count, @results) = &BreedingSearch($title,$isbn,$random); @@ -216,6 +234,421 @@ sub BreedingSearch { return($count, @results); } # sub breedingsearch +=head2 z3950_search + +($breedingref, $error_ref)= C4::Breeding::z3950_search($input); +C<$input> is a CGI object: all search parameters are passed via this object + +C<$breedingref> is an arrayref of search result hashes. +C<$error_ref> is an arrayref of error messages per server. + +z3950_search does not call ImportBreeding anymore for performance reasons. + +=cut + +sub z3950_search { +# This is a completely new Z3950 clients search using async ZOOM -TG 02/11/06 +# Did some refactoring, introduced SRU searching -MR 20110608 +# And incorporated Biblibre XSLT processing for MARC21/UNIMARC conversion + $input= shift; #CGI object passed + my (@errconn, @breeding_loop); + + init_vars(); + build_query(); + my $s= create_connections(); + load_xslt(); + start_async_searches(); + + my $nremaining = $s; + while($nremaining>0) { + my $k=loop_conn_events(); #returns finished connection number + handle_conn_results(\@breeding_loop, \@errconn, $k) unless $k<0; + --$nremaining; + } + $_->destroy() for @oConnection; + + return (\@breeding_loop, \@errconn ); +} + +#------------------------------------------------------------------------------- +# Some internal subroutines + +sub init_vars { + @oConnection=(); + @oResult=(); + @hServer=(); + ($zquery,$squery,$xsltconv,$flavour)=('','',undef,''); +} + +sub build_query { + my $nterms=0; + my $title = $input->param('title')||''; + my $author = $input->param('author')||''; + my $isbn = $input->param('isbn')||''; + my $lccall = $input->param('lccall')||''; + my $subject = $input->param('subject')||''; + my $dewey = $input->param('dewey')||''; + my $controlnumber = $input->param('controlnumber')||''; + my $stdid = $input->param('stdid')||''; + my $srchany = $input->param('srchany')||''; + + if ($isbn) { + $zquery = "\@or \@attr 1=8 \"$isbn\" \@attr 1=7 \"$isbn\" "; + $squery = "([isbn]=\"$isbn\" or [issn]=\"$isbn\") and "; + $nterms++; + } + if ($title) { + utf8::decode($title); + $zquery .= "\@attr 1=4 \"$title\" "; + $squery .= "[title]=\"$title\" and "; + $nterms++; + } + if ($author) { + utf8::decode($author); + $zquery .= "\@attr 1=1003 \"$author\" "; + $squery .= "[author]=\"$author\" and "; + $nterms++; + } + if ($dewey) { + $zquery .= "\@attr 1=16 \"$dewey\" "; + $squery .= "[dewey]=\"$dewey\" and "; + $nterms++; + } + if ($subject) { + utf8::decode($subject); + $zquery .= "\@attr 1=21 \"$subject\" "; + $squery .= "[subject]=\"$subject\" and "; + $nterms++; + } + if ($lccall) { + $zquery .= "\@attr 1=16 \@attr 2=3 \@attr 3=1 \@attr 4=1 \@attr 5=1 \@attr 6=1 \"$lccall\" "; + $squery .= "[lccn]=\"$lccall\" and "; + $nterms++; + } + if ($controlnumber) { + $zquery .= "\@attr 1=12 \"$controlnumber\" "; + $squery .= "[controlnumber]=\"$controlnumber\" and "; + $nterms++; + } + if ($stdid) { + $zquery .= "\@attr 1=1007 \"$stdid\" "; + $squery .= "[stdid]=\"$stdid\" and "; + $nterms++; + } + if ($srchany) { + $zquery .= "\@attr 1=1016 \"$srchany\" "; + $squery .= "[any]=\"$srchany\" and "; + $nterms++; + } + for(1..$nterms-1) { + $zquery = "\@and " . $zquery; + } + $squery=~s/\sand\s$//; #remove last and in sru query + warn "zquery ".$zquery if $DEBUG; + warn "squery ".$squery if $DEBUG; +} + +sub create_connections { + my $s=0; + my $dbh= C4::Context->dbh; + + my @id= $input->param('id'); + foreach my $servid (@id) { + my $sth = $dbh->prepare("select * from z3950servers where id=?"); + $sth->execute($servid); + my $server = $sth->fetchrow_hashref; + next unless $server; + warn "serverinfo ".join(':',my @a=map($_||'',%$server)) if $DEBUG; + + $server->{sru}= $server->{host}=~/^sru=/ ? 1: 0; + change_sru_host($server) if $server->{sru}; + + #set connection options + my $option1 = new ZOOM::Options(); + $option1->option('async' => 1); + $option1->option('elementSetName', 'F'); + $option1->option('databaseName', $server->{db}) unless $server->{sru}; + $option1->option('user', $server->{userid}) if $server->{userid}; + $option1->option('password',$server->{password}) if $server->{password}; + $option1->option('preferredRecordSyntax', $server->{syntax}); + $option1->option('maximumRecords', MAX_RESULTS) if $server->{sru}; + #MR: doubt if maximum makes difference when going through ZOOM + pass_sru_options($server,$option1) if $server->{sru}; + + #create connection object + my $conn; + $oConnection[$s]= create ZOOM::Connection($option1); + + #now connect + if($server->{sru}) { + $oConnection[$s]->connect( 'http://'.$server->{host}); + } + else { + $oConnection[$s]->connect( $server->{host}, $server->{port} ); + } + + $hServer[$s]= $server; + $s++; + } + return $s; +} + +sub change_sru_host { #merge port and database into hostname + my $server= shift; + if($server->{port} ne '80') { + if($server->{host}=~/^([^\/]+)\/(.*)$/ ) { + $server->{host}= $1.':'.$server->{port}.'/'.$2; + } + else { + $server->{host}.= ':'.$server->{port}; + } + } + #prevent double slash between host and db when concatenating + $server->{host}=~ s/\/$//g; + $server->{db}=~ s/^\///g; + $server->{host}.= '/'.$server->{db}; +} + +sub pass_sru_options { + my ($server, $option1)=@_; + my @parts= split /,/,$server->{host}; + foreach(my $i=0; $i<@parts; $i++) { + if($i==@parts-1) { + $server->{host}=$parts[$i]; + } + else { + if($parts[$i]=~/^([^=]+)=(.*)/) { + $option1->option( $1 => $2); + } + } + } +} + +sub load_xslt { #load stylesheet for marc conversion IF needed + $flavour= C4::Context->preference('marcflavour'); + my $loaded=0; + foreach (@hServer) { #load stylesheet once, set key for each server + $_->{marc_conv}=0; + if($flavour eq 'MARC21' && $_->{syntax}=~/UNIMARC/) { + $_->{marc_conv}=1; + _load_xslt_stylesheet(TO_MARC21_XSLT) unless $loaded; + $loaded=1; + } + elsif($flavour eq 'UNIMARC' && $_->{syntax}!~/UNIMARC/) { + $_->{marc_conv}=1; + _load_xslt_stylesheet(TO_UNIMARC_XSLT) unless $loaded; + $loaded=1; + } + } +} + +sub _load_xslt_stylesheet { + my ($name)= @_; + my $f=full_xslt_path($name); + if($f) { + my $parser = XML::LibXML->new(); + my $xslt = XML::LibXSLT->new(); + my $style_doc = $parser->parse_file($f); + $xsltconv = $xslt->parse_stylesheet($style_doc); + } + else { + warn "z3950_search: XSLT problem with $name"; + } +} + +sub full_xslt_path { + my $name=shift; + #absolute path? + if(substr($name,0,1) eq '/') { + return -e $name?$name:undef; + } + #a relative path: look in xslt subfolder of staff templates + my $dir= C4::Context->config('intrahtdocs').'/'. + C4::Context->preference('template'); + #try language folder first, otherwise english + my $lang=$input->cookie('KohaOpacLanguage')||'en'; #null->english + my $ff= $dir.'/'.$lang.'/xslt/'.$name; + return $ff if -e $ff; + $ff=$dir.'/en/xslt/'.$name; + return -e $ff? $ff: undef; +} + +sub start_async_searches { + my $k=0; + foreach my $conn (@oConnection) { + warn 'Doing search '.($k+1) if $DEBUG; + if($hServer[$k]->{sru}) { + $oResult[$k] = $conn->search(new ZOOM::Query::CQL(tran_query($k))); + } + else { + $oResult[$k]=$conn->search_pqf($zquery); + } + $k++; + } +} + +sub loop_conn_events { + my ($event, $k); + while ( ( $k = ZOOM::event( \@oConnection ) ) != 0 ) { + $event = $oConnection[ $k - 1 ]->last_event(); + warn( "connection ", $k - 1, ": event $event (", + ZOOM::event_str($event), ")\n" ) + if $DEBUG; + last if $event == ZOOM::Event::ZEND; + } + return $k-1; +} + +sub handle_conn_results { + my ($breedingref, $errorref, $conn)= @_; + + warn 'Handling results for '.$hServer[$conn]->{name} if $DEBUG; + my ($error, $errmsg, $addinfo, $diagset)= $oConnection[$conn]->error_x(); + if ($error) { + if ($error =~ m/^(10000|10007)$/ ) { + push(@$errorref, {'server' => $hServer[$conn]->{host} }); + } + warn "$conn ".$hServer[$conn]->{host}. + " error $zquery: $errmsg ($error) $addinfo\n"; + return; + } + + my $numresults = $oResult[$conn]->size(); + warn "Number of hits: $numresults" if $DEBUG; + $numresults= MAX_RESULTS if $numresults>MAX_RESULTS; + for(my $i=0; $i<$numresults; $i++) { + my $rec = $oResult[$conn]->record($i); + if($rec) { + handle_one_result($rec, $breedingref, $conn); + } + else { + push(@$breedingref, { + 'server' => $hServer[$conn]->{name}, + 'title' => join(': ',$oConnection[$conn]->error_x()), + 'breedingid' => -1, + 'biblionumber' => -1 + }); + } + } + $oResult[$conn]->destroy(); +} + +sub handle_one_result { + my ($rec, $breedingref, $conn)= @_; + my $marcrecord; + + if($hServer[$conn]->{sru}) { #SRU + $marcrecord= MARC::Record->new_from_xml($rec->raw(),'UTF-8', + $hServer[$conn]->{syntax}); + } + else { #z3950 + ($marcrecord)= MarcToUTF8Record($rec->raw(), + marcflavour_from_syntax($conn), $hServer[$conn]->{encoding}); + } + $marcrecord->encoding('UTF-8'); #force UTF-8 + #convert to system marc flavour and/or additional xslt proc. + $marcrecord= do_xslt_processing($conn, $marcrecord); + + #call to ImportBreeding replaced by next two calls for optimization + my $batch_id = GetZ3950BatchId($hServer[$conn]->{name}); + my $random= $input->param('random') || rand(1000000000); + my $breedingid = AddBiblioToBatch($batch_id, 0, $marcrecord, 'UTF-8',$random); + #call to TransformMarcToKoha replaced by next call; we only need 6 fields + #save results + add_breeding($breedingref, $conn, $marcrecord, $breedingid); +} + +sub marcflavour_from_syntax { +#passing USMARC to MarcToUTF8Record doesn't work; only knows MARC21/UNIMARC + my $conn= shift; + return 'UNIMARC' if $hServer[$conn]->{syntax}=~/UNIMARC/; + return 'MARC21'; #otherwise +} + +sub do_xslt_processing { +#convert marc21<->unimarc and/or additional xslt; return MARC record + my ($conn, $marcrecord)= @_; + my ($res, $newmarcrec, $parser, $style_doc, $stylesheet); + + if($hServer[$conn]->{marc_conv} && defined $xsltconv) { + $parser = XML::LibXML->new(); + $res= $parser->parse_string($marcrecord->as_xml()); + $res= $xsltconv->transform($res); + $res= $xsltconv->output_string($res); + $newmarcrec= MARC::Record->new_from_xml($res, 'UTF-8'); + } + + if($hServer[$conn]->{add_xslt}) { #server specific xslt proc + $res= $newmarcrec? $newmarcrec->as_xml(): $marcrecord->as_xml(); + $parser = XML::LibXML->new() unless $parser; + $res= $parser->parse_string($res); + my $f= full_xslt_path($hServer[$conn]->{add_xslt}); + $style_doc = $parser->parse_file($f) if $f; + my $xslt = XML::LibXSLT->new(); + $stylesheet = $xslt->parse_stylesheet($style_doc) if $style_doc; + if($stylesheet) { + $res= $stylesheet->transform($res); + $res= $stylesheet->output_string($res); + $newmarcrec= MARC::Record->new_from_xml($res, 'UTF-8'); + } + else { + warn "z3950_search: XSLT problem with ".$hServer[$conn]->{add_xslt}; + } + } + return $newmarcrec // $marcrecord; +} + +sub add_breeding { + my ($breedingref, $conn, $marcrecord, $breedingid)=@_; + my %row_data=(); + $row_data{server} = $hServer[$conn]->{name}; + $row_data{breedingid} = $breedingid; + $row_data{biblionumber} = $input->param('biblionumber')||0; + if($flavour ne 'UNIMARC') { #MARC21 system (not target!) + $row_data{isbn} = isbn_cleanup($marcrecord->subfield('020','a')||''); + $row_data{title}= $marcrecord->subfield('245','a')||''; + $row_data{author}= $marcrecord->subfield('100','a')||''; + $row_data{date}= $marcrecord->subfield('260','c')||''; + $row_data{edition}= $marcrecord->subfield('250','a')||''; + $row_data{lccn}= $marcrecord->subfield('050','a')||''; + } + else { #UNIMARC system (not target!) + $row_data{isbn}= isbn_cleanup($marcrecord->subfield('010','a')||''); + $row_data{title}= $marcrecord->subfield('200','a')||''; + $row_data{author}= $marcrecord->subfield('200','f')||''; + $row_data{date}= $marcrecord->subfield('210','d')||''; + $row_data{edition}= $marcrecord->subfield('205','a')||''; + $row_data{lccn}= ''; + } + push( @$breedingref, \%row_data ); +} + +sub isbn_cleanup { + my $isbn= shift; + $isbn=~ s/ |-|\.//g; + $isbn=~ s/\|/ \| /g; + $isbn=~ s/\(/ \(/g; + return $isbn; +} + +sub tran_query { #translate to specific sru fields per server + my ($s)= @_; + #srufields is in format title=field,isbn=field,... + #if a field doesn't exist, try anywhere or remove [field]= + my @parts= split(',', $hServer[$s]->{srufields}); + my %trans= map { if(/=/){($`,$')}else{()} } @parts; + + my $q=$squery; my $any= $trans{any}?$trans{any}.'=':''; + foreach my $key (keys %trans) { + my $f=$trans{$key}; + if($f) {$q=~s/\[$key\]/$f/g; } else {$q=~s/\[$key\]=/$any/g; } + } + $q=~s/\[\w+\]=/$any/g; # remove remaining fields (not found in field list) + warn $hServer[$s]->{name}." sru query: $q" if $DEBUG; + return $q; +} + 1; + __END__ --- a/acqui/z3950_search.pl +++ a/acqui/z3950_search.pl @@ -1,6 +1,5 @@ #!/usr/bin/perl -# This is a completely new Z3950 clients search using async ZOOM -TG 02/11/06 # Copyright 2000-2002 Katipo Communications # Copyright 2010 Catalyst IT # @@ -21,19 +20,19 @@ use warnings; use strict; + use CGI; use C4::Auth; +use C4::Koha; use C4::Output; -use C4::Biblio; use C4::Context; use C4::Breeding; -use C4::Koha; -use C4::Charset; use C4::Bookseller qw/ GetBookSellerFromId /; -use ZOOM; -my $input = new CGI; +#------------------------------------------------------------------------------- + +my $input= new CGI; my ( $template, $loggedinuser, $cookie ) = get_template_and_user( { template_name => "acqui/z3950_search.tmpl", @@ -44,278 +43,77 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( debug => 1, } ); +my $frameworkcode = $input->param('frameworkcode')||''; +my $vendor = GetBookSellerFromId($input->param('booksellerid')||0); +$template->param( + frameworkcode => $frameworkcode, + frameworkcodeloop => get_framework_list(), + booksellerid => $input->param('booksellerid')||0, + basketno => $input->param('basketno'), + name => $vendor? $vendor->{'name'}: '', +); - -my $dbh = C4::Context->dbh; -my $error = $input->param('error'); -my $biblionumber = $input->param('biblionumber'); -$biblionumber = 0 unless $biblionumber; -my $frameworkcode = $input->param('frameworkcode'); -my $title = $input->param('title'); -my $author = $input->param('author'); -my $isbn = $input->param('isbn'); -my $issn = $input->param('issn'); -my $lccn = $input->param('lccn'); -my $lccall = $input->param('lccall'); -my $subject= $input->param('subject'); -my $dewey = $input->param('dewey'); -my $controlnumber = $input->param('controlnumber'); -my $op = $input->param('op'); -my $booksellerid = $input->param('booksellerid'); -my $basketno = $input->param('basketno'); -my $noconnection; -my $numberpending; -my $attr = ''; -my $term; -my $host; -my $server; -my $database; -my $port; -my $marcdata; -my @encoding; -my @results; -my $count; -my $toggle; -my $record; -my $oldbiblio; -my $errmsg; -my @serverhost; -my @servername; -my @breeding_loop = (); -my $random = $input->param('random'); -unless ($random) -{ # this var is not useful anymore just kept to keep rel2_2 compatibility - $random = rand(1000000000); +my $op= $input->param('op')||''; +if($op ne "do_search") { + show_search_form(); +} +else { + run_search(); } +output_html_with_http_headers $input, $cookie, $template->output; -my $DEBUG = 0; # if set to 1, many debug message are send on syslog. +#------------------------------------------------------------------------------- -# get framework list -my $frameworks = getframeworks; -my @frameworkcodeloop; -foreach my $thisframeworkcode ( keys %$frameworks ) { +sub get_framework_list { + my $frameworks = getframeworks(); + my @frameworkcodeloop; + foreach my $thisframeworkcode ( keys %$frameworks ) { my %row = ( value => $thisframeworkcode, frameworktext => $frameworks->{$thisframeworkcode}->{'frameworktext'}, ); - if ( $row{'value'} eq $frameworkcode){ + if ($row{'value'} eq $frameworkcode) { $row{'active'} = 'true'; } push @frameworkcodeloop, \%row; + } + return \@frameworkcodeloop; } -my $vendor = GetBookSellerFromId($booksellerid); -$template->param( frameworkcode => $frameworkcode, - frameworkcodeloop => \@frameworkcodeloop, - booksellerid => $booksellerid, - basketno => $basketno, - name => $vendor->{'name'} - ); - +#------------------------------------------------------------------------------- - -if ( $op ne "do_search" ) { - my $sth = $dbh->prepare("select id,host,name,checked from z3950servers order by host"); - $sth->execute(); - my $serverloop = $sth->fetchall_arrayref( {} ); - $template->param( - isbn => $isbn, - issn => $issn, - lccn => $lccn, - lccall => $lccall, - title => $title, - author => $author, - controlnumber=> $controlnumber, +sub show_search_form { + my $dbh= C4::Context->dbh; + my $sth = $dbh->prepare("select id,host,name,checked from z3950servers order by host"); + $sth->execute(); + my $serverloop = $sth->fetchall_arrayref( {} ); + $template->param( + biblionumber => $input->param('biblionumber') || 0, serverloop => $serverloop, opsearch => "search", - biblionumber => $biblionumber, - ); - output_html_with_http_headers $input, $cookie, $template->output; -} -else { - my @id = $input->param('id'); - my @oConnection; - my @oResult; - my $s = 0; - my $query; - my $nterms; - if ($isbn || $issn) { - $term=$isbn if ($isbn); - $term=$issn if ($issn); - $query .= " \@or \@attr 1=8 \"$term\" \@attr 1=7 \"$term\" "; - $nterms++; - } - if ($title) { - utf8::decode($title); - $query .= " \@attr 1=4 \"$title\" "; - $nterms++; - } - if ($author) { - utf8::decode($author); - $query .= " \@attr 1=1003 \"$author\" "; - $nterms++; - } - if ($dewey) { - $query .= " \@attr 1=16 \"$dewey\" "; - $nterms++; - } - if ($subject) { - utf8::decode($subject); - $query .= " \@attr 1=21 \"$subject\" "; - $nterms++; - } - if ($lccn) { - $query .= " \@attr 1=9 $lccn "; - $nterms++; - } - if ($lccall) { - $query .= " \@attr 1=16 \@attr 2=3 \@attr 3=1 \@attr 4=1 \@attr 5=1 \@attr 6=1 \"$lccall\" "; - $nterms++; - } - if ($controlnumber) { - $query .= " \@attr 1=12 \"$controlnumber\" "; - $nterms++; - } -for my $i (1..$nterms-1) { - $query = "\@and " . $query; + title => $input->param('title')||'', + isbn => $input->param('isbn')||'', + lccall => $input->param('lccall')||'', + controlnumber=> $input->param('controlnumber')||'', + #srchany => $input->param('srchany')||'', + author => $input->param('author')||'', + subject => $input->param('subject')||'', + dewey => $input->param('dewey')||'', + #stdid => $input->param('stdid')||'', + ); + #acqui z3950 doesn't support srchany and stdid but cataloguing does } -warn "query ".$query if $DEBUG; - - foreach my $servid (@id) { - my $sth = $dbh->prepare("select * from z3950servers where id=?"); - $sth->execute($servid); - while ( $server = $sth->fetchrow_hashref ) { - warn "serverinfo ".join(':',%$server) if $DEBUG; - my $noconnection = 0; - my $option1 = new ZOOM::Options(); - $option1->option( 'async' => 1 ); - $option1->option( 'elementSetName', 'F' ); - $option1->option( 'databaseName', $server->{db} ); - $option1->option( 'user', $server->{userid} ) if $server->{userid}; - $option1->option( 'password', $server->{password} ) - if $server->{password}; - $option1->option( 'preferredRecordSyntax', $server->{syntax} ); - $oConnection[$s] = create ZOOM::Connection($option1) - || $DEBUG - && warn( "" . $oConnection[$s]->errmsg() ); - warn( "server data", $server->{name}, $server->{port} ) if $DEBUG; - $oConnection[$s]->connect( $server->{host}, $server->{port} ) - || $DEBUG - && warn( "" . $oConnection[$s]->errmsg() ); - $serverhost[$s] = $server->{host}; - $servername[$s] = $server->{name}; - $encoding[$s] = ($server->{encoding}?$server->{encoding}:"iso-5426"); - $s++; - } ## while fetch - } # foreach - my $nremaining = $s; - my $firstresult = 1; - - for ( my $z = 0 ; $z < $s ; $z++ ) { - warn "doing the search" if $DEBUG; - $oResult[$z] = $oConnection[$z]->search_pqf($query) - || $DEBUG - && warn( "somthing went wrong: " . $oConnection[$s]->errmsg() ); - - # $oResult[$z] = $oConnection[$z]->search_pqf($query); - } -sub displayresults { - my $k; - my $event; - while ( ( $k = ZOOM::event( \@oConnection ) ) != 0 ) { - $event = $oConnection[ $k - 1 ]->last_event(); - warn( "connection ", $k - 1, ": event $event (", - ZOOM::event_str($event), ")\n" ) - if $DEBUG; - last if $event == ZOOM::Event::ZEND; - } - - if ( $k != 0 ) { - $k--; - warn $serverhost[$k] if $DEBUG; - my ( $error, $errmsg, $addinfo, $diagset ) = - $oConnection[$k]->error_x(); - if ($error) { - warn "$k $serverhost[$k] error $query: $errmsg ($error) $addinfo\n" - if $DEBUG; - - } - else { - my $numresults = $oResult[$k]->size(); - my $i; - my $result = ''; - if ( $numresults > 0 ) { - for ( - $i = 0 ; - $i < ( ( $numresults < 20 ) ? ($numresults) : (20) ) ; - $i++ - ) - { - my $rec = $oResult[$k]->record($i); - if ($rec) { - my $marcrecord; - $marcdata = $rec->raw(); - - my ($charset_result, $charset_errors); - ($marcrecord, $charset_result, $charset_errors) = - MarcToUTF8Record($marcdata, C4::Context->preference('marcflavour'), $encoding[$k]); -####WARNING records coming from Z3950 clients are in various character sets MARC8,UTF8,UNIMARC etc -## In HEAD i change everything to UTF-8 -# In rel2_2 i am not sure what encoding is so no character conversion is done here -##Add necessary encoding changes to here -TG - my $oldbiblio = TransformMarcToKoha( $dbh, $marcrecord, "" ); - $oldbiblio->{isbn} =~ s/ |-|\.//g if $oldbiblio->{isbn}; - # pad | and ( with spaces to allow line breaks in the HTML - $oldbiblio->{isbn} =~ s/\|/ \| /g if $oldbiblio->{isbn}; - $oldbiblio->{isbn} =~ s/\(/ \(/g if $oldbiblio->{isbn}; +#------------------------------------------------------------------------------- - $oldbiblio->{issn} =~ s/ |-|\.//g if $oldbiblio->{issn}; - # pad | and ( with spaces to allow line breaks in the HTML - $oldbiblio->{issn} =~ s/\|/ \| /g if $oldbiblio->{issn}; - $oldbiblio->{issn} =~ s/\(/ \(/g if $oldbiblio->{issn}; - my ( - $notmarcrecord, $alreadyindb, $alreadyinfarm, - $imported, $breedingid - ) - = ImportBreeding( $marcdata, 2, $serverhost[$k], $encoding[$k], $random, 'z3950' ); - my %row_data; - if ( $i % 2 ) { - $toggle = 1; - } - else { - $toggle = 0; - } - $row_data{toggle} = $toggle; - $row_data{server} = $servername[$k]; - $row_data{isbn} = $oldbiblio->{isbn}; - $row_data{lccn} = $oldbiblio->{lccn}; - $row_data{title} = $oldbiblio->{title}; - $row_data{author} = $oldbiblio->{author}; - $row_data{breedingid} = $breedingid; - $row_data{biblionumber} = $biblionumber; - push( @breeding_loop, \%row_data ); - - } else { - push(@breeding_loop,{'toggle'=>($i % 2)?1:0,'server'=>$servername[$k],'title'=>join(': ',$oConnection[$k]->error_x()),'breedingid'=>-1,'biblionumber'=>-1}); - } # $rec - } # upto 5 results - } #$numresults - } - } # if $k !=0 - $numberpending = $nremaining - 1; - $template->param( - breeding_loop => \@breeding_loop, - server => $servername[$k], - numberpending => $numberpending, - ); - output_html_with_http_headers $input, $cookie, $template->output if $numberpending == 0; - - # print $template->output if $firstresult !=1; - $firstresult++; +sub run_search { + my ($breedingref)= C4::Breeding::z3950_search($input); + #Code for Z3950 searching moved to C4 module -MR 06/27/11 + #second return value is ignored here (not in cataloguing) + $template->param( + breeding_loop => $breedingref, + biblionumber => $input->param('biblionumber') || 0, + ); } -displayresults(); -while ( --$nremaining > 0 ) { - displayresults(); - } -} ## if op=search + +#------------------------------------------------------------------------------- --- a/admin/z3950servers.pl +++ a/admin/z3950servers.pl @@ -32,7 +32,7 @@ sub StringSearch { $searchstring=~ s/\'/\\\'/g; my @data=split(' ',$searchstring); my $count=@data; - my $sth=$dbh->prepare("Select host,port,db,userid,password,name,id,checked,rank,syntax,encoding from z3950servers where (name like ?) order by rank,name"); + my $sth=$dbh->prepare("Select host,port,db,userid,password,name,id,checked,rank,syntax,encoding,srufields,add_xslt from z3950servers where (name like ?) order by rank,name"); $sth->execute("$data[0]\%"); my @results; while (my $data=$sth->fetchrow_hashref) { @@ -74,15 +74,15 @@ if ($op eq 'add_form') { my $data; if ($searchfield) { my $dbh = C4::Context->dbh; - my $sth=$dbh->prepare("select host,port,db,userid,password,name,id,checked,rank,syntax,encoding from z3950servers where (name = ?) order by rank,name"); + my $sth=$dbh->prepare("select host,port,db,userid,password,name,id,checked,rank,syntax,encoding,srufields,add_xslt from z3950servers where (name = ?) order by rank,name"); $sth->execute($searchfield); $data=$sth->fetchrow_hashref; $sth->finish; } $template->param( $_ => $data->{$_} ) - for ( qw( host port db userid password checked rank ) ); + for ( qw( host port db userid password checked rank srufields add_xslt) ); $template->param( $_ . $data->{$_} => 1) - for ( qw( syntax encoding ) ); + for ( qw( syntax encoding) ); # END $OP eq ADD_FORM ################## ADD_VALIDATE ################################## # called by add_form, used to insert/modify data in DB @@ -92,7 +92,7 @@ if ($op eq 'add_form') { my $sth=$dbh->prepare("select * from z3950servers where name=?"); $sth->execute($input->param('searchfield')); if ($sth->rows) { - $sth=$dbh->prepare("update z3950servers set host=?, port=?, db=?, userid=?, password=?, name=?, checked=?, rank=?,syntax=?,encoding=? where name=?"); + $sth=$dbh->prepare("update z3950servers set host=?, port=?, db=?, userid=?, password=?, name=?, checked=?, rank=?,syntax=?,encoding=?,srufields=?,add_xslt=? where name=?"); $sth->execute($input->param('host'), $input->param('port'), $input->param('db'), @@ -101,27 +101,32 @@ if ($op eq 'add_form') { $input->param('searchfield'), $input->param('checked'), $input->param('rank'), - $input->param('syntax'), - $input->param('encoding'), + $input->param('syntax'), + $input->param('encoding'), + $input->param('srufields'), + $input->param('add_xslt'), $input->param('searchfield'), ); } else { $sth=$dbh->prepare( "INSERT INTO z3950servers " . - "(host,port,db,userid,password,name,checked,rank,syntax,encoding) " . - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" ); - $sth->execute( - $input->param( 'host' ), - $input->param( 'port' ), - $input->param( 'db' ), - $input->param( 'userid' ), - $input->param( 'password' ), - $input->param( 'searchfield' ), - $input->param( 'checked' ), - $input->param( 'rank' ), - $input->param( 'syntax' ), - $input->param( 'encoding' ) ); + "(host,port,db,userid,password,name,checked,rank,syntax,encoding,srufields,add_xslt) " . + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" ); + $sth->execute( + $input->param( 'host' ), + $input->param( 'port' ), + $input->param( 'db' ), + $input->param( 'userid' ), + $input->param( 'password' ), + $input->param( 'searchfield' ), + $input->param( 'checked' ), + $input->param( 'rank' ), + $input->param( 'syntax' ), + $input->param( 'encoding' ), + $input->param( 'srufields'), + $input->param( 'add_xslt'), + ); } $sth->finish; # END $OP eq ADD_VALIDATE @@ -131,7 +136,7 @@ if ($op eq 'add_form') { $template->param(delete_confirm => 1); my $dbh = C4::Context->dbh; - my $sth2=$dbh->prepare("select host,port,db,userid,password,name,id,checked,rank,syntax,encoding from z3950servers where (name = ?) order by rank,name"); + my $sth2=$dbh->prepare("select host,port,db,userid,password,name,id,checked,rank,syntax,encoding,srufields,add_xslt from z3950servers where (name = ?) order by rank,name"); $sth2->execute($searchfield); my $data=$sth2->fetchrow_hashref; $sth2->finish; @@ -144,7 +149,10 @@ if ($op eq 'add_form') { checked => $data->{'checked'}, rank => $data->{'rank'}, syntax => $data->{'syntax'}, - encoding => $data->{'encoding'} ); + encoding => $data->{'encoding'}, + srufields => $data->{srufields}, + add_xslt => $data->{add_xslt}, + ); # END $OP eq DELETE_CONFIRM ################## DELETE_CONFIRMED ################################## @@ -174,7 +182,10 @@ if ($op eq 'add_form') { checked => $results->[$i]{'checked'}, rank => $results->[$i]{'rank'}, syntax => $results->[$i]{'syntax'}, - encoding => $results->[$i]{'encoding'}); + encoding => $results->[$i]{'encoding'}, + srufields => $results->[$i]{srufields}, + add_xslt => $results->[$i]{add_xslt}, + ); push @loop, \%row; } --- a/cataloguing/z3950_search.pl +++ a/cataloguing/z3950_search.pl @@ -1,6 +1,5 @@ #!/usr/bin/perl -# This is a completely new Z3950 clients search using async ZOOM -TG 02/11/06 # Copyright 2000-2002 Katipo Communications # # This file is part of Koha. @@ -19,58 +18,19 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. use strict; -#use warnings; FIXME - Bug 2505 +use warnings; + use CGI; use C4::Auth; use C4::Output; -use C4::Biblio; use C4::Context; use C4::Breeding; -use C4::Koha; -use C4::Charset; -use ZOOM; - -my $input = new CGI; -my $dbh = C4::Context->dbh; -my $error = $input->param('error'); -my $biblionumber = $input->param('biblionumber') || 0; -my $frameworkcode = $input->param('frameworkcode'); -my $title = $input->param('title'); -my $author = $input->param('author'); -my $isbn = $input->param('isbn'); -my $issn = $input->param('issn'); -my $lccn = $input->param('lccn'); -my $lccall = $input->param('lccall'); -my $subject = $input->param('subject'); -my $dewey = $input->param('dewey'); -my $controlnumber = $input->param('controlnumber'); -my $stdid = $input->param('stdid'); -my $srchany = $input->param('srchany'); -my $random = $input->param('random') || rand(1000000000); # this var is not useful anymore just kept for rel2_2 compatibility -my $op = $input->param('op'); -my $numberpending; -my $attr = ''; -my $term; -my $host; -my $server; -my $database; -my $port; -my $marcdata; -my @encoding; -my @results; -my $count; -my $record; -my $oldbiblio; -my $errmsg; -my @serverloop = (); -my @serverhost; -my @servername; -my @breeding_loop = (); -my $DEBUG = 0; # if set to 1, many debug message are send on syslog. +#------------------------------------------------------------------------------- -my ( $template, $loggedinuser, $cookie ) = get_template_and_user({ +my $input= new CGI; +my ($template, $loggedinuser, $cookie ) = get_template_and_user({ template_name => "cataloguing/z3950_search.tmpl", query => $input, type => "intranet", @@ -78,222 +38,49 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user({ flagsrequired => { catalogue => 1 }, debug => 1, }); +$template->param( frameworkcode => $input->param('frameworkcode')||'' ); -$template->param( frameworkcode => $frameworkcode, ); - -if ( $op ne "do_search" ) { - my $sth = $dbh->prepare("select id,host,name,checked from z3950servers order by host"); - $sth->execute(); - my $serverloop = $sth->fetchall_arrayref( {} ); - $template->param( - isbn => $isbn, - issn => $issn, - lccn => $lccn, - lccall => $lccall, - title => $title, - author => $author, - controlnumber=> $controlnumber, - stdid => $stdid, - srchany => $srchany, - serverloop => $serverloop, - opsearch => "search", - biblionumber => $biblionumber, - ); - output_html_with_http_headers $input, $cookie, $template->output; +my $op= $input->param('op')||''; +if($op ne "do_search") { + show_search_form(); } else { - my @id = $input->param('id'); - - if ( not defined @id ) { - # empty server list -> report and exit - $template->param( emptyserverlist => 1 ); - output_html_with_http_headers $input, $cookie, $template->output; - exit; - } - - my @oConnection; - my @oResult; - my @errconn; - my $s = 0; - my $query; - my $nterms; - if ($isbn || $issn) { - $term=$isbn if ($isbn); - $term=$issn if ($issn); - $query .= " \@or \@attr 1=8 \"$term\" \@attr 1=7 \"$term\" "; - $nterms++; - } - if ($title) { - utf8::decode($title); - $query .= " \@attr 1=4 \"$title\" "; - $nterms++; - } - if ($author) { - utf8::decode($author); - $query .= " \@attr 1=1003 \"$author\" "; - $nterms++; - } - if ($dewey) { - $query .= " \@attr 1=16 \"$dewey\" "; - $nterms++; - } - if ($subject) { - utf8::decode($subject); - $query .= " \@attr 1=21 \"$subject\" "; - $nterms++; - } - if ($lccn) { - $query .= " \@attr 1=9 $lccn "; - $nterms++; - } - if ($lccall) { - $query .= " \@attr 1=16 \@attr 2=3 \@attr 3=1 \@attr 4=1 \@attr 5=1 \@attr 6=1 \"$lccall\" "; - $nterms++; - } - if ($controlnumber) { - $query .= " \@attr 1=12 \"$controlnumber\" "; - $nterms++; - } - if ($stdid) { - $query .= " \@attr 1=1007 \"$stdid\" "; - $nterms++; - } - if ($srchany) { - $query .= " \@attr 1=1016 \"$srchany\" "; - $nterms++; - } -for my $i (1..$nterms-1) { - $query = "\@and " . $query; + run_search(); } -warn "query ".$query if $DEBUG; - - foreach my $servid (@id) { - my $sth = $dbh->prepare("select * from z3950servers where id=?"); - $sth->execute($servid); - while ( $server = $sth->fetchrow_hashref ) { - warn "serverinfo ".join(':',%$server) if $DEBUG; - my $option1 = new ZOOM::Options(); - $option1->option('async' => 1); - $option1->option('elementSetName', 'F'); - $option1->option('databaseName', $server->{db}); - $option1->option('user', $server->{userid} ) if $server->{userid}; - $option1->option('password', $server->{password}) if $server->{password}; - $option1->option('preferredRecordSyntax', $server->{syntax}); - $oConnection[$s] = create ZOOM::Connection($option1) - || $DEBUG - && warn( "" . $oConnection[$s]->errmsg() ); - warn( "server data", $server->{name}, $server->{port} ) if $DEBUG; - $oConnection[$s]->connect( $server->{host}, $server->{port} ) - || $DEBUG - && warn( "" . $oConnection[$s]->errmsg() ); - $serverhost[$s] = $server->{host}; - $servername[$s] = $server->{name}; - $encoding[$s] = ($server->{encoding}?$server->{encoding}:"iso-5426"); - $s++; - } ## while fetch - } # foreach - my $nremaining = $s; - my $firstresult = 1; +output_html_with_http_headers $input, $cookie, $template->output; - for ( my $z = 0 ; $z < $s ; $z++ ) { - warn "doing the search" if $DEBUG; - $oResult[$z] = $oConnection[$z]->search_pqf($query) - || $DEBUG - && warn( "somthing went wrong: " . $oConnection[$s]->errmsg() ); +#------------------------------------------------------------------------------- - # $oResult[$z] = $oConnection[$z]->search_pqf($query); - } - - AGAIN: - my $k; - my $event; - while ( ( $k = ZOOM::event( \@oConnection ) ) != 0 ) { - $event = $oConnection[ $k - 1 ]->last_event(); - warn( "connection ", $k - 1, ": event $event (", - ZOOM::event_str($event), ")\n" ) - if $DEBUG; - last if $event == ZOOM::Event::ZEND; - } - - if ( $k != 0 ) { - $k--; - warn $serverhost[$k] if $DEBUG; - my ( $error, $errmsg, $addinfo, $diagset ) = - $oConnection[$k]->error_x(); - if ($error) { - if ($error =~ m/^(10000|10007)$/ ) { - push(@errconn, {'server' => $serverhost[$k]}); - } - $DEBUG and warn "$k $serverhost[$k] error $query: $errmsg ($error) $addinfo\n"; - } - else { - my $numresults = $oResult[$k]->size(); - my $i; - my $result = ''; - if ( $numresults > 0 ) { - for ($i = 0; $i < (($numresults < 20) ? $numresults : 20); $i++) { - my $rec = $oResult[$k]->record($i); - if ($rec) { - my $marcrecord; - $marcdata = $rec->raw(); - - my ($charset_result, $charset_errors); - ($marcrecord, $charset_result, $charset_errors) = - MarcToUTF8Record($marcdata, C4::Context->preference('marcflavour'), $encoding[$k]); -####WARNING records coming from Z3950 clients are in various character sets MARC8,UTF8,UNIMARC etc -## In HEAD i change everything to UTF-8 -# In rel2_2 i am not sure what encoding is so no character conversion is done here -##Add necessary encoding changes to here -TG - my $oldbiblio = TransformMarcToKoha( $dbh, $marcrecord, "" ); - $oldbiblio->{isbn} =~ s/ |-|\.//g if $oldbiblio->{isbn}; - # pad | and ( with spaces to allow line breaks in the HTML - $oldbiblio->{isbn} =~ s/\|/ \| /g if $oldbiblio->{isbn}; - $oldbiblio->{isbn} =~ s/\(/ \(/g if $oldbiblio->{isbn}; +sub show_search_form { + my $dbh= C4::Context->dbh; + my $sth= $dbh->prepare("select id,host,name,checked from z3950servers order by host"); + $sth->execute(); + my $serverloop = $sth->fetchall_arrayref( {} ); + $template->param( + biblionumber => $input->param('biblionumber') || 0, + serverloop => $serverloop, + opsearch => "search", + title => $input->param('title')||'', + isbn => $input->param('isbn')||'', + lccall => $input->param('lccall')||'', + controlnumber=> $input->param('controlnumber')||'', + srchany => $input->param('srchany')||'', + author => $input->param('author')||'', + subject => $input->param('subject')||'', + dewey => $input->param('dewey')||'', + stdid => $input->param('stdid')||'', + ); +} - $oldbiblio->{issn} =~ s/ |-|\.//g if $oldbiblio->{issn}; - # pad | and ( with spaces to allow line breaks in the HTML - $oldbiblio->{issn} =~ s/\|/ \| /g if $oldbiblio->{issn}; - $oldbiblio->{issn} =~ s/\(/ \(/g if $oldbiblio->{issn}; - my ( - $notmarcrecord, $alreadyindb, $alreadyinfarm, - $imported, $breedingid - ) - = ImportBreeding( $marcdata, 2, $serverhost[$k], $encoding[$k], $random, 'z3950' ); - my %row_data; - $row_data{server} = $servername[$k]; - $row_data{isbn} = $oldbiblio->{isbn}; - $row_data{lccn} = $oldbiblio->{lccn}; - $row_data{title} = $oldbiblio->{title}; - $row_data{author} = $oldbiblio->{author}; - $row_data{date} = $oldbiblio->{copyrightdate}; - $row_data{edition} = $oldbiblio->{editionstatement}; - $row_data{breedingid} = $breedingid; - $row_data{biblionumber} = $biblionumber; - push( @breeding_loop, \%row_data ); - - } else { - push(@breeding_loop,{'server'=>$servername[$k],'title'=>join(': ',$oConnection[$k]->error_x()),'breedingid'=>-1,'biblionumber'=>-1}); - } # $rec - } - } #$numresults - } - } # if $k !=0 - $numberpending = $nremaining - 1; - $template->param( - breeding_loop => \@breeding_loop, - server => $servername[$k], - numberpending => $numberpending, - biblionumber => $biblionumber, - errconn => \@errconn - ); - - output_html_with_http_headers $input, $cookie, $template->output if $numberpending == 0; +#------------------------------------------------------------------------------- - # print $template->output if $firstresult !=1; - $firstresult++; +sub run_search { + my ($breedingref, $error_ref)= C4::Breeding::z3950_search($input); + $template->param( + breeding_loop => $breedingref, + biblionumber => $input->param('biblionumber') || 0, + errconn => $error_ref, + ); +} - MAYBE_AGAIN: - if ( --$nremaining > 0 ) { - goto AGAIN; - } -} ## if op=search +#------------------------------------------------------------------------------- --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/z3950servers.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/z3950servers.tt @@ -226,6 +226,8 @@ [% END %] +
  • +
  • --- a/koha-tmpl/intranet-tmpl/prog/en/xslt/MARC21toUNIMARC.xsl +++ a/koha-tmpl/intranet-tmpl/prog/en/xslt/MARC21toUNIMARC.xsl @@ -0,0 +1,1187 @@ + + + + + + + + + + + + 00000 + + + p + + + + + + m + n + + + + + + m + m + + + + + 00000 + + + 2 + 3 + 3 + + + + + + n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + b|| + c|| + a|| + d|| + e|| + k|| + m|| + ||| + u|| + u|| + + + + + a + b + d + e + f + g + h + u + y + z + | + y + + + + + 0 + 1 + + + + + + + + + + + b + y + + + + + + + + + + + + + + + + + + + + a + | + + + + + y + + + + + + + + + + y + + + + + + + + + a + b + c + z + | + z + + + + + a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + u + y + z + | + | + y + + + + + a + b + u + y + | + | + u + + + + + a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + r + z + | + z + + + + + | + | + | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bla + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + 1 + + + + + + + + + + + + + 0 + + + + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 00 + 01 + 04 + uu + zz + zz + + + + + + + + + + + + + + + + --- a/koha-tmpl/intranet-tmpl/prog/en/xslt/UNIMARCtoMARC21.xsl +++ a/koha-tmpl/intranet-tmpl/prog/en/xslt/UNIMARCtoMARC21.xsl @@ -0,0 +1,523 @@ + + + + + + + + + + + + + + + + 001 + + + + + + + + + + + + + + + + + + + + + + + + + + + 00000na + + + + + m + + a2200000u + + + i + + + + + + + 4500 + + + + + + + + + + + + + + + + + + + + + + + + + + + s + + + + + + + + + + + + + xx + + + + ||||||||||||||||| + + + + d + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 700 + + + + , + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 111 + + + 110 + + + + + + + + + + + , + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 200 + + + + + + + + + + + : + + + + + + + + + + + + ; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + , + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 711 + + + 710 + + + + + + + + + + + , + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + --