Forked from
Main Repositories / otb
2546 commits behind the upstream repository.
-
Julien Osman authoredJulien Osman authored
otbXMLMetadataSupplier.cxx 6.11 KiB
/*
* Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES)
*
* This file is part of Orfeo Toolbox
*
* https://www.orfeo-toolbox.org/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "otbXMLMetadataSupplier.h"
namespace otb
{
XMLMetadataSupplier::XMLMetadataSupplier(const std::string & fileName)
: m_FileName(fileName)
{
CPLXMLNode* psNode = CPLParseXMLFile(m_FileName.c_str());
if(psNode != nullptr)
m_MetadataDic = ReadXMLToList(psNode, m_MetadataDic);
else
{
otbLogMacro(Warning, <<"Unable to parse XML file " << fileName);
m_MetadataDic = nullptr;
}
CPLDestroyXMLNode(psNode);
}
std::string XMLMetadataSupplier::GetMetadataValue(const std::string path, bool& hasValue, int band) const
{
const char * ret = CSLFetchNameValue(m_MetadataDic, path.c_str());
if (ret)
hasValue = true;
else
{
hasValue = false;
ret = "";
}
return std::string(ret);
}
std::string XMLMetadataSupplier::GetFirstMetadataValue(const std::string path, bool& hasValue) const
{
// Search for the first joker
std::size_t found = path.find("_#");
// Looking for the keys corresponding to the part of the path before the first joker
char ** values = this->CSLFetchPartialNameValueMultiple(m_MetadataDic, path.substr(0, found).c_str());
// Position of the beginning of the path after the joker
std::size_t start = found + 2;
// While a joker is found
while(found != std::string::npos)
{
// Look for the next joker
found = path.find("_#", start);
// Look for the keys corresponding to the part of the path between the two jokers
char ** new_values = this->CSLFetchPartialNameValueMultiple(values, path.substr(start, found).c_str());
CSLDestroy(values);
values = CSLDuplicate(new_values);
CSLDestroy(new_values);
start = found + 2;
}
if ((values != nullptr) && (values[0] != nullptr))
{
hasValue = true;
std::string ret = values[0];
ret = ret.substr(ret.find('=') + 1);
CSLDestroy(values);
// Return the value part
return ret;
}
else
{
hasValue = false;
return "";
}
}
std::string XMLMetadataSupplier::GetResourceFile(std::string) const
{
return m_FileName;
}
// This method originates from a work by GDAL in the class GDALMDReaderBase.
char** XMLMetadataSupplier::ReadXMLToList(CPLXMLNode* psNode, char** papszList,
const char* pszName)
{
if(nullptr == psNode)
return papszList;
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;
}
char ** XMLMetadataSupplier::CSLFetchPartialNameValueMultiple(char** papszStrList, const char *pszName) const
{
if( papszStrList == nullptr || pszName == nullptr )
return nullptr;
char **papszValues = nullptr;
for( ; *papszStrList != nullptr ; ++papszStrList )
if( strstr(*papszStrList, pszName) )
papszValues = CSLAddString(papszValues, *papszStrList);
return papszValues;
}
int XMLMetadataSupplier::GetNbBands() const
{
return 0;
}
std::string XMLMetadataSupplier::PrintSelf()
{
std::ostringstream oss;
oss << "XMLMetadataSupplier: " << this->m_FileName << '\n';
for (char ** string = this->m_MetadataDic; *string != nullptr ; ++string)
oss << *string << '\n';
return oss.str();
}
} // end namespace otb