OGRErr OGRGMLLayer::CreateFeature( OGRFeature *poFeature ) { int bIsGML3Output = poDS->IsGML3Output(); VSILFILE *fp = poDS->GetOutputFP(); int bWriteSpaceIndentation = poDS->WriteSpaceIndentation(); if( !bWriter ) return OGRERR_FAILURE; if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); if (bIsGML3Output) poDS->PrintLine( fp, "<ogr:featureMember>" ); else poDS->PrintLine( fp, "<gml:featureMember>" ); if( poFeature->GetFID() == OGRNullFID ) poFeature->SetFID( iNextGMLId++ ); int nGMLIdIndex = -1; if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); if (bIsGML3Output) { nGMLIdIndex = poFeatureDefn->GetFieldIndex("gml_id"); if (nGMLIdIndex >= 0 && poFeature->IsFieldSet( nGMLIdIndex ) ) poDS->PrintLine( fp, "<ogr:%s gml:id=\"%s\">", poFeatureDefn->GetName(), poFeature->GetFieldAsString(nGMLIdIndex) ); else poDS->PrintLine( fp, "<ogr:%s gml:id=\"%s.%ld\">", poFeatureDefn->GetName(), poFeatureDefn->GetName(), poFeature->GetFID() ); } else poDS->PrintLine( fp, "<ogr:%s fid=\"F%ld\">", poFeatureDefn->GetName(), poFeature->GetFID() ); // Write out Geometry - for now it isn't indented properly. /* GML geometries don't like very much the concept of empty geometry */ OGRGeometry* poGeom = poFeature->GetGeometryRef(); if( poGeom != NULL && !poGeom->IsEmpty()) { char *pszGeometry; OGREnvelope sGeomBounds; poGeom->getEnvelope( &sGeomBounds ); poDS->GrowExtents( &sGeomBounds ); if (bIsGML3Output) { int bCoordSwap; if (poGeom->getSpatialReference() == NULL && poSRS != NULL) poGeom->assignSpatialReference(poSRS); char* pszSRSName = GML_GetSRSName(poGeom->getSpatialReference(), poDS->IsLongSRSRequired(), &bCoordSwap); char szLowerCorner[75], szUpperCorner[75]; if (bCoordSwap) { OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinY, sGeomBounds.MinX, 0, 2); OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxY, sGeomBounds.MaxX, 0, 2); } else { OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinX, sGeomBounds.MinY, 0, 2); OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxX, sGeomBounds.MaxY, 0, 2); } if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); poDS->PrintLine( fp, "<gml:boundedBy><gml:Envelope%s><gml:lowerCorner>%s</gml:lowerCorner><gml:upperCorner>%s</gml:upperCorner></gml:Envelope></gml:boundedBy>", pszSRSName, szLowerCorner, szUpperCorner); CPLFree(pszSRSName); } char** papszOptions = (bIsGML3Output) ? CSLAddString(NULL, "FORMAT=GML3") : NULL; if (bIsGML3Output && !poDS->IsLongSRSRequired()) papszOptions = CSLAddString(papszOptions, "GML3_LONGSRS=NO"); pszGeometry = poGeom->exportToGML(papszOptions); CSLDestroy(papszOptions); if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); poDS->PrintLine( fp, "<ogr:geometryProperty>%s</ogr:geometryProperty>", pszGeometry ); CPLFree( pszGeometry ); } // Write all "set" fields. for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ ) { OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( iField ); if( poFeature->IsFieldSet( iField ) && iField != nGMLIdIndex ) { const char *pszRaw = poFeature->GetFieldAsString( iField ); while( *pszRaw == ' ' ) pszRaw++; char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw ); if (poFieldDefn->GetType() == OFTReal) { /* Use point as decimal separator */ char* pszComma = strchr(pszEscaped, ','); if (pszComma) *pszComma = '.'; } if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); poDS->PrintLine( fp, "<ogr:%s>%s</ogr:%s>", poFieldDefn->GetNameRef(), pszEscaped, poFieldDefn->GetNameRef() ); CPLFree( pszEscaped ); } } if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); poDS->PrintLine( fp, "</ogr:%s>", poFeatureDefn->GetName() ); if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); if (bIsGML3Output) poDS->PrintLine( fp, "</ogr:featureMember>" ); else poDS->PrintLine( fp, "</gml:featureMember>" ); return OGRERR_NONE; }
OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature ) { int bIsGML3Output = poDS->IsGML3Output(); VSILFILE *fp = poDS->GetOutputFP(); int bWriteSpaceIndentation = poDS->WriteSpaceIndentation(); const char* pszPrefix = poDS->GetAppPrefix(); int bRemoveAppPrefix = poDS->RemoveAppPrefix(); if( !bWriter ) return OGRERR_FAILURE; poFeature->FillUnsetWithDefault(TRUE, NULL); if( !poFeature->Validate( OGR_F_VAL_ALL & ~OGR_F_VAL_GEOM_TYPE & ~OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT, TRUE ) ) return OGRERR_FAILURE; if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); if (bIsGML3Output) { if( bRemoveAppPrefix ) poDS->PrintLine( fp, "<featureMember>" ); else poDS->PrintLine( fp, "<%s:featureMember>", pszPrefix ); } else poDS->PrintLine( fp, "<gml:featureMember>" ); if( iNextGMLId == 0 ) { bSameSRS = true; for( int iGeomField = 1; iGeomField < poFeatureDefn->GetGeomFieldCount(); iGeomField++ ) { OGRGeomFieldDefn *poFieldDefn0 = poFeatureDefn->GetGeomFieldDefn(0); OGRGeomFieldDefn *poFieldDefn = poFeatureDefn->GetGeomFieldDefn(iGeomField); OGRSpatialReference* poSRS0 = poFieldDefn0->GetSpatialRef(); OGRSpatialReference* poSRS = poFieldDefn->GetSpatialRef(); if( poSRS0 != NULL && poSRS == NULL ) bSameSRS = false; else if( poSRS0 == NULL && poSRS != NULL ) bSameSRS = false; else if( poSRS0 != NULL && poSRS != NULL && poSRS0 != poSRS && !poSRS0->IsSame(poSRS) ) { bSameSRS = false; } } } if( poFeature->GetFID() == OGRNullFID ) poFeature->SetFID( iNextGMLId++ ); int nGMLIdIndex = -1; if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); VSIFPrintfL(fp, "<"); if( !bRemoveAppPrefix ) VSIFPrintfL(fp, "%s:", pszPrefix); if (bIsGML3Output) { nGMLIdIndex = poFeatureDefn->GetFieldIndex("gml_id"); if (nGMLIdIndex >= 0 && poFeature->IsFieldSet( nGMLIdIndex ) ) poDS->PrintLine( fp, "%s gml:id=\"%s\">", poFeatureDefn->GetName(), poFeature->GetFieldAsString(nGMLIdIndex) ); else poDS->PrintLine( fp, "%s gml:id=\"%s." CPL_FRMT_GIB "\">", poFeatureDefn->GetName(), poFeatureDefn->GetName(), poFeature->GetFID() ); } else { nGMLIdIndex = poFeatureDefn->GetFieldIndex("fid"); if (bUseOldFIDFormat) { poDS->PrintLine( fp, "%s fid=\"F" CPL_FRMT_GIB "\">", poFeatureDefn->GetName(), poFeature->GetFID() ); } else if (nGMLIdIndex >= 0 && poFeature->IsFieldSet( nGMLIdIndex ) ) { poDS->PrintLine( fp, "%s fid=\"%s\">", poFeatureDefn->GetName(), poFeature->GetFieldAsString(nGMLIdIndex) ); } else { poDS->PrintLine( fp, "%s fid=\"%s." CPL_FRMT_GIB "\">", poFeatureDefn->GetName(), poFeatureDefn->GetName(), poFeature->GetFID() ); } } for( int iGeomField = 0; iGeomField < poFeatureDefn->GetGeomFieldCount(); iGeomField++ ) { OGRGeomFieldDefn *poFieldDefn = poFeatureDefn->GetGeomFieldDefn(iGeomField); // Write out Geometry - for now it isn't indented properly. /* GML geometries don't like very much the concept of empty geometry */ OGRGeometry* poGeom = poFeature->GetGeomFieldRef(iGeomField); if( poGeom != NULL && !poGeom->IsEmpty()) { char *pszGeometry; OGREnvelope3D sGeomBounds; int nCoordDimension = poGeom->getCoordinateDimension(); poGeom->getEnvelope( &sGeomBounds ); if( bSameSRS ) poDS->GrowExtents( &sGeomBounds, nCoordDimension ); if (poGeom->getSpatialReference() == NULL && poFieldDefn->GetSpatialRef() != NULL) poGeom->assignSpatialReference(poFieldDefn->GetSpatialRef()); if (bIsGML3Output && poDS->WriteFeatureBoundedBy()) { bool bCoordSwap; char* pszSRSName = GML_GetSRSName(poGeom->getSpatialReference(), poDS->IsLongSRSRequired(), &bCoordSwap); char szLowerCorner[75], szUpperCorner[75]; if (bCoordSwap) { OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinY, sGeomBounds.MinX, sGeomBounds.MinZ, nCoordDimension); OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxY, sGeomBounds.MaxX, sGeomBounds.MaxZ, nCoordDimension); } else { OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinX, sGeomBounds.MinY, sGeomBounds.MinZ, nCoordDimension); OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxX, sGeomBounds.MaxY, sGeomBounds.MaxZ, nCoordDimension); } if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); poDS->PrintLine( fp, "<gml:boundedBy><gml:Envelope%s%s><gml:lowerCorner>%s</gml:lowerCorner><gml:upperCorner>%s</gml:upperCorner></gml:Envelope></gml:boundedBy>", (nCoordDimension == 3) ? " srsDimension=\"3\"" : "",pszSRSName, szLowerCorner, szUpperCorner); CPLFree(pszSRSName); } char** papszOptions = (bIsGML3Output) ? CSLAddString(NULL, "FORMAT=GML3") : NULL; if (bIsGML3Output && !poDS->IsLongSRSRequired()) papszOptions = CSLAddString(papszOptions, "GML3_LONGSRS=NO"); const char* pszSRSDimensionLoc = poDS->GetSRSDimensionLoc(); if( pszSRSDimensionLoc != NULL ) papszOptions = CSLSetNameValue(papszOptions, "SRSDIMENSION_LOC", pszSRSDimensionLoc); if (poDS->IsGML32Output()) { if( poFeatureDefn->GetGeomFieldCount() > 1 ) papszOptions = CSLAddString(papszOptions, CPLSPrintf("GMLID=%s.%s." CPL_FRMT_GIB, poFeatureDefn->GetName(), poFieldDefn->GetNameRef(), poFeature->GetFID())); else papszOptions = CSLAddString(papszOptions, CPLSPrintf("GMLID=%s.geom." CPL_FRMT_GIB, poFeatureDefn->GetName(), poFeature->GetFID())); } if( !bIsGML3Output && OGR_GT_IsNonLinear(poGeom->getGeometryType()) ) { OGRGeometry* poGeomTmp = OGRGeometryFactory::forceTo( poGeom->clone(),OGR_GT_GetLinear(poGeom->getGeometryType())); pszGeometry = poGeomTmp->exportToGML(papszOptions); delete poGeomTmp; } else pszGeometry = poGeom->exportToGML(papszOptions); CSLDestroy(papszOptions); if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); if( bRemoveAppPrefix ) poDS->PrintLine( fp, "<%s>%s</%s>", poFieldDefn->GetNameRef(), pszGeometry, poFieldDefn->GetNameRef() ); else poDS->PrintLine( fp, "<%s:%s>%s</%s:%s>", pszPrefix, poFieldDefn->GetNameRef(), pszGeometry, pszPrefix, poFieldDefn->GetNameRef() ); CPLFree( pszGeometry ); } } // Write all "set" fields. for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ ) { OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( iField ); if( poFeature->IsFieldSet( iField ) && iField != nGMLIdIndex ) { OGRFieldType eType = poFieldDefn->GetType(); if (eType == OFTStringList ) { char ** papszIter = poFeature->GetFieldAsStringList( iField ); while( papszIter != NULL && *papszIter != NULL ) { char *pszEscaped = OGRGetXML_UTF8_EscapedString( *papszIter ); GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix, bRemoveAppPrefix, poFieldDefn, pszEscaped); CPLFree( pszEscaped ); papszIter ++; } } else if (eType == OFTIntegerList ) { int nCount = 0; const int* panVals = poFeature->GetFieldAsIntegerList( iField, &nCount ); if( poFieldDefn->GetSubType() == OFSTBoolean ) { for(int i = 0; i < nCount; i++) { /* 0 and 1 are OK, but the canonical representation is false and true */ GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix, bRemoveAppPrefix, poFieldDefn, panVals[i] ? "true" : "false"); } } else { for(int i = 0; i < nCount; i++) { GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix, bRemoveAppPrefix, poFieldDefn, CPLSPrintf("%d", panVals[i])); } } } else if (eType == OFTInteger64List ) { int nCount = 0; const GIntBig* panVals = poFeature->GetFieldAsInteger64List( iField, &nCount ); if( poFieldDefn->GetSubType() == OFSTBoolean ) { for(int i = 0; i < nCount; i++) { /* 0 and 1 are OK, but the canonical representation is false and true */ GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix, bRemoveAppPrefix, poFieldDefn, panVals[i] ? "true" : "false"); } } else { for(int i = 0; i < nCount; i++) { GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix, bRemoveAppPrefix, poFieldDefn, CPLSPrintf(CPL_FRMT_GIB, panVals[i])); } } } else if (eType == OFTRealList ) { int nCount = 0; const double* padfVals = poFeature->GetFieldAsDoubleList( iField, &nCount ); for(int i = 0; i < nCount; i++) { char szBuffer[80]; CPLsnprintf( szBuffer, sizeof(szBuffer), "%.15g", padfVals[i]); GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix, bRemoveAppPrefix, poFieldDefn, szBuffer); } } else if ((eType == OFTInteger || eType == OFTInteger64) && poFieldDefn->GetSubType() == OFSTBoolean ) { /* 0 and 1 are OK, but the canonical representation is false and true */ GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix, bRemoveAppPrefix, poFieldDefn, (poFeature->GetFieldAsInteger(iField)) ? "true" : "false"); } else { const char *pszRaw = poFeature->GetFieldAsString( iField ); char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw ); GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix, bRemoveAppPrefix, poFieldDefn, pszEscaped); CPLFree( pszEscaped ); } } } if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); if( bRemoveAppPrefix ) poDS->PrintLine( fp, "</%s>", poFeatureDefn->GetName() ); else poDS->PrintLine( fp, "</%s:%s>", pszPrefix, poFeatureDefn->GetName() ); if (bWriteSpaceIndentation) VSIFPrintfL(fp, " "); if (bIsGML3Output) { if( bRemoveAppPrefix ) poDS->PrintLine( fp, "</featureMember>" ); else poDS->PrintLine( fp, "</%s:featureMember>", pszPrefix ); } else poDS->PrintLine( fp, "</gml:featureMember>" ); return OGRERR_NONE; }