diff --git a/Modules/Core/Metadata/include/otbMetadataSupplierInterface.h b/Modules/Core/Metadata/include/otbMetadataSupplierInterface.h
index f5a289c01c0f366a8fdce09518cbc78cd71d783a..18d2f55f6d84c1a3bd7781a3aa9c6f5c605eec7b 100644
--- a/Modules/Core/Metadata/include/otbMetadataSupplierInterface.h
+++ b/Modules/Core/Metadata/include/otbMetadataSupplierInterface.h
@@ -74,68 +74,71 @@ public:
 
 
   /** Get the metadata value corresponding to a given path (meaning of this path
-   * depends on the specific implementation. Returns NULL when path is not found
+   * depends on the specific implementation. Returns empty string when path is not found,
+   * and hasValue is set to False.
    * If band >= 0, the metadata value is looked in the specified band*/
-  virtual const char * GetMetadataValue(const char * path, int band=-1) const = 0;
+  virtual const std::string GetMetadataValue(const std::string path, bool& hasValue, int band=-1) const = 0;
 
-  bool HasValue(const char * path, int band=-1);
+  bool HasValue(std::string path, int band=-1);
 
   // utility functions
-  template <typename T> T GetAs(const char *path, int band=-1) const
+  template <typename T> T GetAs(std::string path, int band=-1) const
+  {
+    bool hasValue;
+    std::string ret = GetMetadataValue(path, hasValue, band);
+    if (!hasValue)
     {
-    const char * ret = GetMetadataValue(path, band);
-    if (ret == nullptr)
-      {
       otbGenericExceptionMacro(MissingMetadataException,<<"Missing metadata '"<<path<<"'")
-      }
+    }
     try
-      {
+    {
       return boost::lexical_cast<T>(ret);
-      }
+    }
     catch (boost::bad_lexical_cast&)
-      {
+    {
       otbGenericExceptionMacro(MissingMetadataException,<<"Bad metadata value for '"<<path<<"', got: "<<ret)
-      }
     }
+  }
 
   /** Parse a metadata value to a std::vector,
    *  If size>=0, then the final std::vector size is checked and an exception
    *  is raised if it doesn't match the given size.*/
-  template < typename T> std::vector<T> GetAsVector(const char *path, const char sep=' ', int size=-1, int band=-1) const
+  template < typename T> std::vector<T> GetAsVector(std::string path, const char sep=' ', int size=-1, int band=-1) const
+  {
+    bool hasValue;
+    std::string ret = GetMetadataValue(path, hasValue, band);
+    if (!hasValue)
     {
-    const char * ret = GetMetadataValue(path, band);
-    if (ret == nullptr)
-      {
       otbGenericExceptionMacro(MissingMetadataException,<<"Missing metadata '"<<path<<"'")
-      }
+    }
     string_view value(ret);
     string_view filt_value = rstrip(lstrip(value,"[ "), "] ");
     std::vector<T> output;
     typedef part_range<splitter_on_delim> range_type;
     const range_type parts = split_on(filt_value, sep);
     for (auto const& part : parts)
-      {
+    {
       // TODO: check if we can use lexical_cast on a string_view
       std::string strPart = to<std::string>(part, "casting string_view to std::string");
       if (strPart.empty())
-        {
+      {
         continue;
-        }
+      }
       try
-        {
+      {
         output.push_back(boost::lexical_cast<T>(strPart));
-        }
+      }
       catch (boost::bad_lexical_cast&)
-        {
+      {
         otbGenericExceptionMacro(MissingMetadataException,<<"Bad metadata vector element in '"<<path<<"', got :"<<part)
-        }
       }
+    }
     if ((size >= 0) && (output.size() != (size_t)size))
-      {
+    {
       otbGenericExceptionMacro(MissingMetadataException,<<"Bad number of elements in vector '"<<path<<"', expected "<<size<< ", got "<<output.size())
-      }
-    return output;
     }
+    return output;
+  }
 
 };
 
diff --git a/Modules/Core/Metadata/include/otbXMLMetadataSupplier.h b/Modules/Core/Metadata/include/otbXMLMetadataSupplier.h
index 3783a124f8d4d7c9e44514b40284ba4e33eb86c8..225e14a4c92430581ccd797878a5bc442f7c89de 100644
--- a/Modules/Core/Metadata/include/otbXMLMetadataSupplier.h
+++ b/Modules/Core/Metadata/include/otbXMLMetadataSupplier.h
@@ -47,7 +47,7 @@ public:
   /** Get the metadata value corresponding to a given path
    * Returns NULL when path is not found
    * If band >= 0, the metadata value is looked in the specified band*/
-  const char * GetMetadataValue(const char * path, int band=1) const override;
+  const std::string GetMetadataValue(const std::string path, bool& hasValue, int band=1) const override;
 
   std::string GetResourceFile(std::string="") const override;
 
