From 7158c1da8f4b4108c8ba9f0e5fbdaef6512ad7db Mon Sep 17 00:00:00 2001
From: Hector Castro <hector.hecaxmmx@gmail.com>
Date: Mon, 20 Apr 2015 15:09:11 -0600
Subject: [PATCH] Bug 13642 [ENH] 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.
The recommendation can be consulted at <http://dublincore.org/documents/dc-xml-guidelines/>.
This new feature, adds an ability to export Dublin Core metadata to XML and RDF (including rdfxml, rdfjson, ntriples, turtle, etc.)

Test plan
---------------
1) Download Dublin Core file. Open up the file, and make sure that the document not follows the DC-XML recommendations as should be.
2) Apply patches.
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 in the OPAC.
5) Try several bibliographic records in any format (book, magazine, DVD, etc.) to confirm that properly exported.
6) RDF/XML can be validated per RDF Validator W3C.
7) DC-XML cannot valid if not exist a valid XSD schema.
8) OAI-DC can be validated using <http://www.freeformatter.com/xml-validator-xsd.html> and the proper schema <http://www.openarchives.org/OAI/2.0/oai_dc.xsd> typed in text field for URL.
9) Since unit test fail last time, test with prove t/db_dependent/Record.t

Sponsored-by: Universidad de El Salvador

Signed-off-by: Hector Castro <hector.hecaxmmx@gmail.com>
XML::Entities, HTML::Entities and, HTML::Entities::Numbered were eliminated from patch, use instead C4::Record::_entity_encode, RDF::Helper has been eliminated too.
---
 C4/Installer/PerlDependencies.pm                   |    5 +
 C4/Record.pm                                       |  127 ++-
 Koha/DublinCore.pm                                 |  992 ++++++++++++++++++++
 catalogue/export.pl                                |   36 +-
 debian/control                                     |    6 +-
 .../intranet-tmpl/prog/en/includes/cat-toolbar.inc |    2 +-
 .../prog/en/modules/catalogue/detail.tt            |  143 ++-
 .../opac-tmpl/bootstrap/en/includes/masthead.inc   |   66 ++
 .../bootstrap/en/includes/opac-detail-sidebar.inc  |    5 +-
 koha-tmpl/opac-tmpl/bootstrap/js/script.js         |   78 +-
 opac/opac-export.pl                                |   36 +-
 t/db_dependent/Record.t                            |   39 +-
 12 files changed, 1481 insertions(+), 54 deletions(-)
 create mode 100644 Koha/DublinCore.pm

diff --git a/C4/Installer/PerlDependencies.pm b/C4/Installer/PerlDependencies.pm
index 7e382bd..b4ae230 100644
--- a/C4/Installer/PerlDependencies.pm
+++ b/C4/Installer/PerlDependencies.pm
@@ -737,6 +737,11 @@ our $PERL_DEPS = {
         'required' => '0',
         'min_ver'  => '1.17',
     },
+    'RDF::Trine' => {
+        'usage'    => 'Core',
+        'required' => '1',
+        'min_ver'  => '1.000',
+    },
 };
 
 1;
diff --git a/C4/Record.pm b/C4/Record.pm
index 5d894fa..2c6aac2 100644
--- a/C4/Record.pm
+++ b/C4/Record.pm
@@ -25,7 +25,7 @@ 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 Koha::DublinCore; # marc2dcxml
 use Biblio::EndnoteStyle;
 use Unicode::Normalize; # _entity_encode
 use C4::Biblio; #marc2bibtex
