diff --git a/solidify-oai-model/src/main/java/ch/unige/solidify/OAIConstants.java b/solidify-oai-model/src/main/java/ch/unige/solidify/OAIConstants.java
index 2ef969f7ad513c7724e722060c5d0fec5d39e81c..fe2acee2f3be0925dc93656c822d1b1c192b34f0 100644
--- a/solidify-oai-model/src/main/java/ch/unige/solidify/OAIConstants.java
+++ b/solidify-oai-model/src/main/java/ch/unige/solidify/OAIConstants.java
@@ -9,12 +9,12 @@
  * it under the terms of the GNU General Public License as
  * published by the Free Software Foundation, either version 2 of the
  * License, or (at your option) any later version.
- * 
+ *
  * This program 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 this program.  If not, see
  * <http://www.gnu.org/licenses/gpl-2.0.html>.
@@ -61,6 +61,7 @@ public class OAIConstants {
   // OAI Provider
   public static final String OAI_PMH = "OAI-PMH";
   public static final String OAI_PMH_SCHEMA = "http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd";
+  public static final String OAI_PMH_PREFIX_NAMESPACE = "oai-pmh";
   public static final String OAI_PMH_NAMESPACE = "http://www.openarchives.org/OAI/2.0/";
   // OAI Dublin Core
   public static final String OAI_DC = "oai_dc";
diff --git a/solidify-oai-model/src/main/java/ch/unige/solidify/OAIProperties.java b/solidify-oai-model/src/main/java/ch/unige/solidify/OAIProperties.java
index 38cc63c1816c14c7706a1290afcfc7816e3910c8..e28850dac1b51737fc3f3bc4a483cdec2534b0b9 100644
--- a/solidify-oai-model/src/main/java/ch/unige/solidify/OAIProperties.java
+++ b/solidify-oai-model/src/main/java/ch/unige/solidify/OAIProperties.java
@@ -9,12 +9,12 @@
  * it under the terms of the GNU General Public License as
  * published by the Free Software Foundation, either version 2 of the
  * License, or (at your option) any later version.
- * 
+ *
  * This program 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 this program.  If not, see
  * <http://www.gnu.org/licenses/gpl-2.0.html>.
@@ -32,6 +32,9 @@ public class OAIProperties {
   private int pageSize = 100;
   private int tokenLifeTimeMinutes = 5;
 
+  // Parameter that defines if metadata contents must be serialized with their XML namespaces
+  private boolean serializeMetadataWithNamespaces = false;
+
   public int getPageSize() {
     return this.pageSize;
   }
@@ -48,4 +51,11 @@ public class OAIProperties {
     this.tokenLifeTimeMinutes = tokenLifeTimeMinutes;
   }
 
+  public boolean isSerializeMetadataWithNamespaces() {
+    return this.serializeMetadataWithNamespaces;
+  }
+
+  public void setSerializeMetadataWithNamespaces(boolean serializeMetadataWithNamespaces) {
+    this.serializeMetadataWithNamespaces = serializeMetadataWithNamespaces;
+  }
 }
diff --git a/solidify-oai-model/src/main/java/ch/unige/solidify/OAIXmlNamespacePrefixMapper.java b/solidify-oai-model/src/main/java/ch/unige/solidify/OAIXmlNamespacePrefixMapper.java
index d3911c1e136e4ebfcb9ef47dc83fb243579b8117..c39570df27fce3e6f265c0a294a86db0677be000 100644
--- a/solidify-oai-model/src/main/java/ch/unige/solidify/OAIXmlNamespacePrefixMapper.java
+++ b/solidify-oai-model/src/main/java/ch/unige/solidify/OAIXmlNamespacePrefixMapper.java
@@ -9,12 +9,12 @@
  * it under the terms of the GNU General Public License as
  * published by the Free Software Foundation, either version 2 of the
  * License, or (at your option) any later version.
- * 
+ *
  * This program 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 this program.  If not, see
  * <http://www.gnu.org/licenses/gpl-2.0.html>.
@@ -29,6 +29,7 @@ public class OAIXmlNamespacePrefixMapper extends XmlNamespacePrefixMapper {
 
   public OAIXmlNamespacePrefixMapper() {
     super();
+    this.addSchema(OAIConstants.OAI_PMH_NAMESPACE, OAIConstants.OAI_PMH_PREFIX_NAMESPACE);
     this.addSchema(OAIConstants.OAI_DC_NAMESPACE, OAIConstants.OAI_DC);
     this.addSchema(OAIConstants.OAI_ID_NAMESPACE, OAIConstants.OAI_ID);
     this.addSchema(OAIConstants.DC_NAMESPACE, OAIConstants.DC);
diff --git a/solidify-oai-model/src/main/java/ch/unige/solidify/model/oai/MetadataContent.java b/solidify-oai-model/src/main/java/ch/unige/solidify/model/oai/MetadataContent.java
new file mode 100644
index 0000000000000000000000000000000000000000..91e01ce085e6b3525a99b9e62e3371e3777f90d7
--- /dev/null
+++ b/solidify-oai-model/src/main/java/ch/unige/solidify/model/oai/MetadataContent.java
@@ -0,0 +1,34 @@
+/*-
+ * %%----------------------------------------------------------------------------------------------
+ * Solidify Framework - Solidify OAI-PMH Model - MetadataContent.java
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * %----------------------------------------------------------------------------------------------%
+ * Copyright (C) 2017 - 2022 University of Geneva
+ * %----------------------------------------------------------------------------------------------%
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 this program.  If not, see
+ * <http://www.gnu.org/licenses/gpl-2.0.html>.
+ * ----------------------------------------------------------------------------------------------%%
+ */
+package ch.unige.solidify.model.oai;
+
+import java.io.Serializable;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlRootElement(name = "metadataContent")
+public class MetadataContent implements Serializable {
+  private final static long serialVersionUID = 1L;
+}
diff --git a/solidify-oai-model/src/main/java/ch/unige/solidify/model/oai/OAIRepositoryInfo.java b/solidify-oai-model/src/main/java/ch/unige/solidify/model/oai/OAIRepositoryInfo.java
index 98f815ce30637fd1f914d229976315aa4d1e39d9..cea32d01830005b076246ab1f68cc2ee72870943 100644
--- a/solidify-oai-model/src/main/java/ch/unige/solidify/model/oai/OAIRepositoryInfo.java
+++ b/solidify-oai-model/src/main/java/ch/unige/solidify/model/oai/OAIRepositoryInfo.java
@@ -9,12 +9,12 @@
  * it under the terms of the GNU General Public License as
  * published by the Free Software Foundation, either version 2 of the
  * License, or (at your option) any later version.
- * 
+ *
  * This program 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 this program.  If not, see
  * <http://www.gnu.org/licenses/gpl-2.0.html>.
@@ -47,7 +47,7 @@ public interface OAIRepositoryInfo {
 
   JAXBElement<?> getRepositoryDefinition();
 
-  String getRepositoryNamepsace();
+  String getRepositoryNamespace();
 
   String getRepositorySchema();
 }
diff --git a/solidify-oai-pmh/src/main/java/ch/unige/solidify/controller/oai/OAIProviderController.java b/solidify-oai-pmh/src/main/java/ch/unige/solidify/controller/oai/OAIProviderController.java
index 83b98b87ad7c4a6e8992538b4a33f48572425cce..b8f99fdc3ec6fda47ade8e19be6339f58b44c0aa 100644
--- a/solidify-oai-pmh/src/main/java/ch/unige/solidify/controller/oai/OAIProviderController.java
+++ b/solidify-oai-pmh/src/main/java/ch/unige/solidify/controller/oai/OAIProviderController.java
@@ -9,12 +9,12 @@
  * it under the terms of the GNU General Public License as
  * published by the Free Software Foundation, either version 2 of the
  * License, or (at your option) any later version.
- * 
+ *
  * This program 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 this program.  If not, see
  * <http://www.gnu.org/licenses/gpl-2.0.html>.
@@ -31,7 +31,6 @@ import java.time.Instant;
 import java.time.ZoneOffset;
 import java.util.HashMap;
 import java.util.Map;
-
 import javax.servlet.http.HttpServletRequest;
 import javax.xml.bind.JAXBException;
 
@@ -118,7 +117,7 @@ public class OAIProviderController implements ControllerWithHateoasHome {
           // Force http usage, in order to be compatible with old XML validators
           final String httpOnlyOaiUrl = oaiUrl.replace("https://", "http://");
           schemaLocations.put(
-                  this.oaiService.getOaiRepositoryInfo().getRepositoryNamepsace(),
+                  this.oaiService.getOaiRepositoryInfo().getRepositoryNamespace(),
                   httpOnlyOaiUrl + SolidifyConstants.URL_SEP + SolidifyConstants.SCHEMA);
           break;
         case LIST_IDENTIFIERS:
diff --git a/solidify-oai-pmh/src/main/java/ch/unige/solidify/service/OAIService.java b/solidify-oai-pmh/src/main/java/ch/unige/solidify/service/OAIService.java
index e94cc744b6f4bcaf3c88f0dc1c256b171721e375..f04378e85851683a8491ce5186035262f1bd6833 100644
--- a/solidify-oai-pmh/src/main/java/ch/unige/solidify/service/OAIService.java
+++ b/solidify-oai-pmh/src/main/java/ch/unige/solidify/service/OAIService.java
@@ -51,6 +51,7 @@ import ch.unige.solidify.business.OAISetService;
 import ch.unige.solidify.controller.OAIController;
 import ch.unige.solidify.exception.OAIException;
 import ch.unige.solidify.exception.SolidifyRuntimeException;
+import ch.unige.solidify.model.oai.MetadataContent;
 import ch.unige.solidify.model.oai.OAIMetadataPrefix;
 import ch.unige.solidify.model.oai.OAIRecord;
 import ch.unige.solidify.model.oai.OAIRepositoryInfo;
@@ -79,7 +80,6 @@ import ch.unige.solidify.model.xml.oai.v2.oai_dc.ElementType;
 import ch.unige.solidify.model.xml.oai.v2.oai_dc.OaiDcType;
 import ch.unige.solidify.model.xml.oai.v2.oai_dc.ObjectFactory;
 import ch.unige.solidify.model.xml.oai.v2.oai_identifier.OaiIdentifierType;
-import ch.unige.solidify.model.xml.xhtml.v5.Html;
 import ch.unige.solidify.rest.RestCollection;
 import ch.unige.solidify.rest.RestCollectionPage;
 import ch.unige.solidify.specification.OAIMetadataPrefixSpecification;
@@ -92,6 +92,7 @@ import ch.unige.solidify.util.XMLTool;
 public class OAIService {
 
   private final JAXBContext jaxbContext;
+
   private final int oaiPmhPageSize;
   private final int oaiPmhTokenLifeTime;
 
@@ -106,6 +107,8 @@ public class OAIService {
   private final OAIRecordService recordService;
   private final OAIMetadataService metadataService;
 
+  boolean serializeMetadataWithNamespaces;
+
   public OAIService(
           OAIProperties oaiProperties,
           OAIRepositoryInfo oaiRepositoryInfo,
@@ -117,6 +120,7 @@ public class OAIService {
     this.oaiRepositoryInfo = oaiRepositoryInfo;
     this.oaiPmhPageSize = oaiProperties.getPageSize();
     this.oaiPmhTokenLifeTime = oaiProperties.getTokenLifeTimeMinutes();
+    this.serializeMetadataWithNamespaces = oaiProperties.isSerializeMetadataWithNamespaces();
     this.oaiMetadataPrefixService = oaiMetadataPrefixService;
     this.oaiSetService = oaiSetService;
     this.searchService = searchService;
@@ -125,7 +129,8 @@ public class OAIService {
     // JAXB contexts
     try {
       // Add project XML Classes
-      final List<Class<?>> xmlClasses = new ArrayList<>(Arrays.asList(OAIPMHtype.class, OaiDcType.class, OaiIdentifierType.class, Html.class));
+      final List<Class<?>> xmlClasses = new ArrayList<>(
+              Arrays.asList(OAIPMHtype.class, OaiDcType.class, OaiIdentifierType.class, MetadataContent.class));
       xmlClasses.addAll(this.metadataService.getOaiXmlClasses());
       this.jaxbContext = JAXBContext.newInstance(xmlClasses.toArray(Class<?>[]::new));
     } catch (JAXBException e) {
@@ -355,11 +360,77 @@ public class OAIService {
                 .append(schemaLocation.getValue());
       }
     }
+
     marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, schemaLocations.toString());
     final JAXBElement<OAIPMHtype> root = this.getXML(oai);
+
+    if (this.serializeMetadataWithNamespaces) {
+      return this.serializeXmlWithNamespacesInMetadata(oai, root, marshaller, schemaLocations.toString());
+    } else {
+      final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+      marshaller.marshal(root, bos);
+      return bos.toString();
+    }
+  }
+
+  private String serializeXmlWithNamespacesInMetadata(OAIPMHtype oai, JAXBElement<OAIPMHtype> root, Marshaller marshaller,
+          String schemaLocations) throws JAXBException {
+    // Get the list of metadata contents unmarshalled separately to get their XML forms including namespaces
+    List<String> metadataContents = this.getMetadataContents(oai, schemaLocations);
+
+    // Replace metadata nodes content by an XML object that can be replaced later once serialized as String
+    MetadataContent metadataContentToReplace = new MetadataContent();
+    List<RecordType> recordTypes = this.getRecordTypes(oai);
+    for (RecordType recordType : recordTypes) {
+      recordType.getMetadata().setAny(metadataContentToReplace);
+    }
+
+    // Serialize OAI-PMH XML as String
     final ByteArrayOutputStream bos = new ByteArrayOutputStream();
     marshaller.marshal(root, bos);
-    return bos.toString();
+    String xml = bos.toString();
+
+    // Compute String that must be replaced in OAI-PMH XML
+    Marshaller metadataContentMarshaller = JAXBContext.newInstance(MetadataContent.class).createMarshaller();
+    metadataContentMarshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
+    final ByteArrayOutputStream metadataContentOutput = new ByteArrayOutputStream();
+    metadataContentMarshaller.marshal(metadataContentToReplace, metadataContentOutput);
+    String metadataContentXml = metadataContentOutput.toString();
+
+    // Replace each metadata content by the original XML contents including namespaces
+    for (String metadataContent : metadataContents) {
+      xml = xml.replaceFirst(metadataContentXml, metadataContent);
+    }
+    return xml;
+  }
+
+  private List<String> getMetadataContents(OAIPMHtype oai, String schemaLocations) throws JAXBException {
+    final Marshaller metadataMarshaller = this.metadataService.getMarshaller(this.jaxbContext);
+    metadataMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+    metadataMarshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
+    metadataMarshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, schemaLocations);
+
+    List<RecordType> recordTypes = this.getRecordTypes(oai);
+    List<String> metadataFragments = new ArrayList<>();
+    for (RecordType recordType : recordTypes) {
+      Object metadataXml = recordType.getMetadata().getAny();
+      final ByteArrayOutputStream metadataOutput = new ByteArrayOutputStream();
+      metadataMarshaller.marshal(metadataXml, metadataOutput);
+      metadataFragments.add(metadataOutput.toString().trim());
+    }
+    return metadataFragments;
+  }
+
+  private List<RecordType> getRecordTypes(OAIPMHtype oai) {
+    List<RecordType> recordTypes = new ArrayList<>();
+    if (oai.getGetRecord() != null) {
+      recordTypes.add(oai.getGetRecord().getRecord());
+    } else if (oai.getListRecords() != null) {
+      for (RecordType recordType : oai.getListRecords().getRecord()) {
+        recordTypes.add(recordType);
+      }
+    }
+    return recordTypes;
   }
 
   private void addOaiSetInfo(HeaderType hdr, String resId) {