Bug 13642 - Adding new features for Dublin Core metadata

When Koha export a bibliographic record to DC, makes it in XML format.
This XML not follows the DC-XML recommendations as should be: elements
in uppercase eg. dc:Date, dc:Creator, section 4.2, recommendation 4
explain that "The property names for the 15 DC elements should be all
lower-case." eg. dc:date, dc:creator" and section "4.3 Example - a
simple DC record", xsi:schemaLocation="http://example.org/myapp/
http://example.org/myapp/schema.xsd" schema does not exist.

NOTE: This new feature implement the XSLT transformation for OAI-DC,
SRW-DC and RDF-DC

Test plan
---------------
1) Download Dublin Core file from record detail page. Open up the file,
   and make sure that the document not follows the DC-XML
   recommendations as should be.
2) Apply patch.
3) Go to whichever bib record in OPAC or staff and click on Save >
   Dublin Core.  A modal will display, prove all options.
4) Change the system preference 'Opac ExportOptions' by enabling and
   disabling Dublin Core and try to download a record.
5) Try several bibliographic records in any format (book, magazine, DVD,
   etc.) to confirm that properly exported.
6) Test with all marc flavours.

Sponsored-by: Universidad de El Salvador

Signed-off-by: Frederic Demians <f.demians@tamil.fr>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>

Signed-off-by: Brendan A Gallagher <brendan@bywatersolutions.com>
This commit is contained in:
Hector Castro 2015-11-08 23:22:47 -06:00 committed by Brendan A Gallagher
parent b86143b7b8
commit e3139601c6
9 changed files with 160 additions and 42 deletions

View File

