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:
parent
b86143b7b8
commit
e3139601c6
111
C4/Record.pm
111
C4/Record.pm
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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/) {
|
||||
|
|
|
|||
|
|
@ -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&op=export&bib=[% biblionumber %]">BIBTEX</a></li>
|
||||
<li><a href="/cgi-bin/koha/catalogue/export.pl?format=dc&op=export&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&op=export&bib=[% biblionumber %]">MARCXML</a></li>
|
||||
<li><a href="/cgi-bin/koha/catalogue/export.pl?format=marc8&op=export&bib=[% biblionumber %]">MARC (non-Unicode/MARC-8)</a></li>
|
||||
<li><a href="/cgi-bin/koha/catalogue/export.pl?format=utf8&op=export&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">×</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>
|
||||
|
|
|
|||
|
|
@ -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' %]
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
[% INCLUDE 'doc-head-open.inc' %]
|
||||
<title>Koha › Catalog › 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>
|
||||
|
|
|
|||
|
|
@ -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&bib=[% biblionumber %]&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>
|
||||
|
|
|
|||
|
|
@ -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">×</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 %]
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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/) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue