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 2ac9ad92d071b5c87fa376b2d635dcf409b03cd0..2ef969f7ad513c7724e722060c5d0fec5d39e81c 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
@@ -69,6 +69,7 @@ public class OAIConstants {
   public static final String OAI_DC_NAMESPACE = "http://www.openarchives.org/OAI/2.0/oai_dc/";
   // OAI Identifier
   public static final String OAI_ID = "oai-identifier";
+  public static final String OAI_ID_SCHEMA = "http://www.openarchives.org/OAI/2.0/oai-identifier.xsd";
   public static final String OAI_ID_NAMESPACE = "http://www.openarchives.org/OAI/2.0/oai-identifier";
   // Dublin Core
   public static final String DC = "dc";
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 bfb61be0cd24c052461d81ad6275554d3ae62cc7..98f815ce30637fd1f914d229976315aa4d1e39d9 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
@@ -47,4 +47,7 @@ public interface OAIRepositoryInfo {
 
   JAXBElement<?> getRepositoryDefinition();
 
+  String getRepositoryNamepsace();
+
+  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 78293bdbf9f4485c8bc123aace1f54cdc04cf3c6..b37b9dbc41491c70ade437818f7be63439da474f 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
@@ -29,6 +29,8 @@ import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
 import java.io.IOException;
 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;
@@ -61,6 +63,7 @@ import ch.unige.solidify.controller.OAIController;
 import ch.unige.solidify.exception.OAIException;
 import ch.unige.solidify.exception.SolidifyResourceNotFoundException;
 import ch.unige.solidify.exception.SolidifyRuntimeException;
+import ch.unige.solidify.model.oai.OAIMetadataPrefix;
 import ch.unige.solidify.model.oai.OAIPMH;
 import ch.unige.solidify.model.xml.oai.v2.OAIPMHerrorcodeType;
 import ch.unige.solidify.model.xml.oai.v2.OAIPMHtype;
@@ -92,6 +95,7 @@ public class OAIProviderController implements ControllerWithHateoasHome {
           @RequestParam(value = OAIConstants.OAI_VIEW, required = false) String smartView) {
     final OAIPMHtype oai = new OAIPMHtype();
     final String oaiUrl = this.getBaseUrl(request) + this.getRequestUri(request); // OAI provider base URL
+    final Map<String, String> schemaLocations = new HashMap<>();
     try {
       switch (this.oaiService.getVerb(verb)) {
         case GET_RECORD:
@@ -99,12 +103,20 @@ public class OAIProviderController implements ControllerWithHateoasHome {
           // ------------
           // https://www.openarchives.org/OAI/openarchivesprotocol.html#GetRecord
           oai.setGetRecord(this.oaiService.getRecord(this.getRootUrl(request), identifier, metadataPrefix));
+          final OAIMetadataPrefix oaiMetadataPrefixForRecord = this.oaiService.getOAIMetadataPrefix(metadataPrefix);
+          schemaLocations.put(oaiMetadataPrefixForRecord.getSchemaNamespace(), oaiMetadataPrefixForRecord.getSchemaUrl().toString());
           break;
         case IDENTIFY:
           // Specification
           // ------------
           // https://www.openarchives.org/OAI/openarchivesprotocol.html#Identify
           oai.setIdentify(this.oaiService.getIdentify(oaiUrl));
+          // OAI Identifier
+          schemaLocations.put(OAIConstants.OAI_ID_NAMESPACE, OAIConstants.OAI_ID_SCHEMA);
+          // OAI Repository
+          schemaLocations.put(
+                  this.oaiService.getOaiRepositoryInfo().getRepositoryNamepsace(),
+                  oaiUrl + SolidifyConstants.URL_SEP + SolidifyConstants.SCHEMA);
           break;
         case LIST_IDENTIFIERS:
           // Specification
@@ -123,6 +135,8 @@ public class OAIProviderController implements ControllerWithHateoasHome {
           // ------------
           // https://www.openarchives.org/OAI/openarchivesprotocol.html#ListRecords
           oai.setListRecords(this.oaiService.listRecords(this.getBaseUrl(request), metadataPrefix, from, until, set, token));
+          final OAIMetadataPrefix oaiMetadataPrefixForList = this.oaiService.getOAIMetadataPrefix(metadataPrefix);
+          schemaLocations.put(oaiMetadataPrefixForList.getSchemaNamespace(), oaiMetadataPrefixForList.getSchemaUrl().toString());
           break;
         case LIST_SETS:
           // Specification
@@ -159,7 +173,7 @@ public class OAIProviderController implements ControllerWithHateoasHome {
       if (!StringTool.isNullOrEmpty(smartView)) {
         xslUrl = oaiUrl + SolidifyConstants.URL_SEP + SolidifyConstants.XSL + "?" + OAIConstants.OAI_VIEW + "=" + smartView;
       }
-      result = this.oaiService.printOAIPMH(oai, xslUrl);
+      result = this.oaiService.printOAIPMH(oai, xslUrl, schemaLocations);
       log.trace(result);
     } catch (final JAXBException e) {
       log.error("In converting OAI in xml", e);
@@ -180,14 +194,14 @@ public class OAIProviderController implements ControllerWithHateoasHome {
   }
 
   @GetMapping
-  public HttpEntity<?> status() {
+  public HttpEntity<OAIPMH> status() {
     final OAIPMH oaiPmh = new OAIPMH();
     final OAIPMHtype oai = new OAIPMHtype();
     final WebMvcLinkBuilder linkBuilder = linkTo(methodOn(this.getClass()).process(null, null, null, null, null, null, null, null, null));
     oai.setIdentify(this.oaiService.getIdentify(linkBuilder.toUri().toASCIIString()));
     oaiPmh.setOai(oai);
     oaiPmh.add(linkTo(this.getClass()).withSelfRel());
-    oaiPmh.add(Tool.link(linkTo(methodOn(this.getClass()).xsl(null, null)).toUriComponentsBuilder()).withRel(SolidifyConstants.XSL));
+    oaiPmh.add(Tool.link(linkTo(methodOn(this.getClass()).xsl(null)).toUriComponentsBuilder()).withRel(SolidifyConstants.XSL));
     oaiPmh.add(OAITool.oaiLink(linkBuilder.toUriComponentsBuilder(), OAIConstants.OAI_IDENTIFY).withRel(OAIConstants.OAI_IDENTIFY));
     oaiPmh.add(OAITool.oaiLink(linkBuilder.toUriComponentsBuilder(), OAIConstants.OAI_LIST_METADATA_FORMATS)
             .withRel(OAIConstants.OAI_LIST_METADATA_FORMATS));
@@ -201,19 +215,19 @@ public class OAIProviderController implements ControllerWithHateoasHome {
   }
 
   @GetMapping(SolidifyConstants.URL_SEP + OAIConstants.OAI_RESOURCE + SolidifyConstants.URL_SEP + SolidifyConstants.XSL)
-  public HttpEntity<String> xsl(HttpServletRequest request, @RequestParam(value = OAIConstants.OAI_VIEW, required = false) String smartView) {
+  public HttpEntity<String> xsl(@RequestParam(value = OAIConstants.OAI_VIEW, required = false) String smartView) {
     try {
-      String result = null;
+      String result;
       if (StringTool.isNullOrEmpty(smartView)) {
-        result = "";
-        result += "<xmlTransformation>";
+        StringBuilder xslt = new StringBuilder();
+        xslt.append("<xmlTransformation>");
         for (final Resource f : FileTool.scanClassPath("classpath:" + SolidifyConstants.XSL_HOME + "/*.xsl")) {
-          result += "<xslFile>" + f.getFilename() + "</xslFile>";
+          xslt.append("<xslFile>").append(f.getFilename()).append("</xslFile>");
         }
-        result += "</xmlTransformation>";
+        xslt.append("</xmlTransformation>");
+        result = xslt.toString();
       } else {
         final ClassPathResource xsl = new ClassPathResource(SolidifyConstants.XSL_HOME + SolidifyConstants.URL_SEP + smartView);
-
         result = FileTool.toString(xsl.getInputStream());
       }
       final HttpHeaders headers = new HttpHeaders();
@@ -223,7 +237,22 @@ public class OAIProviderController implements ControllerWithHateoasHome {
       log.error("XML Transformation error", e);
       return new ResponseEntity<>(HttpStatus.NOT_FOUND);
     }
+  }
 
+  @GetMapping(SolidifyConstants.URL_SEP + OAIConstants.OAI_RESOURCE + SolidifyConstants.URL_SEP + SolidifyConstants.SCHEMA)
+  public HttpEntity<String> xsd() {
+    try {
+      final ClassPathResource xsl = new ClassPathResource(
+              SolidifyConstants.SCHEMA_HOME + SolidifyConstants.URL_SEP + this.oaiService.getOaiRepositoryInfo().getRepositorySchema());
+      String result = FileTool.toString(xsl.getInputStream());
+
+      final HttpHeaders headers = new HttpHeaders();
+      headers.add(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_XML_VALUE);
+      return new ResponseEntity<>(result, headers, HttpStatus.OK);
+    } catch (final Exception e) {
+      log.error("XML Schema error", e);
+      return new ResponseEntity<>(HttpStatus.NOT_FOUND);
+    }
   }
 
   /**
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 335c92e2caabd3681f375028fbf848eabdaa4e39..354fb8bdc6072846aa422c6e12c85026eaa89c10 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
@@ -30,6 +30,7 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBElement;
 import javax.xml.bind.JAXBException;
@@ -99,6 +100,7 @@ public class OAIService {
   private final ObjectFactory oaiDcFactory = new ObjectFactory();
   // OAI Objects
   private final OAIRepositoryInfo oaiRepositoryInfo;
+
   private final OAIMetadataPrefixService oaiMetadataPrefixService;
   private final OAISetService oaiSetService;
   // OAI Service
@@ -138,6 +140,10 @@ public class OAIService {
     return oaiError;
   }
 
+  public OAIRepositoryInfo getOaiRepositoryInfo() {
+    return this.oaiRepositoryInfo;
+  }
+
   public IdentifyType getIdentify(String oaiUrl) {
     final IdentifyType oaiIdentify = new IdentifyType();
     oaiIdentify.setRepositoryName(this.oaiRepositoryInfo.getLongName());
@@ -170,6 +176,10 @@ public class OAIService {
     return oaiIdentify;
   }
 
+  public OAIMetadataPrefix getOAIMetadataPrefix(String metadataPrefix) {
+    return this.oaiMetadataPrefixService.findByPrefix(metadataPrefix);
+  }
+
   public GetRecordType getRecord(String baseUrl, String identifier, String metadataPrefix) throws JAXBException {
     // Check Parameters
     this.checkParameters(identifier, metadataPrefix);
@@ -268,10 +278,6 @@ public class OAIService {
             PageRequest.of(0, RestCollectionPage.MAX_SIZE_PAGE, Sort.by("prefix")));
   }
 
-  private OAIMetadataPrefix getMetadataPrefix(String metadataPrefix) {
-    return this.oaiMetadataPrefixService.findByPrefix(metadataPrefix);
-  }
-
   public ListRecordsType listRecords(String baseUrl, String metadataPrefix, String from, String until, String set, String token)
           throws JAXBException {
     // Check Parameters
@@ -329,13 +335,28 @@ public class OAIService {
     return setTypes;
   }
 
-  public String printOAIPMH(OAIPMHtype oai, String rootUrl) throws JAXBException {
+  public String printOAIPMH(OAIPMHtype oai, String rootUrl, Map<String, String> schemaLocationList) throws JAXBException {
     final Marshaller marshaller = this.metadataService.getMarshaller(this.jaxbContext);
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
     if (!StringTool.isNullOrEmpty(rootUrl)) {
       marshaller.setProperty("com.sun.xml.bind.xmlHeaders", "<?xml-stylesheet type='text/xsl' href='" + rootUrl + "'?>");
     }
-    marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, OAIConstants.OAI_PMH_NAMESPACE + " " + OAIConstants.OAI_PMH_SCHEMA);
+    // Build schema location string
+    StringBuilder schemaLocations = new StringBuilder();
+    schemaLocations
+            .append(OAIConstants.OAI_PMH_NAMESPACE)
+            .append(" ")
+            .append(OAIConstants.OAI_PMH_SCHEMA);
+    if (schemaLocationList != null && !schemaLocationList.isEmpty()) {
+      for (Map.Entry<String, String> schemaLocation : schemaLocationList.entrySet()) {
+        schemaLocations
+                .append(" ")
+                .append(schemaLocation.getKey())
+                .append(" ")
+                .append(schemaLocation.getValue());
+      }
+    }
+    marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, schemaLocations.toString());
     final JAXBElement<OAIPMHtype> root = this.getXML(oai);
     final ByteArrayOutputStream bos = new ByteArrayOutputStream();
     marshaller.marshal(root, bos);
@@ -446,7 +467,7 @@ public class OAIService {
   @SuppressWarnings("squid:S128")
   private Object getMetadata(String baseUrl, String metadataPrefix, OAIRecord oaiRecord) throws JAXBException {
     final String archiveUrl = this.getArchiveUrl();
-    final OAIMetadataPrefix oaiMetadataPrefix = this.getMetadataPrefix(metadataPrefix);
+    final OAIMetadataPrefix oaiMetadataPrefix = this.getOAIMetadataPrefix(metadataPrefix);
     if (oaiMetadataPrefix == null) {
       throw new OAIException(OAIPMHerrorcodeType.NO_METADATA_FORMATS, "Undefined metadata prefix " + metadataPrefix + " this record");
     }
diff --git a/solidify-oai-pmh/src/test/java/ch/unige/solidify/test/oai/OAIServiceTest.java b/solidify-oai-pmh/src/test/java/ch/unige/solidify/test/oai/OAIServiceTest.java
index d4f96b8f5428b4e1a3ca9cc6ea0a44224671642e..aad50c1ca23747b4f638d1930f829e8b0bcd3572 100644
--- a/solidify-oai-pmh/src/test/java/ch/unige/solidify/test/oai/OAIServiceTest.java
+++ b/solidify-oai-pmh/src/test/java/ch/unige/solidify/test/oai/OAIServiceTest.java
@@ -148,7 +148,7 @@ public abstract class OAIServiceTest {
   void identityTest() throws JAXBException, IOException {
     final OAIPMHtype oai = new OAIPMHtype();
     oai.setIdentify(this.oaiService.getIdentify(HOST_URL));
-    String result = this.oaiService.printOAIPMH(oai, null);
+    String result = this.oaiService.printOAIPMH(oai, null, null);
     this.checkResult(result, "oaiIdentity.xml");
   }
 
@@ -156,7 +156,7 @@ public abstract class OAIServiceTest {
   void listMetadataFormatsTest() throws JAXBException, IOException {
     final OAIPMHtype oai = new OAIPMHtype();
     oai.setListMetadataFormats(this.oaiService.listMetadataFormats(null));
-    String result = this.oaiService.printOAIPMH(oai, null);
+    String result = this.oaiService.printOAIPMH(oai, null, null);
     this.checkResult(result, "oaiListMetadataFormats.xml");
   }
 
@@ -166,7 +166,7 @@ public abstract class OAIServiceTest {
       try {
         final OAIPMHtype oai = new OAIPMHtype();
         oai.setListIdentifiers(this.oaiService.listIdentifiers(metadata, null, null, null, null));
-        String result = this.oaiService.printOAIPMH(oai, null);
+        String result = this.oaiService.printOAIPMH(oai, null, null);
         this.checkResult(result, "oaiIdentity-" + metadata + ".xml");
       } catch (final Exception e) {
         this.returnException(e);
@@ -185,7 +185,7 @@ public abstract class OAIServiceTest {
     try {
       oai.setGetRecord(this.oaiService.getRecord(HOST_URL, "xxx", OAIConstants.OAI_DC));
     } catch (OAIException e) {
-      String result = this.oaiService.printOAIPMH(oai, null);
+      String result = this.oaiService.printOAIPMH(oai, null, null);
       this.checkResult(result, "oaiGetRecordNotFound.xml");
     }
   }
@@ -197,7 +197,7 @@ public abstract class OAIServiceTest {
         try {
           final OAIPMHtype oai = new OAIPMHtype();
           oai.setGetRecord(this.oaiService.getRecord(HOST_URL, id, metadataPrefix));
-          String result = this.oaiService.printOAIPMH(oai, null);
+          String result = this.oaiService.printOAIPMH(oai, null, null);
           this.checkResult(result, "oaiGetRecord-" + metadataPrefix + "-" + id + ".xml");
         } catch (final Exception e) {
           this.returnException(e);
@@ -212,7 +212,7 @@ public abstract class OAIServiceTest {
       try {
         final OAIPMHtype oai = new OAIPMHtype();
         oai.setListRecords(this.oaiService.listRecords(HOST_URL, metadataPrefix, null, null, null, null));
-        String result = this.oaiService.printOAIPMH(oai, null);
+        String result = this.oaiService.printOAIPMH(oai, null, null);
         this.checkResult(result, "oaiListRecords-" + metadataPrefix + ".xml");
       } catch (final Exception e) {
         this.returnException(e);
@@ -224,7 +224,7 @@ public abstract class OAIServiceTest {
   void listSetsTest() throws JAXBException, IOException {
     final OAIPMHtype oai = new OAIPMHtype();
     oai.setListSets(this.oaiService.listSets(null));
-    String result = this.oaiService.printOAIPMH(oai, null);
+    String result = this.oaiService.printOAIPMH(oai, null, null);
     this.checkResult(result, "oaiListSets.xml");
   }
 
diff --git a/solidify-util/src/main/java/ch/unige/solidify/SolidifyConstants.java b/solidify-util/src/main/java/ch/unige/solidify/SolidifyConstants.java
index 26b57739642d4fa7283d25175b601c8fa66e5b1c..cc09e7e33b5687342e8396f689f8b09a4a39767d 100644
--- a/solidify-util/src/main/java/ch/unige/solidify/SolidifyConstants.java
+++ b/solidify-util/src/main/java/ch/unige/solidify/SolidifyConstants.java
@@ -92,6 +92,7 @@ public class SolidifyConstants {
 
   // XML
   public static final String SCHEMA_HOME = "schemas";
+  public static final String SCHEMA = "schema";
   public static final String XSL_HOME = "xslt";
   public static final String XSL = "xsl";