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; }