diff --git a/Modules/Core/Metadata/src/otbMetadataSupplierInterface.cxx b/Modules/Core/Metadata/src/otbMetadataSupplierInterface.cxx
index c276bb6096bddb6c3600514efa7b2a648ff74f67..4cbe8a51284e39aedcd530183afb5dfa4b836642 100644
--- a/Modules/Core/Metadata/src/otbMetadataSupplierInterface.cxx
+++ b/Modules/Core/Metadata/src/otbMetadataSupplierInterface.cxx
@@ -23,10 +23,11 @@
 namespace otb
 {
 
-bool MetadataSupplierInterface::HasValue(const char * path, int band)
+bool MetadataSupplierInterface::HasValue(const std::string path, int band)
 {
-  const char * ret = GetMetadataValue(path, band);
-  return ret;
+  bool hasValue;
+  const std::string ret = GetMetadataValue(path, hasValue, band);
+  return hasValue;
 }
 
 
diff --git a/Modules/Core/Metadata/src/otbXMLMetadataSupplier.cxx b/Modules/Core/Metadata/src/otbXMLMetadataSupplier.cxx
index d4406642c033c96c2c05bea2c17c507abaf4927c..ec1ca62c7947ffb09410e1107fefa69c35b190d3 100644
--- a/Modules/Core/Metadata/src/otbXMLMetadataSupplier.cxx
+++ b/Modules/Core/Metadata/src/otbXMLMetadataSupplier.cxx
@@ -41,9 +41,17 @@ XMLMetadataSupplier::XMLMetadataSupplier(const std::string & fileName)
   CPLDestroyXMLNode(psNode);
 }
 
-const char * XMLMetadataSupplier::GetMetadataValue(const char * path, int band) const
+const std::string XMLMetadataSupplier::GetMetadataValue(const std::string path, bool& hasValue, int band) const
 {
-  return CSLFetchNameValue(m_MetadataDic, path);
+  const char * ret = CSLFetchNameValue(m_MetadataDic, path);
+  if (ret)
+    hasValue = true;
+  else
+  {
+    hasValue = false;
+    ret = "";
+  }
+  return std::string(ret);
 }
 
 std::string XMLMetadataSupplier::GetResourceFile(std::string) const
diff --git a/Modules/IO/IOGDAL/include/otbGDALImageIO.h b/Modules/IO/IOGDAL/include/otbGDALImageIO.h
index 657bea76b239226a02094faaaadfaf0367326b08..22a493a05bac33e8a8d21d342a0b19a7d99b600c 100644
--- a/Modules/IO/IOGDAL/include/otbGDALImageIO.h
+++ b/Modules/IO/IOGDAL/include/otbGDALImageIO.h
@@ -210,7 +210,7 @@ public:
   std::vector<std::string> GetResourceFiles() const override;
 
   /** Get metadata item in GDALDataset, domain can specified as "domain/key" */
-  const char * GetMetadataValue(const char * path, int band = -1) const override;
+  const std::string GetMetadataValue(const std::string path, bool& hasValue, int band = -1) const override;
 
   /** Set metadata item in GDALDataset, domain can specified as prefix of the
    *  path, like "domain/key"*/
diff --git a/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx b/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx
index 0bbeae85eb2ce8847c7fe14bf7fe67f63b147687..f50a024c045280fd56a60dc6cb782a5371ac824a 100644
--- a/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx
+++ b/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx
@@ -1831,24 +1831,31 @@ std::vector<std::string> GDALImageIO::GetResourceFiles() const
   return result;
 }
 
-const char * GDALImageIO::GetMetadataValue(const char * path, int band) const
+const std::string GDALImageIO::GetMetadataValue(const std::string path, bool& hasValue, int band) const
 {
   // detect namespace if any
-  const char *slash = strchr(path,'/');
   std::string domain("");
-  const char *domain_c = nullptr;
   std::string key(path);
-  if (slash)
-    {
-    domain = std::string(path, (slash-path));
-    domain_c = domain.c_str();
-    key = std::string(slash+1);
-    }
+  std::size_t found = path.find_first_of("/");
+  if (found != std::string::npos)
+  {
+    domain = path.substr(0, found);
+    key = path.substr(found + 1);
+  }
+
+  const char* ret;
   if (band >= 0)
-    {
-    return m_Dataset->GetDataSet()->GetRasterBand(band+1)->GetMetadataItem(key.c_str(), domain_c);
-    }
-  return m_Dataset->GetDataSet()->GetMetadataItem(key.c_str(), domain_c);
+    ret = m_Dataset->GetDataSet()->GetRasterBand(band+1)->GetMetadataItem(key.c_str(), domain.c_str());
+  else
+    ret = m_Dataset->GetDataSet()->GetMetadataItem(key.c_str(), domain.c_str());
+  if (ret)
+    hasValue = true;
+  else
+  {
+    hasValue = false;
+    ret = "";
+  }
+  return std::string(ret);
 }
 
 void GDALImageIO::SetMetadataValue(const char * path, const char * value, int band)
@@ -1905,7 +1912,8 @@ void GDALImageIO::ImportMetadata()
   // Keys Starting with: MDGeomNames[MDGeom::SensorGeometry] + '.' should
   // be decoded by the (future) SensorModelFactory.
   // Use ImageMetadataBase::FromKeywordlist to ingest the metadata
-  if (std::string(GetMetadataValue("METADATATYPE")) != "OTB")
+  bool hasValue;
+  if (std::string(GetMetadataValue("METADATATYPE", hasValue)) != "OTB")
     return;
   ImageMetadataBase::Keywordlist kwl;
   GDALMetadataToKeywordlist(m_Dataset->GetDataSet()->GetMetadata(), kwl);