diff --git a/Modules/Core/Metadata/include/otbXMLMetadataSupplier.h b/Modules/Core/Metadata/include/otbXMLMetadataSupplier.h
index 67747df4b675bd1fca04e3fc8d2a5d28e286c818..c2d5f51ffa5f3b06e25bfbd63f1d511f41fa4d8e 100644
--- a/Modules/Core/Metadata/include/otbXMLMetadataSupplier.h
+++ b/Modules/Core/Metadata/include/otbXMLMetadataSupplier.h
@@ -21,7 +21,8 @@
 #ifndef otbXMLMetadataSupplier_h
 #define otbXMLMetadataSupplier_h
 
-#include <gdal_mdreader.h>
+#include "cpl_minixml.h"
+#include "cpl_string.h"
 
 #include "OTBMetadataExport.h"
 #include "otbMetadataSupplierInterface.h"
@@ -38,8 +39,7 @@ namespace otb
  * \ingroup OTBMetadata
  */
 class OTBMetadata_EXPORT XMLMetadataSupplier
-  : public MetadataSupplierInterface,
-	public GDALMDReaderBase
+  : public MetadataSupplierInterface
 {
 public:
   XMLMetadataSupplier(const std::string &);
@@ -52,18 +52,18 @@ public:
   std::string GetResourceFile() const override;
 
   /**
-  * @brief Determine whether the input parameter correspond to the particular
-  *        provider of remote sensing data completely
-  * @return True if all needed sources files found
+  * @brief ReadXMLToList Transform xml to list of NULL terminated name=value
+  *        strings
+  * @param psNode A xml node to process
+  * @param papszList A list to fill with name=value strings
+  * @param pszName A name of parent node. For root xml node should be empty.
+  *        If name is not empty, the sibling nodes will not proceed
+  * @return An input list filled with values
+  *
+  * This method originates from a work by GDAL in the class GDALMDReaderBase.
   */
-  bool HasRequiredFiles() const override;
-
-  /**
-  * @brief Get metadata file names. The caller become owner of returned list
-  *        and have to free it via CSLDestroy.
-  * @return A file name list
-  */
-  char** GetMetadataFiles() const override;
+  virtual char** ReadXMLToList(CPLXMLNode* psNode, char** papszList,
+                               const char* pszName = "");
 
 private:
   /** List of resource files */
diff --git a/Modules/Core/Metadata/src/otbXMLMetadataSupplier.cxx b/Modules/Core/Metadata/src/otbXMLMetadataSupplier.cxx
index 2c0a5aa5d35be2412ddc991eb0af5ce4b321c478..6a5d099cfe954a7c3152c04d1714d7e78d1efaa6 100644
--- a/Modules/Core/Metadata/src/otbXMLMetadataSupplier.cxx
+++ b/Modules/Core/Metadata/src/otbXMLMetadataSupplier.cxx
@@ -23,7 +23,7 @@
 namespace otb
 {
 XMLMetadataSupplier::XMLMetadataSupplier(const std::string & fileName)
-  : GDALMDReaderBase(nullptr, nullptr), m_FileName(fileName)
+  : m_FileName(fileName)
 {
   CPLXMLNode* psNode = CPLParseXMLFile(m_FileName.c_str());
   if(psNode != nullptr)
@@ -50,15 +50,110 @@ std::string XMLMetadataSupplier::GetResourceFile() const
   return m_FileName;
 }
 
-bool XMLMetadataSupplier::HasRequiredFiles() const
+// This method originates from a work by GDAL in the class GDALMDReaderBase.
+char** XMLMetadataSupplier::ReadXMLToList(CPLXMLNode* psNode, char** papszList,
+                                          const char* pszName)
 {
-  return false; // TODO
-}
+  if(nullptr == psNode)
+    return papszList;
 
-char** XMLMetadataSupplier::GetMetadataFiles() const
-{
-  char ** todo;
-  return todo; // TODO
+  if (psNode->eType == CXT_Text)
+  {
+    papszList = CSLAddNameValue(papszList, pszName, psNode->pszValue);
+  }
+
+  if (psNode->eType == CXT_Element)
+  {
+    int nAddIndex = 0;
+    bool bReset = false;
+    for(CPLXMLNode* psChildNode = psNode->psChild; nullptr != psChildNode;
+        psChildNode = psChildNode->psNext)
+    {
+      if (psChildNode->eType == CXT_Element)
+      {
+        // check name duplicates
+        if(nullptr != psChildNode->psNext)
+        {
+          if(bReset)
+          {
+            bReset = false;
+            nAddIndex = 0;
+          }
+
+          if(EQUAL(psChildNode->pszValue, psChildNode->psNext->pszValue))
+          {
+            nAddIndex++;
+          }
+          else
+          { // the name changed
+            if(nAddIndex > 0)
+            {
+              bReset = true;
+              nAddIndex++;
+            }
+          }
+        }
+        else
+        {
+          if(bReset)
+          {
+            bReset = false;
+            nAddIndex = 0;
+          }
+          if(nAddIndex > 0)
+          {
+            nAddIndex++;
+          }
+        }
+        char szName[512];
+        if(nAddIndex > 0)
+        {
+          CPLsnprintf( szName, 511, "%s_%d", psChildNode->pszValue,
+                       nAddIndex);
+        }
+        else
+        {
+          CPLStrlcpy(szName, psChildNode->pszValue, 511);
+        }
+        char szNameNew[512];
+        if(CPLStrnlen( pszName, 511 ) > 0) //if no prefix just set name to node name
+        {
+          CPLsnprintf( szNameNew, 511, "%s.%s", pszName, szName );
+        }
+        else
+        {
+          CPLsnprintf( szNameNew, 511, "%s.%s", psNode->pszValue, szName );
+        }
+        papszList = ReadXMLToList(psChildNode, papszList, szNameNew);
+      }
+      else if( psChildNode->eType == CXT_Attribute )
+      {
+        papszList = CSLAddNameValue(papszList,
+                                    CPLSPrintf("%s.%s", pszName, psChildNode->pszValue),
+                                    psChildNode->psChild->pszValue);
+      }
+      else
+      {
+        // Text nodes should always have name
+        if(EQUAL(pszName, ""))
+        {
+          papszList = ReadXMLToList(psChildNode, papszList, psNode->pszValue);
+        }
+        else
+        {
+          papszList = ReadXMLToList(psChildNode, papszList, pszName);
+        }
+      }
+    }
+  }
+
+  // proceed next only on top level
+  if(nullptr != psNode->psNext && EQUAL(pszName, ""))
+  {
+    papszList = ReadXMLToList(psNode->psNext, papszList, pszName);
+  }
+
+  return papszList;
 }