@ -2,6 +2,7 @@ package C4::Record;
#
# Copyright 2006 (C) LibLime
# Parts copyright 2010 BibLibre
# Part copyright 2015 Universidad de El Salvador
#
# This file is part of Koha.
#
@ -25,7 +26,6 @@ use strict;
# please specify in which methods a given module is used
use MARC::Record; # marc2marcxml, marcxml2marc, changeEncoding
use MARC::File::XML; # marc2marcxml, marcxml2marc, changeEncoding
use MARC::Crosswalk::DublinCore; # marc2dcxml
use Biblio::EndnoteStyle;
use Unicode::Normalize; # _entity_encode
use C4::Biblio; #marc2bibtex
@ -36,6 +36,8 @@ use YAML; #marcrecords2csv
use Template;
use Text::CSV::Encoded; #marc2csv
use Koha::SimpleMARC qw(read_field);
use Koha::XSLT_Handler;
use Carp;
use vars qw($VERSION @ISA @EXPORT);
@ -220,51 +222,92 @@ sub marcxml2marc {
=head2 marc2dcxml - Convert from ISO-2709 to Dublin Core
my ($error,$dcxml) = marc2dcxml($marc,$qualified);
my dcxml = marc2dcxml ($marc, $xml, $biblionumber, $format);
Returns a DublinCore::Record object, will eventually return a Dublin Core scalar
EXAMPLE
FIXME: should return actual XML, not just an object
my dcxml = marc2dcxml (undef, undef, 1, "oaidc");
Convert MARC or MARCXML to Dublin Core metadata (XSLT Transformation),
optionally can get an XML directly from database (biblioitems.marcxml)
without item information. This method take into consideration the syspref
'marcflavour' (UNIMARC, MARC21 and NORMARC).
Return an XML file with the format defined in C<$format>
C<$marc> - an ISO-2709 scalar or MARC::Record object
C<$qualified> - specify whether qualified Dublin Core should be used in the input or output [0]
C<$xml> - a MARCXML file
C<$biblionumber> - obtain the record directly from database (biblioitems.marcxml)
C<$format> - accept three type of DC formats (oaidc, srwdc, and rdfdc )
=cut
sub marc2dcxml {
my ($marc,$qualified) = @_;
my $error;
# test if it's already a MARC::Record object, if not, make it one
my $marc_record_obj;
if ($marc =~ /^MARC::Record/) { # it's already a MARC::Record object
$marc_record_obj = $marc;
} else { # it's not a MARC::Record object, make it one
eval { $marc_record_obj = MARC::Record->new_from_usmarc($marc) }; # handle exceptions
my ( $marc, $xml, $biblionumber, $format ) = @_;
# conversion to MARC::Record object failed, populate $error
if ($@) {
$error .="\nCreation of MARC::Record object failed: ".$MARC::File::ERROR;
}
}
my $crosswalk = MARC::Crosswalk::DublinCore->new;
if ($qualified) {
$crosswalk = MARC::Crosswalk::DublinCore->new( qualified => 1 );
}
my $dcxml = $crosswalk->as_dublincore($marc_record_obj);
my $dcxmlfinal = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
$dcxmlfinal .= "<metadata
xmlns=\"http://example.org/myapp/\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xsi:schemaLocation=\"http://example.org/myapp/ http://example.org/myapp/schema.xsd\"
xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
xmlns:dcterms=\"http://purl.org/dc/terms/\">";
# global variables
my ( $marcxml, $record, $output );
foreach my $element ( $dcxml->elements() ) {
$dcxmlfinal.="<"."dc:".$element->name().">".$element->content()."</"."dc:".$element->name().">\n";
# set the default path for intranet xslts
# differents xslts to process (OAIDC, SRWDC and RDFDC)
my $xsl = C4::Context->config('intrahtdocs') . '/prog/en/xslt/' .
C4::Context->preference('marcflavour') . 'slim2' . uc ( $format ) . '.xsl';
if ( defined $marc ) {
# no need to catch errors or warnings marc2marcxml do it instead
$marcxml = C4::Record::marc2marcxml( $marc );
} elsif ( not defined $xml and defined $biblionumber ) {
# get MARCXML biblio directly from biblioitems.marcxml without item information
$marcxml = C4::Biblio::GetXmlBiblio( $biblionumber );
} else {
$marcxml = $xml;
}
# only proceed if MARC21 or UNIMARC; else clause is executed if marcflavour set it to NORMARC
# generate MARC::Record object to see if not a marcxml record
unless ( C4::Context->preference('marcflavour') eq 'NORMARC' ) {
eval { $record = MARC::Record->new_from_xml(
$marcxml,
'UTF-8',
C4::Context->preference('marcflavour')
);
};
} else {
eval { $record = MARC::Record->new_from_xml(
$marcxml,
'UTF-8',
'MARC21'
);
};
}
# conversion to MARC::Record object failed
if ( $@ ) {
croak "Creation of MARC::Record object failed.";
} elsif ( $record->warnings() ) {
carp "Warnings encountered while processing ISO-2709 record.\n";
my @warnings = $record->warnings();
foreach my $warn (@warnings) {
carp "\t". $warn;
};
} elsif ( $record =~ /^MARC::Record/ ) { # if OK makes xslt transformation
my $xslt_engine = Koha::XSLT_Handler->new;
if ( $format =~ /oaidc|srwdc|rdfdc/ ) {
$output = $xslt_engine->transform( $marcxml, $xsl );
} else {
croak "The format argument ($format) not accepted.\n" .
"Please pass a valid format (oaidc, srwdc, or rdfdc)\n";
}
my $err = $xslt_engine->err; # error number
my $errstr = $xslt_engine->errstr; # error message
if ( $err ) {
croak "Error when processing $errstr Error number: $err\n";
} else {
return $output;
}
}
$dcxmlfinal .= "\n</metadata>";
return ($error,$dcxmlfinal);
}
=head2 marc2modsxml - Convert from ISO-2709 to MODS

View File

@ -50,8 +50,8 @@ if ($op eq "export") {
$marc = marc2bibtex($marc);
$format = "bibtex";
}
elsif ($format =~ /dc/) {
($error,$marc) = marc2dcxml($marc,1);
elsif ($format =~ /dc$/) {
$marc = marc2dcxml(undef, undef, $biblionumber, $format);
$format = "dublin-core.xml";
}
elsif ($format =~ /marc8/) {

View File

@ -217,7 +217,7 @@ CAN_user_serials_create_subscription ) %]
<button class="btn btn-small dropdown-toggle" data-toggle="dropdown"><i class="fa fa-download"></i> Save <span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a href="/cgi-bin/koha/catalogue/export.pl?format=bibtex&amp;op=export&amp;bib=[% biblionumber %]">BIBTEX</a></li>
<li><a href="/cgi-bin/koha/catalogue/export.pl?format=dc&amp;op=export&amp;bib=[% biblionumber %]">Dublin Core (XML)</a></li>
<li><a href="#" data-toggle="modal" data-target="#exportModal_">Dublin Core</a></li>
<li><a href="/cgi-bin/koha/catalogue/export.pl?format=marcxml&amp;op=export&amp;bib=[% biblionumber %]">MARCXML</a></li>
<li><a href="/cgi-bin/koha/catalogue/export.pl?format=marc8&amp;op=export&amp;bib=[% biblionumber %]">MARC (non-Unicode/MARC-8)</a></li>
<li><a href="/cgi-bin/koha/catalogue/export.pl?format=utf8&amp;op=export&amp;bib=[% biblionumber %]">MARC (Unicode/UTF-8)</a></li>
@ -266,3 +266,31 @@ CAN_user_serials_create_subscription ) %]
</form>
</div>
<!--Modal for Dublin Core-->
<div class="modal hide" id="exportModal_" tabindex="-1" role="dialog" aria-labelledby="exportLabelexportModal_" aria-hidden="true">
<div class="modal-header">
<button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3 id="exportLabelexportModal_">Exporting to Dublin Core...</h3>
</div>
<form method="get" action="/cgi-bin/koha/catalogue/export.pl">
<div class="modal-body">
<fieldset>
<input id="input-simple" type="radio" name="format" value="rdfdc">
<label for="input-simple">Simple DC-RDF</label>
<br>
<input id="input-oai" type="radio" name="format" value="oaidc" checked>
<label for="input-oai">OAI-DC</label>
<br>
<input id="input-srw" type="radio" name="format" value="srwdc">
<label for="input-srw">SRW-DC</label>
<br>
</fieldset>
</div>
<div class="modal-footer">
<button type="submit" class="btn">Export</button>
<button class="btn btn-link" data-dismiss="modal" aria-hidden="true">Cancel</button>
</div>
<input type="hidden" name="op" value="export" />
<input type="hidden" name="bib" value="[% biblionumber %]" />
</form>
</div>