@@ -219,20 +219,34 @@ sub marcxml2marc {
 
 =head2 marc2dcxml - Convert from ISO-2709 to Dublin Core
 
-  my ($error,$dcxml) = marc2dcxml($marc,$qualified);
+  ($error,$marc) = marc2dcxml($marc, $type, $qualified,
+                              $entities, $root, $xsi_schemaLocation, $rdf_subject, $rdf_format);
 
 Returns a DublinCore::Record object, will eventually return a Dublin Core scalar
 
-FIXME: should return actual XML, not just an object
+FIXME: should return actual XML, not just an object (Koha::DublinCore return an XML)
 
 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<$type> - the recommendation ( simple-dc-rdf, dc-rdf, dc-xml, oai-dc, srw_dc )
+
+C<$qualified> - specify whether simple or qualified Dublin Core should be used in output [0 or 1]
+
+C<$entities> placing entities to 0 will codify only the five basic entities e.g., &lt, &gt, &quot, &amp, and &apos. Conversely if it is encoded to 1, all entities will coded into decimal
+
+C<$root> root element for XML files
+
+C<$xsi_schemaLocation> the xsischemaLocation for XML files.
+
+C<$rdf_subject> Represent the main subject of RDF triples (for Koha the URI of the resource)
+
+C<$rdf_format> Imply multiple formats for RDF (ntriples, nquads, rdfxml, rdfjson, ntriples-canonical, turtle)
 
 =cut
 
 sub marc2dcxml {
-	my ($marc,$qualified) = @_;
+    my ( $marc, $type, $qualified, $entities, $root, $xsi_schemaLocation, $rdf_subject,
+        $rdf_format ) = @_;
 	my $error;
     # test if it's already a MARC::Record object, if not, make it one
     my $marc_record_obj;
@@ -246,24 +260,93 @@ sub marc2dcxml {
 			$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/\">";
-
-	foreach my $element ( $dcxml->elements() ) {
-                $dcxmlfinal.="<"."dc:".$element->name().">".$element->content()."</"."dc:".$element->name().">\n";
+    my $dcxml;
+
+    SWITCH:
+    for ($type) {
+        if (/^simple-dc-rdf/) {
+            my $objectDC = Koha::DublinCore->new({
+                type            => 'rdf',
+                qualified       => 0,
+                get_marc_record => $marc,
+            });
+
+            $objectDC->get_rdf_data({
+                rdf_subject => $rdf_subject,
+                rdf_format  => $rdf_format,
+                entities    => 1,
+            });
+            $dcxml = $objectDC->write_rdf();
+            last SWITCH;
+        }
+        if (/^dc-rdf/) {
+            my $objectDC = Koha::DublinCore->new({
+                type            => 'rdf',
+                qualified       => 1,
+                get_marc_record => $marc,
+            });
+
+            $objectDC->get_rdf_data({
+                rdf_subject => $rdf_subject,
+                rdf_format  => $rdf_format,
+                entities    => 1,
+            });
+            $dcxml = $objectDC->write_rdf();
+            last SWITCH;
+        }
+        if (/^dc-xml/) {
+            my $objectDC = Koha::DublinCore->new({
+                type            => 'xml',
+                qualified       => $qualified,
+                get_marc_record => $marc,
+            });
+
+            $objectDC->get_xml_data({
+                root               => $root,
+                xsi_schemaLocation => $xsi_schemaLocation,
+                entities           => 1,
+            });
+            $dcxml = $objectDC->write_xml();
+            last SWITCH;
+        }
+        if (/^oai-dc/) {
+            my $objectDC = Koha::DublinCore->new({
+                type            => 'xml',
+                qualified       => 0,
+                get_marc_record => $marc,
+            });
+
+            $objectDC->get_xml_data({
+                root               => 'oai_dc:dc',
+                xsi_schemaLocation => 'http://www.openarchives.org/OAI/2.0/oai_dc/' .
+                                      ' http://www.openarchives.org/OAI/2.0/oai_dc.xsd',
+                entities           => 0,
+                opt_namespace      => 'oai_dc',
+                opt_namespace_url  => 'http://www.openarchives.org/OAI/2.0/oai_dc/',
+            });
+            $dcxml = $objectDC->write_xml();
+            last SWITCH;
+        }
+        if (/^srw_dc/) {
+            my $objectDC = Koha::DublinCore->new({
+                type            => 'xml',
+                qualified       => 0,
+                get_marc_record => $marc,
+            });
+
+            $objectDC->get_xml_data({
+                root               => 'srw_dc:dc',
+                xsi_schemaLocation => 'info:srw/schema/1/dc-schema' .
+                                      ' http://www.loc.gov/standards/sru/resources/dc-schema.xsd',
+                entities           => 0,
+                opt_namespace      => 'srw_dc',
+                opt_namespace_url  => 'info:srw/schema/1/dc-schema',
+            });
+            $dcxml = $objectDC->write_xml();
+            last SWITCH;
+        }
     }
-	$dcxmlfinal .= "\n</metadata>";
-	return ($error,$dcxmlfinal);
+    return ( $error, $dcxml );
 }
 
 =head2 marc2modsxml - Convert from ISO-2709 to MODS
diff --git a/Koha/DublinCore.pm b/Koha/DublinCore.pm
new file mode 100644
index 0000000..2313349
--- /dev/null
+++ b/Koha/DublinCore.pm
@@ -0,0 +1,992 @@
+#!/usr/bin/perl
+package Koha::DublinCore;
+
+#
+# This file is part of Koha.
+#
+# Copyright (C) 2014 Universidad de El Salvador,
+# Facultad Multidisciplinaria Oriental
+#
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
+#
+
+use Modern::Perl;
+use strict;
+use warnings::register;
+use utf8;
+use version;
+
+BEGIN {
+    require Exporter;
+
+    # set the version for version checking
+    our $VERSION = version->declare("v0.01");
+
+    # Inherit from Exporter to export functions and variables
+    our @ISA = qw(Exporter);
+
+    # Functions and variables which are exported by default
+    our @EXPORT = qw(new get_xml_data get_rdf_data write_xml write_rdf);
+
+    # Functions and variables which can be optionally exported
+    our @EXPORT_OK =
+      qw(type qualified get_marc_record root xsi_schemaLocation rdf_subject rdf_format opt_namespace opt_namespace_url);
+
+}
+
+use MARC::File::USMARC;
+use MARC::Crosswalk::DublinCore;
+use XML::LibXML;
+use C4::Record;
+use RDF::Trine;
+use base qw(Class::Accessor);
+__PACKAGE__->mk_accessors(
+    qw(type qualified get_marc_record root xsi_schemaLocation rdf_subject rdf_format entities opt_namespace opt_namespace_url)
+);
+
+# Defining some constants
+my $xsi_schema  = qq(http://www.w3.org/2001/XMLSchema-instance);
+my $unqualified = qq(http://purl.org/dc/elements/1.1/);
+my $qualified   = qq(http://purl.org/dc/terms/);
+my $dcam        = qq(http://purl.org/dc/dcam/);
+my $rdfNS       = qq(http://www.w3.org/1999/02/22-rdf-syntax-ns#);
+my @elementupcase =
+  qw/tableOfContents dateAccepted dateCopyrighted dateSubmitted isVersionOf hasVersion isReplacedBy isRequiredBy isPartOf hasPart isReferencedBy isFormatOf hasFormat conformsTo accrualMethod accrualPeriodicity accrualPolicy instructionalMethod rightsHolder educationLevel accessRights bibliographicCitation/;
+my $map;
+
+#USAGE: Koha::DublinCore->new({
+#    type => 'xml|rdf',
+#    qualified => 0|1,
+#    get_marc_record => $record
+#});
+
+sub new {
+    my ( $class, $args ) = @_;
+    $args = {} unless defined $args;
+    return bless( $args, $class );
+}
+
+sub get_xml_data {
+
+#USAGE: oop->get_xml_data({
+#        root => 'root',
+#        xsi_schemaLocation => 'http://example.org/myapp/ http://example.org/myapp/schema.xsd',
+#        entities => 0|1,
+#        opt_namespace => 'oai_dc'
+#        opt_namespace_url => 'http://www.openarchives.org/OAI/2.0/oai_dc/'
+#});
+    my $self = shift;
+    my ($args) = @_;
+
+    if (@_) {
+        $self->root( $args->{root} );
+        $self->xsi_schemaLocation( $args->{xsi_schemaLocation} );
+        $self->entities( $args->{entities} );
+        $self->opt_namespace( $args->{opt_namespace} );
+        $self->opt_namespace_url( $args->{opt_namespace_url} );
+    }
+
+    #if data not filled
+    $self->{root}     = "metadata" unless ( defined $self->{root} );
+    $self->{entities} = 0          unless ( defined $self->{entities} );
+    my %dataxml = (
+        xmlroot            => $self->{root},
+        entities           => $self->{entities},
+        opt_namespace => $self->{opt_namespace},
+        opt_namespace_url      => $self->{opt_namespace_url},
+    );
+
+    if ( exists $self->{xsi_schemaLocation} ) {
+        $dataxml{'xsi_schemaLocation'} = $self->{xsi_schemaLocation};
+    }
+    if ( exists $self->{xsi_schemaLocation} ) {
+        $dataxml{'opt_namespace'} = $self->{opt_namespace};
+    }
+    if ( exists $self->{xsi_schemaLocation} ) {
+        $dataxml{'opt_namespace_url'} = $self->{opt_namespace_url};
+    }
+    return \%dataxml;
+}
+
+sub get_rdf_data {
+
+#USAGE: oop->get_rdf_data({
+#        rdf_subject => 'http://opac.mydomain.edu/cgi-bin/koha/opac-detail.pl?biblionumber=17589',
+#        rdf_format => 'ntriples | nquads| rdfxml | rdfjson | ntriples-canonical | turtle',
+#        entities => 0|1,
+#})
+
+    my $self = shift;
+    my ($args) = @_;
+
+    if (@_) {
+        $self->rdf_subject( $args->{rdf_subject} );
+        $self->rdf_format( $args->{rdf_format} );
+        $self->entities( $args->{entities} );
+    }
+
+    #if data not filled
+    $self->{rdf_subject} = "http://koha-community.org/"
+      unless ( defined $self->{rdf_subject} );
+    $self->{rdf_format} = "rdfxml" unless ( defined $self->{rdf_format} );
+    $self->{entities}   = 0        unless ( defined $self->{entities} );
+    my %rdfdescription = (
+        rdf_subject => $self->{rdf_subject},
+        rdf_format  => $self->{rdf_format},
+        entities    => $self->{entities},
+    );
+
+    return \%rdfdescription;
+}
+
+sub conversion_to_dc {
+
+#Get the MARC record and return a Dublin Core elements, passed as argument in dc_order_execution method.
+#USAGE:
+#my dc = $self->conversion_to_dc();
+#$self->dc_order_execution ($dc, $dcxml, $root);
+    my $self            = shift;
+    my $marc_record_obj = $self->get_marc_record();
+    my $crosswalk;
+    my $dc;
+
+    #if data not filled
+    $self->qualified(0) unless ( exists $self->{qualified} );
+    if ( ( $self->qualified() != 0 and $self->qualified() != 1 )
+        && warnings::enabled($self) )
+    {
+        warnings::warn( $self, "Only the 0 or 1 values are accepted" );
+        die "Set qualified => " . $self->qualified() . " is no good, stopped";
+    }
+    if ( $self->qualified() == 1 ) {
+        $crosswalk = MARC::Crosswalk::DublinCore->new( qualified => 1 );
+    }
+    elsif ( $self->qualified() == 0 ) {
+        $crosswalk = MARC::Crosswalk::DublinCore->new( qualified => 0 );
+    }
+    if ( $marc_record_obj =~ /^MARC::Record/ ) {
+        $dc = $crosswalk->as_dublincore($marc_record_obj);
+    }
+    else {
+        warnings::warn( $self,
+            "MARC::Record object failed or not a MARC::Record" );
+        die "Stopped due get_marc_record => is not a MARC::Record";
+    }
+
+    return $dc;
+
+}
+
+sub write_xml {
+    my $self    = shift;
+    my $dataxml = $self->get_xml_data();
+    my $dc      = $self->conversion_to_dc();
+
+    #Looking for bad data
+    if ( ( $self->type() ne 'xml' and $self->type() ne 'rdf' )
+        && warnings::enabled($self) )
+    {
+        warnings::warn( $self, "Only the xml or rdf values are accepted" );
+        die "Set type => " . $self->type() . " is no good, stopped";
+    }
+    elsif ( $self->type() eq 'rdf' && warnings::enabled($self) ) {
+        warnings::warn( $self, "The constructor specified rdf" );
+        die "Cannot use this method with rdf. This is no good, stopped";
+    }
+
+    if ( ( $self->entities() != 0 and $self->entities() != 1 )
+        && warnings::enabled($self) )
+    {
+        warnings::warn( $self, "Only the 0 or 1 values are accepted" );
+        die "Set entities => " . $self->entities() . " is no good, stopped";
+    }
+
+    #Creating XML object
+    my $doc = XML::LibXML::Document->new( '1.0', 'utf-8' );
+    my $root = $doc->createElement( $dataxml->{'xmlroot'} );
+    $root->setNamespace( $xsi_schema, 'xsi', 0 );
+
+    if ( defined $dataxml->{'opt_namespace'} ) {
+        $root->setNamespace( $dataxml->{'opt_namespace_url'},
+            $dataxml->{'opt_namespace'}, 0 );
+    }
+
+    if ( $self->type() eq 'xml' ) {
+        if ( $self->qualified() == 0 ) {
+            if ( defined $dataxml->{'xsi_schemaLocation'} ) {
+                $root->setAttribute(
+                    'xsi:schemaLocation' => $dataxml->{'xsi_schemaLocation'} );
+                $root->setNamespace( $unqualified, 'dc', 0 );
+                $self->dc_order_execution( $dc, $doc, $root );
+            }
+            else {
+                $root->setNamespace( $unqualified, 'dc', 0 );
+                $self->dc_order_execution( $dc, $doc, $root );
+            }
+        }
+        elsif ( $self->qualified() == 1 ) {
+            if ( defined $dataxml->{'xsi_schemaLocation'} ) {
+                $root->setAttribute(
+                    'xsi:schemaLocation' => $dataxml->{'xsi_schemaLocation'} );
+                $root->setNamespace( $unqualified, 'dc',      0 );
+                $root->setNamespace( $qualified,   'dcterms', 0 );
+                $self->dc_order_execution( $dc, $doc, $root );
+            }
+            else {
+                $root->setNamespace( $unqualified, 'dc',      0 );
+                $root->setNamespace( $qualified,   'dcterms', 0 );
+                $self->dc_order_execution( $dc, $doc, $root );
+            }
+        }
+    }
+
+    $doc->setDocumentElement($root);
+
+    #Enabling or desabling entities and print the xml and, decoding string to utf8
+    if ( $dataxml->{'entities'} == 1 ) {
+        my $serialized_data = $doc->toString(1);
+        utf8::decode($serialized_data);
+        my ($dcxml_entity_encoded) = C4::Record::_entity_encode($serialized_data);
+        $serialized_data = $dcxml_entity_encoded;
+        return $serialized_data;
+    }
+    else {
+        return $doc->toString(1);
+    }
+}
+
+sub write_rdf {
+    my $self           = shift;
+    my $rdfdescription = $self->get_rdf_data();
+    my $dc             = $self->conversion_to_dc();
+    my $serializer;
+    my %namespaces;
+
+    #Looking for bad data
+    if ( ( $self->type() ne 'xml' and $self->type() ne 'rdf' )
+        && warnings::enabled($self) )
+    {
+        warnings::warn( $self, "Only the xml or rdf values are accepted" );
+        die "Set type => " . $self->type() . " is no good, stopped";
+    }
+    elsif ( $self->type() eq 'xml' && warnings::enabled($self) ) {
+        warnings::warn( $self, "The constructor specified xml" );
+        die "Cannot use this method with xml. This is no good, stopped";
+    }
+
+    if ( ( $self->entities() != 0 and $self->entities() != 1 )
+        && warnings::enabled($self) )
+    {
+        warnings::warn( $self, "Only the 0 or 1 values are accepted" );
+        die "Set entities => " . $self->entities() . " is no good, stopped";
+    }
+
+    # Creating the triple store in temporary data
+    my $store = RDF::Trine::Store::Memory->new();
+
+    # Creating the model
+    my $rdf = RDF::Trine::Model->new($store);
+
+    # Creating the subject
+    my $subject =
+      RDF::Trine::Node::Resource->new( $rdfdescription->{'rdf_subject'} );
+
+    $namespaces{'rdf'} = $rdfNS;
+
+    if ( $self->qualified() == 0 ) {
+
+        # Declaring all namespaces in a hash
+        $namespaces{'dc'} = $unqualified;
+    }
+    else {
+
+        # Declaring all namespaces in a hash
+        $namespaces{'dcterms'} = $qualified;
+        $namespaces{'dcam'}    = $dcam;
+    }
+
+    # Creating namespaces
+    $map = RDF::Trine::NamespaceMap->new( \%namespaces );
+
+    if ( $self->type() eq 'rdf' ) {
+        $self->dc_order_execution( $dc, $rdf, $subject );
+    }
+
+   #Enabling or desabling entities and print the xml and, decoding string to utf8
+    if ( $rdfdescription->{'rdf_format'} eq 'rdfxml' ) {
+        if ( $rdfdescription->{'entities'} == 1 ) {
+            $serializer =
+              RDF::Trine::Serializer::RDFXML->new(
+                namespaces => {%namespaces} );
+            my $serialized_data = $serializer->serialize_model_to_string($rdf);
+            utf8::decode($serialized_data);
+            my ($dcxml_entity_encoded) = C4::Record::_entity_encode($serialized_data);
+            return $serialized_data = $dcxml_entity_encoded;
+        }
+        else {
+            $serializer =
+              RDF::Trine::Serializer::RDFXML->new(
+                namespaces => {%namespaces} );
+            return $serializer->serialize_model_to_string($rdf);
+        }
+    }
+    elsif ( $rdfdescription->{'rdf_format'} eq 'turtle' ) {
+        $serializer =
+          RDF::Trine::Serializer::Turtle->new( namespaces => {%namespaces} );
+        return $serializer->serialize_model_to_string($rdf);
+    }
+    else {
+        $serializer =
+          RDF::Trine::Serializer->new( $rdfdescription->{'rdf_format'} );
+        return $serializer->serialize_model_to_string($rdf);
+    }
+}
+
+sub upper_or_lowercase {
+
+#This subroutine define if is necessary to convert lowercase some qualifiers or let them as crosswalk method basis
+#USAGE: upper_or_lowercase (element->qualifier())
+    my $dcelement = $_[0];
+    my $count     = 0;
+    my $result;
+    while ( $count <= $#elementupcase ) {
+        if ( $elementupcase[$count] eq $dcelement ) {
+            $result = $dcelement;
+            last;
+        }
+        elsif ( $dcelement ne $elementupcase[$count] ) {
+            $result = lc($dcelement);
+            $count++;
+            next;
+        }
+    }
+
+    return $result;
+
+}
+
+sub xml_constructor {
+
+#xml_constructor ( doc, root, namespace, attr, element_name, element_content, element_qualifier, element_scheme )
+#USAGE: define all posible elements (name, content, qualifier, scheme) as neccesary
+#doc: the XML object
+#root: append root to doc
+#namespace: defined as "dc" or "dcterms"
+#attr: a boolean value to determinate xsi:type xml namespace for dcterms
+#examples:
+#xml_constructor ( $dcxml, $root, "dc", 0, element->name(), element->content() );
+#xml_constructor ( $dcxml, $root, "dcterms", 1, element->name(), element->content(), $element->qualifier() );
+
+    my ( $doc, $root, $namespace, $attr, $element_name, $element_content,
+        $element_qualifier, $element_scheme )
+      = @_;
+
+    # This scalar is used for deleting spaces in scheme elements
+    my $deletespaces;
+
+    # This scalar is used for making upper or lowercase the qualifier elements
+    my $lowercase;
+    my $tagxml;
+
+    if ( $namespace eq "dc" ) {
+        $lowercase = lc($element_name);
+    }
+    elsif ( $namespace eq "dcterms" ) {
+        $lowercase = upper_or_lowercase($element_qualifier);
+
+        #replacing spacial to spatial, bug from dublin or crosswalk.
+        $lowercase =~ s/spacial/spatial/;
+    }
+
+    if ( ( $namespace eq "dc" or "dcterms" ) and $attr == 0 ) {
+
+        # This will do something like: <dc:title>Title</dc:title>
+        $tagxml = XML::LibXML::Element->new($lowercase);
+        $tagxml->setNamespace( undef, $namespace, 1 );
+        $tagxml->appendTextNode($element_content);
+        $root->appendChild($tagxml);
+    }
+    elsif ( ( $namespace eq "dcterms" ) and $attr == 1 ) {
+
+# This will do something like: <dcterms:spatial xsi:type="dcterms:ISO3166">us</dcterms:spatial>
+        $deletespaces = $element_scheme;
+        $deletespaces =~ s/\s//;
+        $tagxml = XML::LibXML::Element->new($lowercase);
+        $tagxml->setNamespace( undef, $namespace, 1 );
+        my $attribute = $namespace . ':' . $deletespaces;
+        $tagxml->setAttribute( 'xsi:type', $attribute );
+        $tagxml->appendTextNode($element_content);
+        $root->appendChild($tagxml);
+    }
+    elsif ( ( $namespace eq "dc" ) and $attr == 1 ) {
+
+# This will do something like: <dc:subject xsi:type="dcterms:LCSH">Water supply.</dc:subject>
+            if ( $element_scheme ne "DCMI Type Vocabulary" )
+            {    #Dublin core returns DCMI Type Vocabulary
+                $deletespaces = $element_scheme;
+                $deletespaces =~ s/\s//;
+                $tagxml = XML::LibXML::Element->new($lowercase);
+                $tagxml->setNamespace( undef, $namespace, 1 );
+                my $attribute = 'dcterms:' . $deletespaces;
+                $tagxml->setAttribute( 'xsi:type', $attribute );
+                $tagxml->appendTextNode($element_content);
+                $root->appendChild($tagxml);
+            }
+            elsif ( $element_scheme eq "DCMI Type Vocabulary" )
+            {    #Changing for DCMIType
+                 # This will do something like: <dc:type xsi:type="dcterms:DCMIType">Text</dc:type>
+                $tagxml = XML::LibXML::Element->new($lowercase);
+                $tagxml->setNamespace( undef, $namespace, 1 );
+                $tagxml->setAttribute( 'xsi:type', 'dcterms:DCMIType' );
+                $tagxml->appendTextNode($element_content);
+                $root->appendChild($tagxml);
+            }
+    }    #if...elsif
+
+    return $tagxml;
+
+}    #subroutine
+
+sub rdf_constructor {
+
+#xml_constructor ( rdf, subject, namespace, attr, element_name, element_content, element_qualifier, element_scheme )
+#USAGE: define all posible elements (name, content, qualifier, scheme) as neccesary
+#rdf: the RDF object
+#subject: the subject for the triples
+#namespace: defined as "dc" or "dcterms". This is for Simple DC or DC-RDF recommendations.
+#attr: a boolean value to determine the nodeID attribute for dcterms
+
+    my ( $rdf, $subject, $namespace, $attr, $element_name, $element_content,
+        $element_qualifier, $element_scheme )
+      = @_;
+
+    #This scalar is used for deleting spaces in scheme elements
+    my $deletespaces;
+
+    #This scalar is used for making upper or lowercase the qualifier elements
+    my $lowercase;
+
+    if ( $namespace eq "dc" ) {
+        $lowercase = lc($element_name);
+    }
+    elsif ( $namespace eq "dcterms" ) {
+        $lowercase = upper_or_lowercase($element_qualifier);
+
+        #replacing spacial to spatial, bug from dublin or crosswalk.
+        $lowercase =~ s/spacial/spatial/;
+    }
+
+    if ( ( $namespace eq "dc" or "dcterms" ) and $attr == 0 ) {
+
+        # This will do something like: <dc:title>Title</dc:title>
+        my $predicate = undef;
+        if ( $namespace eq "dc" ) {
+            $predicate = $map->dc($lowercase);
+        }
+        else {
+            $predicate = $map->dcterms($lowercase);
+        }
+        my $object = RDF::Trine::Node::Literal->new($element_content);
+        my $statement =
+          RDF::Trine::Statement->new( $subject, $predicate, $object );
+        $rdf->add_statement($statement);
+    }
+    elsif ( ( $namespace eq "dc" ) and $attr == 2 ) {
+
+        # This will do something like: <dcterms:title>Title</dcterms:title>
+        my $predicate = $map->dcterms($lowercase);
+        my $object    = RDF::Trine::Node::Literal->new($element_content);
+        my $statement =
+          RDF::Trine::Statement->new( $subject, $predicate, $object );
+        $rdf->add_statement($statement);
+    }
+    elsif ( ( $namespace eq "dc" ) and $attr == 1 ) {
+        $deletespaces = $element_scheme;
+        $deletespaces =~ s/\s//;
+      SWITCH:
+        for ($element_scheme) {
+            if (/^ISO 3166/) {
+
+       #  Dublin core returns DCMI Type Vocabulary
+       #  This will do something like:
+       #    <rdf:Description rdf:nodeID="country">
+       #        <dcam:memberOf rdf:resource="http://purl.org/dc/terms/ISO3166"/>
+       #        <rdf:value>us</rdf:value>
+       #    </rdf:Description>
+       #    <dcterms:spatial rdf:nodeID="country"/>
+                my $objectbnode = RDF::Trine::Node::Blank->new('country');
+                my $predicate   = $map->dcterms($lowercase);
+                my $object = RDF::Trine::Node::Literal->new($element_content);
+                my $dcam_member_of  = $map->dcam('memberOf');
+                my $resource_schema = $map->dcterms($deletespaces);
+                my $rdf_value       = $map->rdf('value');
+                my $statement1 =
+                  RDF::Trine::Statement->new( $subject, $predicate,
+                    $objectbnode );
+                my $statement2 =
+                  RDF::Trine::Statement->new( $objectbnode, $dcam_member_of,
+                    $resource_schema );
+                my $statement3 =
+                  RDF::Trine::Statement->new( $objectbnode, $rdf_value,
+                    $object );
+                $rdf->add_statement($statement1);
+                $rdf->add_statement($statement2);
+                $rdf->add_statement($statement3);
+                last SWITCH;
+            }
+            if (/^DCMI Type Vocabulary/) {    #Changing for DCMIType
+                my $objectbnode = RDF::Trine::Node::Blank->new('DCMIType');
+                my $predicate   = $map->dcterms($lowercase);
+                my $object = RDF::Trine::Node::Literal->new($element_content);
+                my $dcam_member_of  = $map->dcam('memberOf');
+                my $resource_schema = $map->dcterms('DCMIType');
+                my $rdf_value       = $map->rdf('value');
+                my $statement1 =
+                  RDF::Trine::Statement->new( $subject, $predicate,
+                    $objectbnode );
+                my $statement2 =
+                  RDF::Trine::Statement->new( $objectbnode, $dcam_member_of,
+                    $resource_schema );
+                my $statement3 =
+                  RDF::Trine::Statement->new( $objectbnode, $rdf_value,
+                    $object );
+                $rdf->add_statement($statement1);
+                $rdf->add_statement($statement2);
+                $rdf->add_statement($statement3);
+                last SWITCH;
+            }
+            if (/^ISO 639-2/) {    #Changing bnodeId ISO639-2 for language
+                my $objectbnode = RDF::Trine::Node::Blank->new('language');
+                my $predicate   = $map->dcterms($lowercase);
+                my $object = RDF::Trine::Node::Literal->new($element_content);
+                my $dcam_member_of  = $map->dcam('memberOf');
+                my $resource_schema = $map->dcterms($deletespaces);
+                my $rdf_value       = $map->rdf('value');
+                my $statement1 =
+                  RDF::Trine::Statement->new( $subject, $predicate,
+                    $objectbnode );
+                my $statement2 =
+                  RDF::Trine::Statement->new( $objectbnode, $dcam_member_of,
+                    $resource_schema );
+                my $statement3 =
+                  RDF::Trine::Statement->new( $objectbnode, $rdf_value,
+                    $object );
+                $rdf->add_statement($statement1);
+                $rdf->add_statement($statement2);
+                $rdf->add_statement($statement3);
+                last SWITCH;
+            }
+            if (/^RFC 1766/) {    #Changing bnodeId RFC1766 for languagetag
+                my $objectbnode = RDF::Trine::Node::Blank->new('languagetag');
+                my $predicate   = $map->dcterms($lowercase);
+                my $object = RDF::Trine::Node::Literal->new($element_content);
+                my $dcam_member_of  = $map->dcam('memberOf');
+                my $resource_schema = $map->dcterms($deletespaces);
+                my $rdf_value       = $map->rdf('value');
+                my $statement1 =
+                  RDF::Trine::Statement->new( $subject, $predicate,
+                    $objectbnode );
+                my $statement2 =
+                  RDF::Trine::Statement->new( $objectbnode, $dcam_member_of,
+                    $resource_schema );
+                my $statement3 =
+                  RDF::Trine::Statement->new( $objectbnode, $rdf_value,
+                    $object );
+                $rdf->add_statement($statement1);
+                $rdf->add_statement($statement2);
+                $rdf->add_statement($statement3);
+                last SWITCH;
+            }
+            if ( /^LCSH/ || /^MeSH/ || /^LCC/ || /^DDC/ ||
+                 /^UDC/ || /^IMT/ || /^URI/ || /^TGN/ )
+            {    #Scheme sharing common elements
+                my $objectbnode = RDF::Trine::Node::Blank->new($deletespaces);
+                my $predicate   = $map->dcterms($lowercase);
+                my $object = RDF::Trine::Node::Literal->new($element_content);
+                my $dcam_member_of  = $map->dcam('memberOf');
+                my $resource_schema = $map->dcterms($deletespaces);
+                my $rdf_value       = $map->rdf('value');
+                my $statement1 =
+                  RDF::Trine::Statement->new( $subject, $predicate,
+                    $objectbnode );
+                my $statement2 =
+                  RDF::Trine::Statement->new( $objectbnode, $dcam_member_of,
+                    $resource_schema );
+                my $statement3 =
+                  RDF::Trine::Statement->new( $objectbnode, $rdf_value,
+                    $object );
+                $rdf->add_statement($statement1);
+                $rdf->add_statement($statement2);
+                $rdf->add_statement($statement3);
+                last SWITCH;
+            }
+        }
+    }    #if-elsif
+    return $rdf;
+}    #subroutine
+
+sub dc_order_execution {
+
+    #USAGE: USAGE: Get the parameters for xml or rdf and execute in order.
+    my $self = shift;
+
+    if ( $self->type() eq 'xml' ) {    #Order for xml
+        my ( $dc, $dcxml, $root ) = @_;
+        foreach my $element ( $dc->elements() ) {
+          SWITCH: {
+                if (    $element->name()
+                    and not defined $element->scheme()
+                    and not defined $element->qualifier() )
+                {
+                    $dcxml =
+                      xml_constructor( $dcxml, $root, "dc", 0, $element->name(),
+                        $element->content() );
+                    last SWITCH;
+                }
+
+                if (    $element->name()
+                    and not defined $element->scheme()
+                    and not defined $element->qualifier() )
+                {
+                    $dcxml =
+                      xml_constructor( $dcxml, $root, "dcterms", 0,
+                        $element->name(), $element->content() );
+                    last SWITCH;
+                }
+
+                if (    $element->name()
+                    and $element->scheme()
+                    and $element->qualifier() )
+                {
+                    $dcxml = xml_constructor(
+                        $dcxml,                $root,
+                        "dcterms",             1,
+                        $element->name(),      $element->content(),
+                        $element->qualifier(), $element->scheme()
+                    );
+                    last SWITCH;
+                }
+
+                if (    $element->name()
+                    and $element->scheme()
+                    and ( $element->scheme ne "DCMI Type Vocabulary" ) )
+                {
+                    $dcxml =
+                      xml_constructor( $dcxml, $root, "dc", 1, $element->name(),
+                        $element->content(), $element->qualifier(),
+                        $element->scheme() );
+                    last SWITCH;
+                }
+
+                if (    $element->name()
+                    and $element->scheme()
+                    and ( $element->scheme() eq "DCMI Type Vocabulary" ) )
+                {
+                    $dcxml =
+                      xml_constructor( $dcxml, $root, "dc", 1, $element->name(),
+                        $element->content(), $element->qualifier(),
+                        $element->scheme() );
+                    last SWITCH;
+                }
+
+                if ( $element->name() and $element->qualifier() ) {
+                    $dcxml = xml_constructor(
+                        $dcxml,                $root,
+                        "dcterms",             0,
+                        $element->name(),      $element->content(),
+                        $element->qualifier(), $element->scheme()
+                    );
+                    last SWITCH;
+                }    #if
+            }    #SWITCH
+        }    #foreach 1
+    }
+    elsif ( $self->type() eq 'rdf' ) {    #Order for rdf/xml
+        my ( $dc, $rdf, $subject ) = @_;
+        foreach my $element ( $dc->elements() ) {
+          SWITCH: {
+                if (    $element->name()
+                    and not defined $element->scheme()
+                    and not defined $element->qualifier() )
+                {
+                    rdf_constructor( $rdf, $subject, "dc", 0, $element->name(),
+                        $element->content() )
+                      unless $self->qualified() == 1;
+                    rdf_constructor( $rdf, $subject, "dc", 2, $element->name(),
+                        $element->content() )
+                      unless $self->qualified() == 0;
+                    last SWITCH;
+                }
+
+                if (    $element->name()
+                    and $element->scheme()
+                    and ( $element->scheme ne "DCMI Type Vocabulary" ) )
+                {
+                    rdf_constructor( $rdf, $subject, "dc", 1, $element->name(),
+                        $element->content(), $element->qualifier(),
+                        $element->scheme() );
+                    last SWITCH;
+                }
+
+                if (    $element->name()
+                    and $element->scheme()
+                    and ( $element->scheme() eq "DCMI Type Vocabulary" ) )
+                {
+                    rdf_constructor( $rdf, $subject, "dc", 1, $element->name(),
+                        $element->content(), $element->qualifier(),
+                        $element->scheme() );
+                    last SWITCH;
+                }
+
+                if ( $element->name() and $element->qualifier() ) {
+                    rdf_constructor(
+                        $rdf,                  $subject,
+                        "dcterms",             0,
+                        $element->name(),      $element->content(),
+                        $element->qualifier(), $element->scheme()
+                    );
+                    last SWITCH;
+                }    #if
+            }    #SWITCH
+        }    #foreach 2
+    }
+    return;
+}
+
+END {
+
+    #When opened with MARC::File::USMARC, close marc record if not closed
+    sub DESTROY {
+        my $self = shift;
+        if ( $self->{get_marc_record} =~ /^MARC:File::USMARC/ ) {
+            $self->{get_marc_record}->close();
+            undef $self->{get_marc_record};
+        }
+    }
+}
+1;
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Koha::DublinCore - transform the values of MARC::Crosswalk::DublinCore
+into metadata in XML or RDF format.
+
+=head1 SYNOPSIS
+
+=head2 XML-DC
+
+  use Koha::DublinCore;
+  use MARC::File::USMARC;
+  my $batch = MARC::File::USMARC->in('in.mrc');
+
+  ## the $record will be a MARC::Record object.
+  my $record = $batch->next();
+
+  #For Simple DC-XML
+  my $objectDC = Koha::DublinCore->new({
+        type => 'xml',
+        qualified => 0,
+        get_marc_record => $record});
+
+  #For Qualified DC-XML
+  my $objectDC = Koha::DublinCore->new({
+        type => 'xml',
+        qualified => 1,
+        get_marc_record => $record});
+
+  #After call constructor you need to pass the root element and
+  #the schema in .xsd format. If you prefer or you don't know nothing
+  #about it pass the method in blank, i.e., without arguments.
+  #Also you can determine if you want to encode with xml entities or
+  #just with the five basics entities.
+  #Set entities to 0 for the five basics or 1 to encode with the
+  #complete xml entities.
+  $objectDC->get_xml_data({
+        root => 'metadata',
+        xsi_schemaLocation => 'http://example.org/myapp/' .
+                              ' http://example.org/myapp/schema.xsd',
+  });
+  #This print your xml file in STDOUT
+  my $XML-DC = $objectDC->write_xml();
+  print $XML-DC;
+
+  #Close the file according to MARC::File::USMARC
+  $batch->close();
+  undef $batch;
+
+  #Or if you want to generate a file
+  open (OUTPUT, '> dc2xml.xml') or die $!;
+  print OUTPUT $XML-DC;
+  close(OUTPUT);
+
+=head2 DC-RDF
+
+  use Koha::DublinCore;
+  use MARC::File::USMARC;
+  my $marc = MARC::File::USMARC->in('in.mrc');
+  my $record = $marc->next();
+
+  #Simple DC-RDF is not used but not deprecated, DublinCore
+  #can generate it as follow:
+  my $objectDC = Koha::DublinCore->new({
+        type => 'rdf',
+        qualified => 0,
+        get_marc_record => $record});
+
+  #DC-RDF
+  my $objectDC = Koha::DublinCore->new({
+        type => 'rdf',
+        qualified => 1,
+        get_marc_record => $record});
+
+  #The get_rdf_data method for RDF does not need to use the root element
+  #and the schema, but you need to declare the resource being described,
+  #i.e., the record.
+  #Note: For Koha is the IRI identifier of the record
+  $objectDC->get_rdf_data({
+        rdf_subject => 'http://opac.mydomain.edu/cgi-bin/koha/opac-detail.pl?biblionumber=17589',
+  });
+
+  my $XML-RDF = $objectDC->write_rdf();
+  print $XML-RDF;
+  #Close the file according to MARC::File::USMARC
+  $batch->close();
+  undef $marc;
+
+=head1 DESCRIPTION
+
+The Koha::DublinCore defines the interface to transform
+and manipulate MARC records into DC-XML or DC-RDF recommendation.
+This package transform MARC records to XML or RDF/XML Dublin Core
+and follows the recommendations listed below:
+
+L<DC-XML-GUIDELINES [DCMI Recommendation]|http://dublincore.org/documents/dc-xml-guidelines/>
+
+L<Expressing Simple Dublin Core in RDF-XML|http://dublincore.org/documents/dcmes-xml/>
+This recommendation is superseded by DC-RDFrecommendation but not obsoleted at all.
+
+L<DC-RDF [DCMI Recommendation]|http://dublincore.org/documents/dc-rdf/>
+
+=head2 Methods
+
+=over 12
+
+=item C<new>
+
+Return a new Koha::DublinCore object.
+This constructor sets the output type (RDF or XML), the level of the standard (Simple DC or Qualified DC) and the MARC record to be transformed to DC.
+
+  my $objectDC = Koha::DublinCore->new({
+        type => 'rdf',
+        qualified => 0,
+        get_marc_record => $record});
+
+=item C<get_xml_data>
+
+This method is just for DC-XML: Fetch the xml root element and the schema in .xsd format.
+
+  $objectDC->get_xml_data({
+        root => 'metadata',
+        xsi_schemaLocation => 'http://example.org/myapp/ http://example.org/myapp/schema.xsd',
+        entities => 1,
+  });
+
+The entities argument is for extended xml entities, i.e., placing entities to zero will codify only the five basic entities e.g., &lt, &gt, &quot, &amp, and &apos. Conversely if it is encoded to one, all entities will coded into decimal.
+
+Additionally, has been included the opt_namespace and opt_namespace_url arguments to include another XML name space, like OAI-DC or SRW-DC.
+
+NOTE: This method is only for use of the DC-XML recommendation, i.e., type => 'xml'.
+See C<new> method or the section SYNOPSIS.
+
+=item C<get_rdf_data>
+
+This method is only for DC-RDF: Fetch the IRI identifier of the resource being described. As well, you can pass the format you want to generate with the rdf, by default the DC-RDF specify RDF/XML but RDF can represent in other formats listed below:
+
+. ntriples
+
+. nquads
+
+. rdfxml
+
+. rdfjson
+
+. ntriples-canonical
+
+. turtle
+
+    $objectDC->get_rdf_data({
+        rdf_subject => 'http://opac.mydomain.edu/cgi-bin/koha/opac-detail.pl?biblionumber=17589',
+        rdf_format => 'rdfxml',
+        entities => 0|1,
+    });
+
+NOTE: The entities is needed only for rdfxml value and is used like C<get_xml_data> method.
+
+=item C<write_xml>
+
+Return the xml object as string.
+
+NOTE: This method is only for use of the DC-XML recommendation, i.e., type => 'xml'.
+See C<new> and C<get_xml_data> methods or the section SYNOPSIS.
+
+=item C<write_rdf>
+
+Return the rdf object as string.
+
+NOTE: This method is only for use of the DC-RDF recommendation, i.e., type => 'rdf'.
+See C<new> and C<get_rdf_data> methods or the section SYNOPSIS.
+
+=back
+
+=head1 VERSION
+
+version 0.01
+
+=head1 RELATES MODULES
+
+This package requires the following modules:
+
+L<DublinCore::Record>
+
+L<MARC::Record>
+
+L<MARC::File::USMARC>
+
+L<MARC::Crosswalk::DublinCore>
+
+L<XML::LibXML>
+
+L<RDF::Trine>
+
+L<C4::Record>
+
+=head2 SEE ALSO
+
+Dublin Core Web Page L<http://dublincore.org>.
+
+=head1 LICENSE
+
+Copyright (c) 2014 Koha Community. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
+
+=head1 AUTHOR
+
+Hector Eduardo Catro Avalos E<lt> hector.hecaxmmx at gmail dot com E<gt>
+and the Koha Development Team.
+
+=cut
diff --git a/catalogue/export.pl b/catalogue/export.pl
index e66d3f2..c4e0617 100755
--- a/catalogue/export.pl
+++ b/catalogue/export.pl
@@ -26,6 +26,14 @@ my $format=$query->param("format");
 my $error = '';
 if ($op eq "export") {
     my $biblionumber = $query->param("bib");
+    my $recommendation = $query->param("recommendation");
+    my $formats = $query->param("formats");
+    my $qualifier = $query->param("qualifier");
+    my $root_element = $query->param("root_element");
+    my $xsischemalocation = $query->param("xsischemalocation");
+    my $resource_url = $query->url(-base => 1) .
+                       '/cgi-bin/koha/catalogue/detail.pl?biblionumber=' .
+                       $biblionumber;
         if ($biblionumber){
 
             my $marc = GetMarcBiblio($biblionumber, 1);
@@ -51,8 +59,32 @@ if ($op eq "export") {
                 $format = "bibtex";
             }
             elsif ($format =~ /dc/) {
-                ($error,$marc) = marc2dcxml($marc,1);
-                $format = "dublin-core.xml";
+                SWITCH:
+                    for ($recommendation) {
+                        if (/^simple-dc-rdf/) {
+                            ($error,$marc) = marc2dcxml($marc, $recommendation, 0,
+                            1, undef, undef, $resource_url , $formats);
+                            $format = "dublin-core." . $formats;
+                            last SWITCH; }
+                        if (/^dc-rdf/) {
+                            ($error,$marc) = marc2dcxml($marc, $recommendation, 1,
+                            1, undef, undef, $resource_url, $formats);
+                            $format = "dublin-core." . $formats;
+                            last SWITCH; }
+                        if (/^dc-xml/) {
+                            ($error,$marc) = marc2dcxml($marc, $recommendation, $qualifier,
+                            1, $root_element, $xsischemalocation, undef, undef);
+                            $format = "dublin-core.xml";
+                            last SWITCH; }
+                        if (/^oai-dc/) {
+                            ($error,$marc) = marc2dcxml($marc, $recommendation);
+                            $format = "dublin-core.xml";
+                            last SWITCH; }
+                        if (/^srw_dc/) {
+                            ($error,$marc) = marc2dcxml($marc, $recommendation);
+                            $format = "dublin-core.xml";
+                            last SWITCH; }
+                    }
             }
             elsif ($format =~ /marc8/) {
                 $marc = changeEncoding($marc,"MARC","MARC21","MARC-8");
diff --git a/debian/control b/debian/control
index 429b4d4..f825377 100644
--- a/debian/control
+++ b/debian/control
@@ -43,6 +43,7 @@ Build-Depends: libalgorithm-checkdigits-perl,
  libdbi-perl,
  libdbix-class-schema-loader-perl,
  libdbix-connector-perl,
+ libdevel-cover-perl,
  libdigest-sha-perl | perl,
  libemail-date-perl,
  libemail-valid-perl,
@@ -87,6 +88,7 @@ Build-Depends: libalgorithm-checkdigits-perl,
  libpdf-reuse-barcode-perl,
  libpdf-reuse-perl,
  libpdf-table-perl,
+ librdf-trine-perl,
  libscalar-list-utils-perl,
  libschedule-at-perl,
  libsms-send-perl,
@@ -124,7 +126,7 @@ Build-Depends: libalgorithm-checkdigits-perl,
  libyaml-perl,
  libyaml-syck-perl,
  perl,
- perl-modules,
+ perl-modules, 
  debhelper (>= 7.0.50), gettext, xsltproc, docbook-xsl,
  libxml2-utils, bash-completion, perl-modules (>= 5.14.2) | libtest-simple-perl (>= 0.98)
 
@@ -239,6 +241,7 @@ Depends: libalgorithm-checkdigits-perl,
  libdbi-perl,
  libdbix-class-schema-loader-perl,
  libdbix-connector-perl,
+ libdevel-cover-perl,
  libdigest-sha-perl | perl,
  libemail-date-perl,
  libemail-valid-perl,
@@ -283,6 +286,7 @@ Depends: libalgorithm-checkdigits-perl,
  libpdf-reuse-barcode-perl,
  libpdf-reuse-perl,
  libpdf-table-perl,
+ librdf-trine-perl,
  libscalar-list-utils-perl,
  libschedule-at-perl,
  libsms-send-perl,
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc
index ee39f31..d5b454d 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc
@@ -221,7 +221,7 @@ CAN_user_serials_create_subscription ) %]
     <button class="btn btn-small dropdown-toggle" data-toggle="dropdown"><i class="icon-download-alt"></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>
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt
index b782616..9349713 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt
@@ -303,6 +303,83 @@ function verify_images() {
 
         [% END %]
     });
+
+    //JQuery for Dublin Core Modal
+    $(document).ready(function(){
+        $("#input-simple").click(function(){
+            $(".rdfoptions").removeAttr("disabled");
+            $(".xmloptions").attr("disabled","disabled");
+            $("#dc-rdf").toggle();
+            $("#dc-xml").hide();
+        });
+    });
+
+    $(document).ready(function(){
+        $("#input-rdf").click(function(){
+            $(".rdfoptions").removeAttr("disabled");
+            $(".xmloptions").attr("disabled","disabled");
+            $("#dc-rdf").toggle();
+            $("#dc-xml").hide();
+        });
+    });
+
+    $(document).ready(function(){
+        $("#input-xml").click(function(){
+            $(".xmloptions").removeAttr("disabled");
+            $(".rdfoptions").attr("disabled","disabled");
+                if($("#root_checked").is(':checked')){
+                    $("#root_value").removeAttr("disabled");
+                } else {
+                    $("#root_value").attr("disabled","disabled");
+                }
+                if($("#schema_checked").is(':checked')){
+                    $("#schema_value").removeAttr("disabled");
+                } else {
+                    $("#schema_value").attr("disabled","disabled");
+                }
+                $("#dc-xml").toggle();
+                $("#dc-rdf").hide();
+        });
+    });
+
+    $(document).ready(function(){
+        $("#root_checked").click(function(){
+            if($("#root_checked").is(':checked')){
+                $("#root_value").removeAttr("disabled");
+            } else {
+                $("#root_value").attr("disabled","disabled");
+            }
+        });
+    });
+
+    $(document).ready(function(){
+        $("#schema_checked").click(function(){
+            if($("#schema_checked").is(':checked')){
+                $("#schema_value").removeAttr("disabled");
+            } else {
+                $("#schema_value").attr("disabled","disabled");
+            }
+        });
+    });
+
+    $(document).ready(function(){
+        $("#input-oai").click(function(){
+            $(".rdfoptions").attr("disabled","disabled");
+            $(".xmloptions").attr("disabled","disabled");
+            $("#dc-rdf").hide();
+            $("#dc-xml").hide();
+        });
+    });
+
+    $(document).ready(function(){
+        $("#input-srw").click(function(){
+            $(".rdfoptions").attr("disabled","disabled");
+            $(".xmloptions").attr("disabled","disabled");
+            $("#dc-rdf").hide();
+            $("#dc-xml").hide();
+        });
+    });
+
 //]]>
 </script>
 </head>
@@ -1043,7 +1120,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>
@@ -1076,4 +1153,68 @@ function verify_images() {
 </div>
 [% END %]
 </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 to recolect data for Dublin Core-->
+        <form method="get" action="/cgi-bin/koha/catalogue/export.pl">
+        <div class="modal-body">
+            <fieldset>
+                <input id="input-simple" type="radio" name="recommendation" value="simple-dc-rdf">Simple DC-RDF
+                <br>
+                <input id="input-rdf" type="radio" name="recommendation" value="dc-rdf" checked>DC-RDF (Recommended)
+                <div id="dc-rdf" style="display:none;">
+                    <br>DC-RDF is downloadable in &quot;rdfxml&quot; by default (this is according with the
+                    <br>recommendation),  but you can download the file in other formats:
+                    <br>
+                    <input class="rdfoptions" type="radio" name="formats" value="rdfxml" checked>rdfxml
+                    <input class="rdfoptions" type="radio" name="formats" value="rdfjson">rdfjson
+                    <input class="rdfoptions" type="radio" name="formats" value="ntriples">ntriples
+                    <input class="rdfoptions" type="radio" name="formats" value="nquads">nquads
+                    <input class="rdfoptions" type="radio" name="formats" value="ntriples-canonical">ntriples-canonical
+                    <input class="rdfoptions" type="radio" name="formats" value="turtle">turtle
+                </div>
+                <br>
+                <input id="input-xml" type="radio" name="recommendation" value="dc-xml">DC-XML
+                <div id="dc-xml" style="display:none;">
+                    <p><b>Output options for DC-XML</b>
+                    <br>
+                    <b>Dublin Core level</b></p>
+                    <p><input class="xmloptions" type="radio" name="qualifier" value="0" checked disabled>Simple Dublin Core
+                    <input class="xmloptions" type="radio" name="qualifier" value="1" disabled>Qualified Dublin Core</p>
+                    <b>Other data (Optional)</b>
+                    <br>
+                    <input id="root_checked" class="xmloptions" type="checkbox" value="root">
+                    Root element: <input id="root_value" class="xmloptions" type="text" name="root_element" value="metadata" disabled>
+                    <br>The xsischemaLocation should be filled like:
+                    <br>http://example.org/myapp/ http://example.org/myapp/schema.xsd
+                    <br>
+                    <input id="schema_checked" class="xmloptions" type="checkbox" value="schema" disabled>
+                    xsischemaLocation: <input id="schema_value" class="xmloptions" type="url" name="xsischemalocation" disabled><br>
+                </div>
+                <br>
+                <input id="input-oai" type="radio" name="recommendation" value="oai-dc">OAI-DC
+                <br>
+                <input id="input-srw" type="radio" name="recommendation" value="srw_dc">SRW-DC
+                <br>
+                <div>
+                <br>Learn more about DCMI Specifications at: <a href="http://dublincore.org/specifications/">http://dublincore.org/specifications/</a>
+                <br>
+                </div>
+            </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="format" value="dc" />
+        <input type="hidden" name="bib" value="[% biblionumber %]" />
+        </form>
+    </div>
+
 [% INCLUDE 'intranet-bottom.inc' %]
diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc b/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc
index aeca007..6fe1a3c 100644
--- a/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc
+++ b/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc
@@ -316,3 +316,69 @@
             </div>
         </form> <!-- /#auth -->
     </div>  <!-- /#modalAuth  -->
+
+    <!-- Dublin Core Modal Form -->
+    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+        <div class="modal-dialog">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">&times;</button>
+                    <h4 class="modal-title" id="myModalLabel">Exporting to Dublin Core...</h4>
+                </div>
+                <form method="get" action="/cgi-bin/koha/opac-export.pl">
+                    <div class="modal-body">
+                        <fieldset>
+                            <input id="input-simple" type="radio" name="recommendation" value="simple-dc-rdf">Simple DC-RDF
+                            <br>
+                            <input id="input-rdf" type="radio" name="recommendation" value="dc-rdf" checked>DC-RDF (Recommended)
+                            <div id="dc-rdf" style="display:none;">
+                                <br>DC-RDF is downloadable in &quot;rdfxml&quot; by default (this is according with the
+                                <br>recommendation),  but you can download the file in other formats:
+                                <br>
+                                <input class="rdfoptions" type="radio" name="formats" value="rdfxml" checked>rdfxml
+                                <input class="rdfoptions" type="radio" name="formats" value="rdfjson">rdfjson
+                                <input class="rdfoptions" type="radio" name="formats" value="ntriples">ntriples
+                                <input class="rdfoptions" type="radio" name="formats" value="nquads">nquads
+                                <input class="rdfoptions" type="radio" name="formats" value="ntriples-canonical">ntriples-canonical
+                                <input class="rdfoptions" type="radio" name="formats" value="turtle">turtle
+                            </div>
+                            <br>
+                            <input id="input-xml" type="radio" name="recommendation" value="dc-xml">DC-XML
+                            <div id="dc-xml" style="display:none;">
+                                <p><b>Output options for DC-XML</b>
+                                <br>
+                                <b>Dublin Core level</b></p>
+                                <p><input class="xmloptions" type="radio" name="qualifier" value="0" checked disabled>Simple Dublin Core
+                                <input class="xmloptions" type="radio" name="qualifier" value="1" disabled>Qualified Dublin Core</p>
+                                <b>Other data (Optional)</b>
+                                <br>
+                                <input id="root_checked" class="xmloptions" type="checkbox" value="root">
+                                Root element: <input id="root_value" class="xmloptions" type="text" name="root_element" value="metadata" disabled>
+                                <br>The xsischemaLocation should be filled like:
+                                <br>http://example.org/myapp/ http://example.org/myapp/schema.xsd
+                                <br>
+                                <input id="schema_checked" class="xmloptions" type="checkbox" value="schema" disabled>
+                                xsischemaLocation: <input id="schema_value" class="xmloptions" type="url" name="xsischemalocation" disabled><br>
+                            </div>
+                            <br>
+                            <input id="input-oai" type="radio" name="recommendation" value="oai-dc">OAI-DC
+                            <br>
+                            <input id="input-srw" type="radio" name="recommendation" value="srw_dc">SRW-DC
+                            <br>
+                            <div>
+                                <br>Learn more about DCMI Specifications at: <a href="http://dublincore.org/specifications/">http://dublincore.org/specifications/</a>
+                                <br>
+                            </div>
+                        </fieldset>
+                    </div>
+                    <div class="modal-footer">
+                        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+                        <button type="submit" class="btn btn-primary">Export</button>
+                    </div>
+                    <input type="hidden" name="op" value="export" />
+                    <input type="hidden" name="format" value="dc" />
+                    <input type="hidden" name="bib" value="[% biblionumber %]" />
+                </form>
+            </div>
+        </div>
+    </div>
diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-detail-sidebar.inc b/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-detail-sidebar.inc
index a4ef40e..069c0cf 100644
--- a/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-detail-sidebar.inc
+++ b/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-detail-sidebar.inc
@@ -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="#myModal">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>
diff --git a/koha-tmpl/opac-tmpl/bootstrap/js/script.js b/koha-tmpl/opac-tmpl/bootstrap/js/script.js
index de8401b..29b6108 100644
--- a/koha-tmpl/opac-tmpl/bootstrap/js/script.js
+++ b/koha-tmpl/opac-tmpl/bootstrap/js/script.js
@@ -63,4 +63,80 @@ $(document).ready(function(){
             $("#members").removeAttr("style");
         }
     });
-});
\ No newline at end of file
+});
+
+    //JQuery for Dublin Core Modal
+    $(document).ready(function(){
+        $("#input-simple").click(function(){
+            $(".rdfoptions").removeAttr("disabled");
+            $(".xmloptions").attr("disabled","disabled");
+            $("#dc-rdf").toggle();
+            $("#dc-xml").hide();
+        });
+    });
+
+    $(document).ready(function(){
+        $("#input-rdf").click(function(){
+            $(".rdfoptions").removeAttr("disabled");
+            $(".xmloptions").attr("disabled","disabled");
+            $("#dc-rdf").toggle();
+            $("#dc-xml").hide();
+        });
+    });
+
+    $(document).ready(function(){
+        $("#input-xml").click(function(){
+            $(".xmloptions").removeAttr("disabled");
+            $(".rdfoptions").attr("disabled","disabled");
+                if($("#root_checked").is(':checked')){
+                    $("#root_value").removeAttr("disabled");
+                } else {
+                    $("#root_value").attr("disabled","disabled");
+                }
+                if($("#schema_checked").is(':checked')){
+                    $("#schema_value").removeAttr("disabled");
+                } else {
+                    $("#schema_value").attr("disabled","disabled");
+                }
+                $("#dc-xml").toggle();
+                $("#dc-rdf").hide();
+        });
+    });
+
+    $(document).ready(function(){
+        $("#root_checked").click(function(){
+            if($("#root_checked").is(':checked')){
+                $("#root_value").removeAttr("disabled");
+            } else {
+                $("#root_value").attr("disabled","disabled");
+            }
+        });
+    });
+
+    $(document).ready(function(){
+        $("#schema_checked").click(function(){
+            if($("#schema_checked").is(':checked')){
+                $("#schema_value").removeAttr("disabled");
+            } else {
+                $("#schema_value").attr("disabled","disabled");
+            }
+        });
+    });
+
+    $(document).ready(function(){
+        $("#input-oai").click(function(){
+            $(".rdfoptions").attr("disabled","disabled");
+            $(".xmloptions").attr("disabled","disabled");
+            $("#dc-rdf").hide();
+            $("#dc-xml").hide();
+        });
+    });
+
+    $(document).ready(function(){
+        $("#input-srw").click(function(){
+            $(".rdfoptions").attr("disabled","disabled");
+            $(".xmloptions").attr("disabled","disabled");
+            $("#dc-rdf").hide();
+            $("#dc-xml").hide();
+        });
+    });
diff --git a/opac/opac-export.pl b/opac/opac-export.pl
index bf040db..c7bfe61 100755
--- a/opac/opac-export.pl
+++ b/opac/opac-export.pl
@@ -34,6 +34,14 @@ my $format=$query->param("format")||'utf8';
 my $biblionumber = $query->param("bib")||0;
 $biblionumber = int($biblionumber);
 my ($marc, $error)= ('','');
+my $recommendation = $query->param("recommendation");
+my $formats = $query->param("formats");
+my $qualifier = $query->param("qualifier");
+my $root_element = $query->param("root_element");
+my $xsischemalocation = $query->param("xsischemalocation");
+my $resource_url = $query->url(-base => 1) .
+                   '/cgi-bin/koha/opac-detail.pl?biblionumber=' .
+                   $biblionumber;
 
 $marc = GetMarcBiblio($biblionumber, 1) if $biblionumber;
 if(!$marc) {
@@ -61,8 +69,32 @@ elsif ($format =~ /bibtex/) {
     $format = 'bibtex';
 }
 elsif ($format =~ /dc/) {
-    ($error,$marc) = marc2dcxml($marc,1);
-    $format = "dublin-core.xml";
+    SWITCH:
+        for ($recommendation) {
+            if (/^simple-dc-rdf/) {
+                ($error,$marc) = marc2dcxml($marc, $recommendation, 0,
+                1, undef, undef, $resource_url , $formats);
+                $format = "dublin-core." . $formats;
+                last SWITCH; }
+            if (/^dc-rdf/) {
+                ($error,$marc) = marc2dcxml($marc, $recommendation, 1,
+                1, undef, undef, $resource_url, $formats);
+                $format = "dublin-core." . $formats;
+                last SWITCH; }
+            if (/^dc-xml/) {
+                ($error,$marc) = marc2dcxml($marc, $recommendation, $qualifier,
+                1, $root_element, $xsischemalocation, undef, undef);
+                $format = "dublin-core.xml";
+                last SWITCH; }
+            if (/^oai-dc/) {
+                ($error,$marc) = marc2dcxml($marc, $recommendation);
+                $format = "dublin-core.xml";
+                last SWITCH; }
+            if (/^srw_dc/) {
+                ($error,$marc) = marc2dcxml($marc, $recommendation);
+                $format = "dublin-core.xml";
+                last SWITCH; }
+        }
 }
 elsif ($format =~ /marc8/) {
     ($error,$marc) = changeEncoding($marc,"MARC","MARC21","MARC-8");
diff --git a/t/db_dependent/Record.t b/t/db_dependent/Record.t
index e8d6094..d372c4c 100755
--- a/t/db_dependent/Record.t
+++ b/t/db_dependent/Record.t
@@ -46,29 +46,22 @@ is ($marcxml, $testxml, "testing marc2xml");
 my $marcconvert=marcxml2marc($marcxml);
 is ($marcconvert->as_xml,$marc->as_xml, "testing xml2marc");
 
-my $marcdc=marc2dcxml($marc);
-my $test2xml=qq(<?xml version="1.0" encoding="UTF-8"?>
-<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/">
-</metadata>);
-
-is ($marcdc, $test2xml, "testing marc2dcxml");
-
-my $marcqualified=marc2dcxml($marc,1);
-my $test3xml=qq(<?xml version="1.0" encoding="UTF-8"?>
-<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/">
-</metadata>);
-
-is ($marcqualified, $test3xml, "testing marcQualified");
+my $marcrdf=marc2dcxml($marc, 'dc-rdf', 1,
+                      0, undef, undef, undef, 'rdfxml');
+my $test2xml=qq(<?xml version="1.0" encoding="utf-8"?>
+<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dcam="http://purl.org/dc/dcam/" xmlns:dcterms="http://purl.org/dc/terms/">
+</rdf:RDF>
+);
+
+is ($marcrdf, $test2xml, "testing marc2dcxml with dc-rdf");
+
+my $marcdc=marc2dcxml($marc, 'dc-xml', 0,
+                      0, 'metadata', undef, undef, undef);
+my $test3xml=qq(<?xml version="1.0" encoding="utf-8"?>
+<metadata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dc="http://purl.org/dc/elements/1.1/"/>
+);
+
+is ($marcdc, $test3xml, "testing marc2dcxml with unqualified dc-xml");
 
 my $mods=marc2modsxml($marc);
 my $test4xml=qq(<?xml version="1.0" encoding="UTF-8"?>
-- 
1.7.10.4