X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=opac%2Foai.pl;h=038b6d17925ae264c8697c7d35172b63214cb767;hb=05d9510ca91016a78db38cf7bec0bb4a2ea46480;hp=73f352f4f770938fa4c5d724b2ba8d21a9c13f0d;hpb=90b69c9e4078f7aa6c48717ba32dbaf0108677d2;p=koha_fer diff --git a/opac/oai.pl b/opac/oai.pl index 73f352f4f7..038b6d1792 100755 --- a/opac/oai.pl +++ b/opac/oai.pl @@ -1,379 +1,529 @@ #!/usr/bin/perl use strict; +use warnings; +use diagnostics; +use CGI qw/:standard -oldstyle_urls/; +use vars qw( $GZIP ); use C4::Context; -use C4::Biblio; -=head1 OAI-PMH for koha -This file is an implementation of the OAI-PMH protocol for koha. Its purpose -is to share metadata in Dublin core format with harvester like PKP-Harverster. -Presently, all the bibliographic records managed by the runing koha instance -are publicly shared (as the opac is). +BEGIN { + eval { require PerlIO::gzip }; + $GZIP = ($@) ? 0 : 1; +} -=head1 Package MARC::Record::KOHADC +unless ( C4::Context->preference('OAI-PMH') ) { + print + header( + -type => 'text/plain; charset=utf-8', + -charset => 'utf-8', + -status => '404 OAI-PMH service is disabled', + ), + "OAI-PMH service is disabled"; + exit; +} -This package is a sub-class of the MARC::File::USMARC. It add methods and functions -to map the content of a marc record (of any flavor) to Dublin core. -As soon as it is possible, mapping between marc fields and there semantic -are got from ::GetMarcFromKohaField fonction from C4::Biblio (see also the "Koha -to MARC mapping" preferences). +my @encodings = http('HTTP_ACCEPT_ENCODING'); +if ( $GZIP && grep { defined($_) && $_ eq 'gzip' } @encodings ) { + print header( + -type => 'text/xml; charset=utf-8', + -charset => 'utf-8', + -Content-Encoding => 'gzip', + ); + binmode( STDOUT, ":gzip" ); +} +else { + print header( + -type => 'text/xml; charset=utf-8', + -charset => 'utf-8', + ); +} -=cut +binmode( STDOUT, ":utf8" ); +my $repository = C4::OAI::Repository->new(); -package MARC::Record::KOHADC; -use vars ('@ISA'); -@ISA = qw(MARC::Record); +# __END__ Main Prog -use MARC::File::USMARC; -sub new { # Get a MAR::Record as parameter and bless it as MARC::Record::KOHADC - shift; - bless shift; -} +# +# Extends HTTP::OAI::ResumptionToken +# A token is identified by: +# - metadataPrefix +# - from +# - until +# - offset +# +package C4::OAI::ResumptionToken; -sub subfield { - my $self = shift; - my ($t,$sf) = @_; +use strict; +use warnings; +use diagnostics; +use HTTP::OAI; - return $self->SUPER::subfield( @_ ) unless wantarray; +use base ("HTTP::OAI::ResumptionToken"); - my @field = $self->field($t); - my @list = (); - my $f; - foreach $f ( @field ) { - push( @list, $f->subfield( $sf ) ); - } - return @list; -} +sub new { + my ($class, %args) = @_; -sub getfields { -my $marc = shift; -my @result = (); + my $self = $class->SUPER::new(%args); - foreach my $kohafield ( @_ ) { - my ( $field, $subfield ) = ::GetMarcFromKohaField( $kohafield, '' ); - push( @result, $field < 10 ? $marc->field( $field )->as_string() : $marc->subfield( $field, $subfield ) ); + my ($metadata_prefix, $offset, $from, $until); + if ( $args{ resumptionToken } ) { + ($metadata_prefix, $offset, $from, $until) + = split( ':', $args{resumptionToken} ); + } + else { + $metadata_prefix = $args{ metadataPrefix }; + $from = $args{ from } || '1970-01-01'; + $until = $args{ until }; + unless ( $until) { + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime( time ); + $until = sprintf( "%.4d-%.2d-%.2d", $year+1900, $mon+1,$mday ); } -# @result>1 ? \@result : $result[0]; - \@result; -} + $offset = $args{ offset } || 0; + } -sub Status { - my $self = shift; - undef; -} + $self->{ metadata_prefix } = $metadata_prefix; + $self->{ offset } = $offset; + $self->{ from } = $from; + $self->{ until } = $until; -sub Title { - my $self = shift; - $self->getfields('biblio.title'); -} + $self->resumptionToken( + join( ':', $metadata_prefix, $offset, $from, $until ) ); + $self->cursor( $offset ); -sub Creator { - my $self = shift; - $self->getfields('biblio.author'); + return $self; } -sub Subject { - my $self = shift; - $self->getfields('bibliosubject.subject'); -} +# __END__ C4::OAI::ResumptionToken -sub DateStamp { - my $self = shift; - my ($d,$h) = split( ' ', $self->{'biblio.timestamp'} ); - $d . "T" . $h . "Z"; -} -sub Date { - my $self = shift; - my ($str) = @{$self->getfields('biblioitems.publicationyear')}; - my ($y,$m,$d) = (substr($str,0,4), substr($str,4,2), substr($str,6,2)); - $y=1970 unless($y>0); $m=1 unless($m>0); $d=1 unless($d>0); +package C4::OAI::Identify; - sprintf( "%.4d-%.2d-%.2d", $y,$m,$d); -} +use strict; +use warnings; +use diagnostics; +use HTTP::OAI; +use C4::Context; -sub Description { - my $self = shift; - undef; -} +use base ("HTTP::OAI::Identify"); -sub Identifier { - my $self = shift; - my $id = $self->getfields('biblio.biblionumber')->[0]; - -# get url of this script and assume that OAI server is in the same place as opac-detail script -# and build a direct link to the record. - my $uri = $ENV{'SCRIPT_URI'}; - $uri= "http://" . $ENV{'HTTP_HOST'} . $ENV{'REQUEST_URI'} unless( $uri ); # SCRIPT_URI doesn't exist on all httpd server - $uri =~ s#[^/]+$##; - [ - C4::Context->preference("OAI-PMH:archiveID") .":" .$id, - "${uri}opac-detail.pl?bib=$id", - @{$self->getfields('biblioitems.isbn', 'biblioitems.issn')} - ]; -} +sub new { + my ($class, $repository) = @_; -sub Language { - my $self = shift; - undef; -} + my ($baseURL) = $repository->self_url() =~ /(.*)\?.*/; + my $self = $class->SUPER::new( + baseURL => $baseURL, + repositoryName => C4::Context->preference("LibraryName"), + adminEmail => C4::Context->preference("KohaAdminEmailAddress"), + MaxCount => C4::Context->preference("OAI-PMH:MaxCount"), + granularity => 'YYYY-MM-DD', + earliestDatestamp => '0001-01-01', + deletedRecord => 'no', + ); -sub Type { - my $self = shift; - $self->getfields('biblioitems.itemtype'); -} + # FIXME - alas, the description element is not so simple; to validate + # against the OAI-PMH schema, it cannot contain just a string, + # but one or more elements that validate against another XML schema. + # For now, simply omitting it. + # $self->description( "Koha OAI Repository" ); -sub Publisher { - my $self = shift; - $self->getfields('biblioitems.publishercode'); -} + $self->compression( 'gzip' ); -sub Set { -my $set = &OAI::KOHA::Set(); - [ map( $_=$_->[0], @$set) ]; + return $self; } -=head1 The OAI::KOHA package +# __END__ C4::OAI::Identify -This package is a subclass of the OAI::DC data provider. It overides needed methods -and provide the links between the OAI-PMH request and the koha application. -The data used in answers are from the koha table I. -=cut -package OAI::KOHA; +package C4::OAI::ListMetadataFormats; -use C4::OAI::DC; -use vars ('@ISA'); -@ISA = ("C4::OAI::DC"); +use strict; +use warnings; +use diagnostics; +use HTTP::OAI; -=head2 Set +use base ("HTTP::OAI::ListMetadataFormats"); -return the Set list to the I query. Data are from the 'OAI-PMH:Set' preference. +sub new { + my ($class, $repository) = @_; -=cut + my $self = $class->SUPER::new(); -sub Set { -# [ -# ['BRISE','Experimental unimarc set for BRISE network'], -# ['BRISE:EMSE','EMSE set in BRISE network'] -# ]; -# -# A blinder correctement - [ map( $_ = [ split(",", $_)], split( "\n",C4::Context->preference("OAI-PMH:Set") ) ) ]; + if ( $repository->{ conf } ) { + foreach my $name ( @{ $repository->{ koha_metadata_format } } ) { + my $format = $repository->{ conf }->{ format }->{ $name }; + $self->metadataFormat( HTTP::OAI::MetadataFormat->new( + metadataPrefix => $format->{metadataPrefix}, + schema => $format->{schema}, + metadataNamespace => $format->{metadataNamespace}, ) ); + } + } + else { + $self->metadataFormat( HTTP::OAI::MetadataFormat->new( + metadataPrefix => 'oai_dc', + schema => 'http://www.openarchives.org/OAI/2.0/oai_dc.xsd', + metadataNamespace => 'http://www.openarchives.org/OAI/2.0/oai_dc/' + ) ); + $self->metadataFormat( HTTP::OAI::MetadataFormat->new( + metadataPrefix => 'marcxml', + schema => 'http://www.loc.gov/MARC21/slim http://www.loc.gov/ standards/marcxml/schema/MARC21slim.xsd', + metadataNamespace => 'http://www.loc.gov/MARC21/slim http://www.loc.gov/ standards/marcxml/schema/MARC21slim' + ) ); + } + + return $self; } -=head2 new +# __END__ C4::OAI::ListMetadataFormats -The new method is the constructor for this class. It doesn't have any parameters and -get required data from koha preferences. Koha I is used to identify the -OAI-PMH repository, I is used to set the maximun number of records -returned at the same time in answers to I or I -queries. -The method return a blessed reference. -=cut +package C4::OAI::Record; -# constructor -sub new -{ - my $classname = shift; - my $self = $classname->SUPER::new (); +use strict; +use warnings; +use diagnostics; +use HTTP::OAI; +use HTTP::OAI::Metadata::OAI_DC; - # set configuration - $self->{'repositoryName'} = C4::Context->preference("LibraryName"); - $self->{'MaxCount'} = C4::Context->preference("OAI-PMH:MaxCount"); - $self->{'adminEmail'} = C4::Context->preference("KohaAdminEmailAddress"); +use base ("HTTP::OAI::Record"); - bless $self, $classname; - return $self; -} +sub new { + my ($class, $repository, $marcxml, $timestamp, %args) = @_; -=head2 dispose + my $self = $class->SUPER::new(%args); -The dispose method is used as a destructor. It call just the SUPER::dispose method. + $timestamp =~ s/ /T/, $timestamp .= 'Z'; + $self->header( new HTTP::OAI::Header( + identifier => $args{identifier}, + datestamp => $timestamp, + ) ); -=cut + my $parser = XML::LibXML->new(); + my $record_dom = $parser->parse_string( $marcxml ); + my $format = $args{metadataPrefix}; + if ( $format ne 'marcxml' ) { + $record_dom = $repository->stylesheet($format)->transform( $record_dom ); + } + $self->metadata( HTTP::OAI::Metadata->new( dom => $record_dom ) ); -# destructor -sub dispose -{ - my ($self) = @_; - $self->SUPER::dispose (); + return $self; } -# now date -sub now { -my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime( time ); +# __END__ C4::OAI::Record - sprintf( "%.4d-%.2d-%.2d", $year+1900, $mon+1,$mday ); -} -# build the resumptionTocken fom ($metadataPrefix,$offset,$from,$until) -=head2 buildResumptionToken and parseResumptionToken +package C4::OAI::GetRecord; -Theses two functions are used to manage resumption tokens. The choosed syntax is simple as -possible, a token is only the metadata prefix, the offset in the full answer, the from and -the until date (in the yyyy-mm-dd format) joined by ':' caracter. +use strict; +use warnings; +use diagnostics; +use HTTP::OAI; + +use base ("HTTP::OAI::GetRecord"); + + +sub new { + my ($class, $repository, %args) = @_; + + my $self = HTTP::OAI::GetRecord->new(%args); + + my $dbh = C4::Context->dbh; + my $sth = $dbh->prepare(" + SELECT marcxml, timestamp + FROM biblioitems + WHERE biblionumber=? " ); + my $prefix = $repository->{koha_identifier} . ':'; + my ($biblionumber) = $args{identifier} =~ /^$prefix(.*)/; + $sth->execute( $biblionumber ); + my ($marcxml, $timestamp); + unless ( ($marcxml, $timestamp) = $sth->fetchrow ) { + return HTTP::OAI::Response->new( + requestURL => $repository->self_url(), + errors => [ new HTTP::OAI::Error( + code => 'idDoesNotExist', + message => "There is no biblio record with this identifier", + ) ] , + ); + } -I get the four elements as parameters and return the ':' separated -string. + #$self->header( HTTP::OAI::Header->new( identifier => $args{identifier} ) ); + $self->record( C4::OAI::Record->new( + $repository, $marcxml, $timestamp, %args ) ); -I is used to set the default values to the from and until date, the -metadata prefix using the resumption tocken if necessary. This function have four parameters -(from,until,metadata prefix and resumption tocken) which can be undefined and return every -time this list of values correctly set. The missing values are set with defaults: offset=0, -from= 1970-01-01 and until is set to current date. + return $self; +} -=cut +# __END__ C4::OAI::GetRecord -sub buildResumptionToken { - join( ':', @_ ); -} -# parse the resumptionTocken -sub parseResumptionToken { -my ($from, $until, $metadataPrefix, $resumptionToken) = @_; -my $offset = 0; - if( $resumptionToken ) { - ($metadataPrefix,$offset,$from,$until) = split( ':', $resumptionToken ); - } +package C4::OAI::ListIdentifiers; - $from = "1970-01-01" unless( $from ); - $until = &now unless( $until ); - ($metadataPrefix, $offset, $from, $until ); +use strict; +use warnings; +use diagnostics; +use HTTP::OAI; + +use base ("HTTP::OAI::ListIdentifiers"); + + +sub new { + my ($class, $repository, %args) = @_; + + my $self = HTTP::OAI::ListIdentifiers->new(%args); + + my $token = new C4::OAI::ResumptionToken( %args ); + my $dbh = C4::Context->dbh; + my $sql = "SELECT biblionumber, timestamp + FROM biblioitems + WHERE timestamp >= ? AND timestamp <= ? + LIMIT " . $repository->{koha_max_count} . " + OFFSET " . $token->{offset}; + my $sth = $dbh->prepare( $sql ); + $sth->execute( $token->{from}, $token->{until} ); + + my $pos = $token->{offset}; + while ( my ($biblionumber, $timestamp) = $sth->fetchrow ) { + $timestamp =~ s/ /T/, $timestamp .= 'Z'; + $self->identifier( new HTTP::OAI::Header( + identifier => $repository->{ koha_identifier} . ':' . $biblionumber, + datestamp => $timestamp, + ) ); + $pos++; + } + $self->resumptionToken( new C4::OAI::ResumptionToken( + metadataPrefix => $token->{metadata_prefix}, + from => $token->{from}, + until => $token->{until}, + offset => $pos ) ) if ($pos > $token->{offset}); + + return $self; } -=head2 Archive_ListSets +# __END__ C4::OAI::ListIdentifiers -return the full list Set to the I query. Data are from the 'OAI-PMH:Set' preference. -=cut -# get full list of sets from the archive -sub Archive_ListSets -{ - &Set(); +package C4::OAI::ListRecords; + +use strict; +use warnings; +use diagnostics; +use HTTP::OAI; + +use base ("HTTP::OAI::ListRecords"); + + +sub new { + my ($class, $repository, %args) = @_; + + my $self = HTTP::OAI::ListRecords->new(%args); + + my $token = new C4::OAI::ResumptionToken( %args ); + my $dbh = C4::Context->dbh; + my $sql = "SELECT biblionumber, marcxml, timestamp + FROM biblioitems + WHERE timestamp >= ? AND timestamp <= ? + LIMIT " . $repository->{koha_max_count} . " + OFFSET " . $token->{offset}; + my $sth = $dbh->prepare( $sql ); + $sth->execute( $token->{from}, $token->{until} ); + + my $pos = $token->{offset}; + while ( my ($biblionumber, $marcxml, $timestamp) = $sth->fetchrow ) { + $self->record( C4::OAI::Record->new( + $repository, $marcxml, $timestamp, + identifier => $repository->{ koha_identifier } . ':' . $biblionumber, + metadataPrefix => $token->{metadata_prefix} + ) ); + $pos++; + } + $self->resumptionToken( new C4::OAI::ResumptionToken( + metadataPrefix => $token->{metadata_prefix}, + from => $token->{from}, + until => $token->{until}, + offset => $pos ) ) if ($pos > $token->{offset}); + + return $self; } - -=head2 Archive_GetRecord -This method select the record specified as its first parameter from the koha I -table and return a reference to a MARC::Record::KOHADC object. +# __END__ C4::OAI::ListRecords -=cut -# get a single record from the archive -sub Archive_GetRecord -{ - my ($self, $identifier, $metadataFormat) = @_; - my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare("SELECT biblionumber,timestamp FROM biblio WHERE biblionumber=?"); - my $prefixID = C4::Context->preference("OAI-PMH:archiveID"); $prefixID=qr{$prefixID:}; - $identifier =~ s/^$prefixID//; +package C4::OAI::Repository; - $sth->execute( $identifier ); +use base ("HTTP::OAI::Repository"); - if( my $r = $sth->fetchrow_hashref() ) { - my $marc = new MARC::Record::KOHADC( ::GetMarcBiblio( $identifier ) ); - $marc->{'biblio.timestamp'} = $r->{'timestamp'}; - return $marc ; - } +use strict; +use warnings; +use diagnostics; - $self->AddError ('idDoesNotExist', 'The value of the identifier argument is unknown or illegal in this repository'); - undef; -} +use HTTP::OAI; +use HTTP::OAI::Repository qw/:validate/; -=head2 Archive_ListRecords +use XML::SAX::Writer; +use XML::LibXML; +use XML::LibXSLT; +use YAML::Syck qw( LoadFile ); +use CGI qw/:standard -oldstyle_urls/; -This method return a list of 'MaxCount' references to MARC::Record::KOHADC object build from the -koha I table according to its parameters : set, from and until date, metadata prefix -and resumption token. +use C4::Context; +use C4::Biblio; -=cut -# list metadata records from the archive -sub Archive_ListRecords -{ - my ($self, $set, $from, $until, $metadataPrefix, $resumptionToken) = @_; - - my @allrows = (); - my $marc; - my $offset; - my $tokenInfo; - my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare("SELECT biblionumber,timestamp FROM biblio WHERE DATE(timestamp) >= ? and DATE(timestamp) <= ? LIMIT ? OFFSET ?"); - my $count; - - ($metadataPrefix, $offset, $from, $until ) = &parseResumptionToken($from, $until, $metadataPrefix, $resumptionToken); - -warn( "Archive_ListRecords : $set, $from, $until, $metadataPrefix, $resumptionToken\n"); - $sth->execute( $from,$until,$self->{'MaxCount'}?$self->{'MaxCount'}:100000, $offset ); - - while( my $r = $sth->fetchrow_hashref() ) { - my $marc = new MARC::Record::KOHADC( ::GetMarcBiblio( $r->{'biblionumber'} ) ); - $marc->{'biblio.timestamp'} = $r->{'timestamp'}; - push( @allrows, $marc ); - } - - $sth = $dbh->prepare("SELECT count(*) FROM biblioitems WHERE DATE(timestamp) >= ? and DATE(timestamp) <= ?"); - $sth->execute($from, $until); - ( $count ) = $sth->fetchrow_array(); - - unless( @allrows ) { - $self->AddError ('noRecordsMatch', 'The combination of the values of arguments results in an empty set'); - } - - if( $offset + $self->{'MaxCount'} < $count ) { # Not at the end - $offset = $offset + $self->{'MaxCount'}; - $resumptionToken = &buildResumptionToken($metadataPrefix,$offset,$from,$until); - $tokenInfo = { 'completeListSize' => $count, 'cursor' => $offset }; - } - else { - $resumptionToken = ''; - $tokenInfo = {}; - } - ( \@allrows, $resumptionToken, $metadataPrefix, $tokenInfo ); -} +sub new { + my ($class, %args) = @_; + my $self = $class->SUPER::new(%args); -package main; + $self->{ koha_identifier } = C4::Context->preference("OAI-PMH:archiveID"); + $self->{ koha_max_count } = C4::Context->preference("OAI-PMH:MaxCount"); + $self->{ koha_metadata_format } = ['oai_dc', 'marcxml']; + $self->{ koha_stylesheet } = { }; # Build when needed -=head1 Main package + # Load configuration file if defined in OAI-PMH:ConfFile syspref + if ( my $file = C4::Context->preference("OAI-PMH:ConfFile") ) { + $self->{ conf } = LoadFile( $file ); + my @formats = keys %{ $self->{conf}->{format} }; + $self->{ koha_metadata_format } = \@formats; + } -The I
function is the starting point of the service. The first step is -to verify if the service is enable using the 'OAI-PMH' preference value -(See Koha systeme preferences). + # Check for grammatical errors in the request + my @errs = validate_request( CGI::Vars() ); -If the service is enable, it create a new instance of the OAI::KOHA data -provider (see before) and run the service. + # Is metadataPrefix supported by the respository? + my $mdp = param('metadataPrefix') || ''; + if ( $mdp && !grep { $_ eq $mdp } @{$self->{ koha_metadata_format }} ) { + push @errs, new HTTP::OAI::Error( + code => 'cannotDisseminateFormat', + message => "Dissemination as '$mdp' is not supported", + ); + } -=cut + my $response; + if ( @errs ) { + $response = HTTP::OAI::Response->new( + requestURL => self_url(), + errors => \@errs, + ); + } + else { + my %attr = CGI::Vars(); + my $verb = delete( $attr{verb} ); + if ( grep { $_ eq $verb } qw( ListSets ) ) { + $response = HTTP::OAI::Response->new( + requestURL => $self->self_url(), + errors => [ new HTTP::OAI::Error( + code => 'noSetHierarchy', + message => "Koha repository doesn't have sets", + ) ] , + ); + } + elsif ( $verb eq 'Identify' ) { + $response = C4::OAI::Identify->new( $self ); + } + elsif ( $verb eq 'ListMetadataFormats' ) { + $response = C4::OAI::ListMetadataFormats->new( $self ); + } + elsif ( $verb eq 'GetRecord' ) { + $response = C4::OAI::GetRecord->new( $self, %attr ); + } + elsif ( $verb eq 'ListRecords' ) { + $response = C4::OAI::ListRecords->new( $self, %attr ); + } + elsif ( $verb eq 'ListIdentifiers' ) { + $response = C4::OAI::ListIdentifiers->new( $self, %attr ); + } + } -sub disable { - print "Status:404 OAI-PMH service is disabled\n"; - print "Content-type: text/plain\n\n"; + $response->set_handler( XML::SAX::Writer->new( Output => *STDOUT ) ); + $response->generate; - print "OAI-PMH service is disable.\n"; + bless $self, $class; + return $self; } -sub main -{ - return &disable() unless( C4::Context->preference('OAI-PMH') ); - my $OAI = new OAI::KOHA(); - $OAI->Run; - $OAI->dispose; +sub stylesheet { + my ( $self, $format ) = @_; + + my $stylesheet = $self->{ koha_stylesheet }->{ $format }; + unless ( $stylesheet ) { + my $xsl_file = $self->{ conf } + ? $self->{ conf }->{ format }->{ $format }->{ xsl_file } + : ( C4::Context->config('intrahtdocs') . + '/prog/en/xslt/' . + C4::Context->preference('marcflavour') . + 'slim2OAIDC.xsl' ); + my $parser = XML::LibXML->new(); + my $xslt = XML::LibXSLT->new(); + my $style_doc = $parser->parse_file( $xsl_file ); + $stylesheet = $xslt->parse_stylesheet( $style_doc ); + $self->{ koha_stylesheet }->{ $format } = $stylesheet; + } + + return $stylesheet; } -main; -1; + +=head1 NAME + +C4::OAI::Repository - Handles OAI-PMH requests for a Koha database. + +=head1 SYNOPSIS + + use C4::OAI::Repository; + + my $repository = C4::OAI::Repository->new(); + +=head1 DESCRIPTION + +This object extend HTTP::OAI::Repository object. +It accepts OAI-PMH HTTP requests and returns result. + +This OAI-PMH server can operate in a simple mode and extended one. + +In simple mode, repository configuration comes entirely from Koha system +preferences (OAI-PMH:archiveID and OAI-PMH:MaxCount) and the server returns +records in marcxml or dublin core format. Dublin core records are created from +koha marcxml records tranformed with XSLT. Used XSL file is located in +koha-tmpl/intranet-tmpl/prog/en/xslt directory and choosed based on marcflavour, +respecively MARC21slim2OAIDC.xsl for MARC21 and MARC21slim2OAIDC.xsl for +UNIMARC. + +In extende mode, it's possible to parameter other format than marcxml or Dublin +Core. A new syspref OAI-PMH:ConfFile specify a YAML configuration file which +list available metadata formats and XSL file used to create them from marcxml +records. If this syspref isn't set, Koha OAI server works in simple mode. A +configuration file koha-oai.conf can look like that: + + --- + format: + vs: + metadataPrefix: vs + metadataNamespace: http://veryspecial.tamil.fr/vs/format-pivot/1.1/vs + schema: http://veryspecial.tamil.fr/vs/format-pivot/1.1/vs.xsd + xsl_file: /usr/local/koha/xslt/vs.xsl + marcxml: + metadataPrefix: marxml + metadataNamespace: http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim + schema: http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd + oai_dc: + metadataPrefix: oai_dc + metadataNamespace: http://www.openarchives.org/OAI/2.0/oai_dc/ + schema: http://www.openarchives.org/OAI/2.0/oai_dc.xsd + xsl_file: /usr/local/koha/koha-tmpl/intranet-tmpl/xslt/UNIMARCslim2OAIDC.xsl + +=cut + + +