View File

@ -1046,7 +1046,7 @@ function verify_images() {
<th>Save Record</th> </tr>
<tr><td> Select download format: <select name="format">
<option value="mods">MODS (XML)</option>
<option value="dc">Dublin Core (XML)</option>
<option data-toggle="modal" data-target="#exportModal_">Dublin Core</option>
<option value="marcxml">MARCXML</option>
<option value="marc8">MARC (non-Unicode/MARC-8)</option>
<option value="utf8">MARC (Unicode/UTF-8)</option> </select>
@ -1079,4 +1079,5 @@ function verify_images() {
</div>
[% END %]
</div>
[% INCLUDE 'intranet-bottom.inc' %]

View File

@ -2,7 +2,7 @@
[% INCLUDE 'doc-head-open.inc' %]
<title>Koha &rsaquo; Catalog &rsaquo; Item details for [% title %] [% FOREACH subtitl IN subtitle %] [% subtitl.subfield %][% END %]</title>
[% INCLUDE 'doc-head-close.inc' %]
<style type="text/css">h3{padding-top: 1em; border-top: 2px solid #CCCCCC;}</style>
<style type="text/css">h3{padding-top: 1em; border-top: 2px solid #CCCCCC;}#exportLabelexportModal_{border-top: 0px;}</style>
[% INCLUDE 'browser-strings.inc' %]
<!--[if lt IE 9]>
<script type="text/javascript" src="[% interface %]/lib/shims/json2.min.js"></script>

View File

@ -38,11 +38,13 @@
<a id="format" class="dropdown-toggle" data-toggle="dropdown" href="#">Save record <b class="caret"></b></a>
<ul class="dropdown-menu pull-right" role="menu" aria-labelledby="format">
[% FOREACH option IN export_options %]
[% IF option == 'dc' %]
<li><a role="menuitem" href="#" data-toggle="modal" data-target="#exportModal_">Dublin Core</a></li>
[% ELSE %]
<li>
<a role="menuitem" href="/cgi-bin/koha/opac-export.pl?op=export&amp;bib=[% biblionumber %]&amp;format=[% option %]">
[% SWITCH option %]
[% CASE 'bibtex' %]BIBTEX
[% CASE 'dc' %]Dublin Core (XML)
[% CASE 'endnote' %]EndNote
[% CASE 'marcxml' %]MARCXML
[% CASE 'marc8' %]MARC (non-Unicode/MARC-8)
@ -54,6 +56,7 @@
[% END %]
</a>
</li>
[% END %]
[% END %]
</ul>
</div>

View File

@ -1150,6 +1150,35 @@
</div> <!-- / .container-fluid -->
</div> <!-- / .main -->
<!-- Dublin Core Modal Form -->
<div class="modal hide" id="exportModal_" tabindex="-1" role="dialog" aria-labelledby="exportLabelexportModal_" aria-hidden="true">
<div class="modal-header">
<button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3 class="modal-title" id="exportModalLabel">Exporting to Dublin Core...</h3>
</div>
<form method="get" action="/cgi-bin/koha/opac-export.pl">
<div class="modal-body">
<fieldset id="dc_fieldset">
<input id="input-simple" type="radio" name="format" value="rdfdc">
<label class="label_dc" for="input-simple">Simple DC-RDF</label>
<br>
<input id="input-oai" type="radio" name="format" value="oaidc">
<label class="label_dc" for="input-oai">OAI-DC</label>
<br>
<input id="input-srw" type="radio" name="format" value="srwdc">
<label class="label_dc" for="input-srw">SRW-DC</label>
<br>
<input type="hidden" name="op" value="export">
<input type="hidden" name="bib" value="[% biblionumber %]">
</fieldset>
</div>
<div class="modal-footer">
<button type="submit" class="btn">Export</button>
<button class="btn btn-link" data-dismiss="modal" aria-hidden="true">Cancel</button>
</div>
</form>
</div>
[% INCLUDE 'opac-bottom.inc' %]
[%# End of template %]

View File

@ -2490,4 +2490,18 @@ a.reviewlink:visited {
font-size: 90%;
}
#dc_fieldset {
border: 1px solid #dddddd;
border-width: 1px;
padding: 5px;
border-radius: 10px
}
.label_dc{
display: inline;
padding: 0px;
margin: 0px;
cursor: pointer;
}
@import "responsive.less";

View File

@ -60,8 +60,8 @@ elsif ($format =~ /bibtex/) {
$marc = marc2bibtex(C4::Biblio::GetMarcBiblio($biblionumber),$biblionumber);
$format = 'bibtex';
}
elsif ($format =~ /dc/) {
($error,$marc) = marc2dcxml($marc,1);
elsif ($format =~ /dc$/) {
$marc = marc2dcxml(undef, undef, $biblionumber, $format);
$format = "dublin-core.xml";
}
elsif ($format =~ /marc8/) {