CPLErr GDALPamRasterBand::SetDefaultHistogram( double dfMin, double dfMax, int nBuckets, int *panHistogram) { CPLXMLNode *psNode; PamInitialize(); if( psPam == NULL ) return GDALRasterBand::SetDefaultHistogram( dfMin, dfMax, nBuckets, panHistogram ); /* -------------------------------------------------------------------- */ /* Do we have a matching histogram we should replace? */ /* -------------------------------------------------------------------- */ psNode = PamFindMatchingHistogram( psPam->psSavedHistograms, dfMin, dfMax, nBuckets, TRUE, TRUE ); if( psNode != NULL ) { /* blow this one away */ CPLRemoveXMLChild( psPam->psSavedHistograms, psNode ); CPLDestroyXMLNode( psNode ); } /* -------------------------------------------------------------------- */ /* Translate into a histogram XML tree. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psHistItem; psHistItem = PamHistogramToXMLTree( dfMin, dfMax, nBuckets, panHistogram, TRUE, FALSE ); if( psHistItem == NULL ) return CE_Failure; /* -------------------------------------------------------------------- */ /* Insert our new default histogram at the front of the */ /* histogram list so that it will be the default histogram. */ /* -------------------------------------------------------------------- */ psPam->poParentDS->MarkPamDirty(); if( psPam->psSavedHistograms == NULL ) psPam->psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element, "Histograms" ); psHistItem->psNext = psPam->psSavedHistograms->psChild; psPam->psSavedHistograms->psChild = psHistItem; return CE_None; }
CPLErr VRTRasterBand::SetDefaultHistogram( double dfMin, double dfMax, int nBuckets, GUIntBig *panHistogram) { CPLXMLNode *psNode; /* -------------------------------------------------------------------- */ /* Do we have a matching histogram we should replace? */ /* -------------------------------------------------------------------- */ psNode = PamFindMatchingHistogram( psSavedHistograms, dfMin, dfMax, nBuckets, TRUE, TRUE ); if( psNode != NULL ) { /* blow this one away */ CPLRemoveXMLChild( psSavedHistograms, psNode ); CPLDestroyXMLNode( psNode ); } /* -------------------------------------------------------------------- */ /* Translate into a histogram XML tree. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psHistItem; psHistItem = PamHistogramToXMLTree( dfMin, dfMax, nBuckets, panHistogram, TRUE, FALSE ); if( psHistItem == NULL ) return CE_Failure; /* -------------------------------------------------------------------- */ /* Insert our new default histogram at the front of the */ /* histogram list so that it will be the default histogram. */ /* -------------------------------------------------------------------- */ ((VRTDataset *) poDS)->SetNeedsFlush(); if( psSavedHistograms == NULL ) psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element, "Histograms" ); psHistItem->psNext = psSavedHistograms->psChild; psSavedHistograms->psChild = psHistItem; return CE_None; }
static void RemoveIDs( CPLXMLNode * psRoot ) { if( psRoot == NULL ) return; CPLXMLNode *psChild = psRoot->psChild; // check for id attribute while( psChild != NULL && !( psChild->eType == CXT_Attribute && EQUAL(psChild->pszValue, "gml:id"))) psChild = psChild->psNext; CPLRemoveXMLChild( psRoot, psChild ); CPLDestroyXMLNode( psChild ); // search the child elements of psRoot for( psChild = psRoot->psChild; psChild != NULL; psChild = psChild->psNext) if( psChild->eType == CXT_Element ) RemoveIDs( psChild ); }
static int TrimTree( CPLXMLNode * psRoot ) { if( psRoot == NULL ) return FALSE; CPLXMLNode *psChild = psRoot->psChild; // check for id attribute while( psChild != NULL && !( psChild->eType == CXT_Attribute && EQUAL(psChild->pszValue, "gml:id"))) psChild = psChild->psNext; if( psChild != NULL ) return TRUE; // search the child elements of psRoot int bReturn = FALSE, bRemove; for( psChild = psRoot->psChild; psChild != NULL;) { CPLXMLNode* psNextChild = psChild->psNext; if( psChild->eType == CXT_Element ) { bRemove = TrimTree( psChild ); if( bRemove ) { bReturn = bRemove; } else { //remove this child CPLRemoveXMLChild( psRoot, psChild ); CPLDestroyXMLNode( psChild ); } } psChild = psNextChild; } return bReturn; }
static CPLErr Resolve( CPLXMLNode * psNode, CPLXMLNode *** ppapsRoot, char *** ppapszResourceHREF, char ** papszSkip, const int bStrict ) { //for each sibling CPLXMLNode *psSibling = NULL; CPLXMLNode *psResource = NULL; CPLXMLNode *psTarget = NULL; CPLErr eReturn = CE_None, eReturned; for( psSibling = psNode; psSibling != NULL; psSibling = psSibling->psNext ) { if( psSibling->eType != CXT_Element ) continue; CPLXMLNode *psChild = psSibling->psChild; while( psChild != NULL && !( psChild->eType == CXT_Attribute && EQUAL( psChild->pszValue, "xlink:href" ) ) ) psChild = psChild->psNext; //if a child has a "xlink:href" attribute if( psChild != NULL && psChild->psChild != NULL ) { if( CSLFindString( papszSkip, psSibling->pszValue ) >= 0 ) {//Skipping a specified element eReturn = CE_Warning; continue; } static int i = 0; if( i-- == 0 ) {//a way to track progress i = 256; CPLDebug( "GML", "Resolving xlinks... (currently %s)", psChild->psChild->pszValue ); } char **papszTokens; papszTokens = CSLTokenizeString2( psChild->psChild->pszValue, "#", CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES ); if( CSLCount( papszTokens ) != 2 || strlen(papszTokens[1]) <= 0 ) { CPLError( bStrict ? CE_Failure : CE_Warning, CPLE_NotSupported, "Error parsing the href %s.%s", psChild->psChild->pszValue, bStrict ? "" : " Skipping..." ); CSLDestroy( papszTokens ); if( bStrict ) return CE_Failure; eReturn = CE_Warning; continue; } //look for the resource with that URL psResource = FindTreeByURL( ppapsRoot, ppapszResourceHREF, papszTokens[0] ); if( psResource == NULL ) { CSLDestroy( papszTokens ); if( bStrict ) return CE_Failure; eReturn = CE_Warning; continue; } //look for the element with the ID psTarget = FindElementByID( psResource, papszTokens[1] ); if( psTarget != NULL ) { //remove the xlink:href attribute CPLRemoveXMLChild( psSibling, psChild ); CPLDestroyXMLNode( psChild ); //make a copy of psTarget CPLXMLNode *psCopy = CPLCreateXMLNode( NULL, CXT_Element, psTarget->pszValue ); psCopy->psChild = CPLCloneXMLTree( psTarget->psChild ); RemoveIDs( psCopy ); //correct empty URLs in URL#id pairs if( CPLStrnlen( papszTokens[0], 1 ) > 0 ) { CorrectURLs( psCopy, papszTokens[0] ); } CPLAddXMLChild( psSibling, psCopy ); CSLDestroy( papszTokens ); } else { //element not found CSLDestroy( papszTokens ); CPLError( bStrict ? CE_Failure : CE_Warning, CPLE_ObjectNull, "Couldn't find the element with id %s.", psChild->psChild->pszValue ); if( bStrict ) return CE_Failure; eReturn = CE_Warning; } } //Recurse with the first child eReturned=Resolve( psSibling->psChild, ppapsRoot, ppapszResourceHREF, papszSkip, bStrict ); if( eReturned == CE_Failure ) return CE_Failure; if( eReturned == CE_Warning ) eReturn = CE_Warning; } return eReturn; }
CPLErr GDALPamDataset::TrySaveXML() { CPLXMLNode *psTree; CPLErr eErr = CE_None; nPamFlags &= ~GPF_DIRTY; if( psPam == NULL || (nPamFlags & GPF_NOSAVE) ) return CE_None; /* -------------------------------------------------------------------- */ /* Make sure we know the filename we want to store in. */ /* -------------------------------------------------------------------- */ if( !BuildPamFilename() ) return CE_None; /* -------------------------------------------------------------------- */ /* Build the XML representation of the auxilary metadata. */ /* -------------------------------------------------------------------- */ CPLString osVRTPath = CPLGetPath(psPam->pszPamFilename); psTree = SerializeToXML( osVRTPath ); if( psTree == NULL ) return CE_None; /* -------------------------------------------------------------------- */ /* If we are working with a subdataset, we need to integrate */ /* the subdataset tree within the whole existing pam tree, */ /* after removing any old version of the same subdataset. */ /* -------------------------------------------------------------------- */ if( psPam->osSubdatasetName.size() != 0 ) { CPLXMLNode *psOldTree, *psSubTree; CPLErrorReset(); CPLPushErrorHandler( CPLQuietErrorHandler ); psOldTree = CPLParseXMLFile( psPam->pszPamFilename ); CPLPopErrorHandler(); if( psOldTree == NULL ) psOldTree = CPLCreateXMLNode( NULL, CXT_Element, "PAMDataset" ); for( psSubTree = psTree->psChild; psSubTree != NULL; psSubTree = psSubTree->psNext ) { if( psSubTree->eType != CXT_Element || !EQUAL(psSubTree->pszValue,"Subdataset") ) continue; if( !EQUAL(CPLGetXMLValue( psSubTree, "name", "" ), psPam->osSubdatasetName) ) continue; break; } if( psSubTree == NULL ) { psSubTree = CPLCreateXMLNode( psOldTree, CXT_Element, "Subdataset" ); CPLCreateXMLNode( CPLCreateXMLNode( psSubTree, CXT_Attribute, "name" ), CXT_Text, psPam->osSubdatasetName ); } CPLXMLNode *psOldPamDataset = CPLGetXMLNode( psSubTree, "PAMDataset"); if( psOldPamDataset != NULL ) { CPLRemoveXMLChild( psSubTree, psOldPamDataset ); CPLDestroyXMLNode( psOldPamDataset ); } CPLAddXMLChild( psSubTree, psTree ); psTree = psOldTree; } /* -------------------------------------------------------------------- */ /* Try saving the auxilary metadata. */ /* -------------------------------------------------------------------- */ const char *pszNewPam; int bSaved; CPLPushErrorHandler( CPLQuietErrorHandler ); bSaved = CPLSerializeXMLTreeToFile( psTree, psPam->pszPamFilename ); CPLPopErrorHandler(); /* -------------------------------------------------------------------- */ /* If it fails, check if we have a proxy directory for auxilary */ /* metadata to be stored in, and try to save there. */ /* -------------------------------------------------------------------- */ if( bSaved ) eErr = CE_None; else if( PamGetProxy(GetDescription()) == NULL && ((pszNewPam = PamAllocateProxy(GetDescription())) != NULL)) { CPLErrorReset(); CPLFree( psPam->pszPamFilename ); psPam->pszPamFilename = CPLStrdup(pszNewPam); eErr = TrySaveXML(); } else { CPLError( CE_Warning, CPLE_AppDefined, "Unable to save auxilary information in %s.", psPam->pszPamFilename ); eErr = CE_Warning; } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ CPLDestroyXMLNode( psTree ); return eErr; }