LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/gml - ogrgmllayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 303 277 91.4 %
Date: 2011-12-18 Functions: 14 11 78.6 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrgmllayer.cpp 23371 2011-11-13 14:24:00Z rouault $
       3                 :  *
       4                 :  * Project:  OGR
       5                 :  * Purpose:  Implements OGRGMLLayer class.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "ogr_gml.h"
      31                 : #include "gmlutils.h"
      32                 : #include "cpl_conv.h"
      33                 : #include "cpl_port.h"
      34                 : #include "cpl_string.h"
      35                 : #include "ogr_p.h"
      36                 : #include "ogr_api.h"
      37                 : 
      38                 : CPL_CVSID("$Id: ogrgmllayer.cpp 23371 2011-11-13 14:24:00Z rouault $");
      39                 : 
      40                 : /************************************************************************/
      41                 : /*                           OGRGMLLayer()                              */
      42                 : /************************************************************************/
      43                 : 
      44              98 : OGRGMLLayer::OGRGMLLayer( const char * pszName,
      45                 :                           OGRSpatialReference *poSRSIn, int bWriterIn,
      46                 :                           OGRwkbGeometryType eReqType,
      47              98 :                           OGRGMLDataSource *poDSIn )
      48                 : 
      49                 : {
      50              98 :     if( poSRSIn == NULL )
      51              72 :         poSRS = NULL;
      52                 :     else
      53              26 :         poSRS = poSRSIn->Clone();
      54                 :     
      55              98 :     iNextGMLId = 0;
      56              98 :     nTotalGMLCount = -1;
      57              98 :     bInvalidFIDFound = FALSE;
      58              98 :     pszFIDPrefix = NULL;
      59                 :         
      60              98 :     poDS = poDSIn;
      61                 : 
      62              98 :     if ( EQUALN(pszName, "ogr:", 4) )
      63               0 :       poFeatureDefn = new OGRFeatureDefn( pszName+4 );
      64                 :     else
      65              98 :       poFeatureDefn = new OGRFeatureDefn( pszName );
      66              98 :     poFeatureDefn->Reference();
      67              98 :     poFeatureDefn->SetGeomType( eReqType );
      68                 : 
      69              98 :     bWriter = bWriterIn;
      70                 : 
      71                 : /* -------------------------------------------------------------------- */
      72                 : /*      Reader's should get the corresponding GMLFeatureClass and       */
      73                 : /*      cache it.                                                       */
      74                 : /* -------------------------------------------------------------------- */
      75              98 :     if( !bWriter )
      76              89 :         poFClass = poDS->GetReader()->GetClass( pszName );
      77                 :     else
      78               9 :         poFClass = NULL;
      79                 : 
      80              98 :     hCacheSRS = GML_BuildOGRGeometryFromList_CreateCache();
      81                 : 
      82                 :     /* Compatibility option. Not advertized, because hopefully won't be needed */
      83                 :     /* Just put here in provision... */
      84              98 :     bUseOldFIDFormat = CSLTestBoolean(CPLGetConfigOption("GML_USE_OLD_FID_FORMAT", "FALSE"));
      85              98 : }
      86                 : 
      87                 : /************************************************************************/
      88                 : /*                           ~OGRGMLLayer()                           */
      89                 : /************************************************************************/
      90                 : 
      91              98 : OGRGMLLayer::~OGRGMLLayer()
      92                 : 
      93                 : {
      94              98 :     CPLFree(pszFIDPrefix);
      95                 : 
      96              98 :     if( poFeatureDefn )
      97              98 :         poFeatureDefn->Release();
      98                 : 
      99              98 :     if( poSRS != NULL )
     100              26 :         poSRS->Release();
     101                 : 
     102              98 :     GML_BuildOGRGeometryFromList_DestroyCache(hCacheSRS);
     103              98 : }
     104                 : 
     105                 : /************************************************************************/
     106                 : /*                            ResetReading()                            */
     107                 : /************************************************************************/
     108                 : 
     109             156 : void OGRGMLLayer::ResetReading()
     110                 : 
     111                 : {
     112             156 :     if (bWriter)
     113               0 :         return;
     114                 : 
     115             156 :     if (poDS->GetReadMode() == INTERLEAVED_LAYERS ||
     116                 :         poDS->GetReadMode() == SEQUENTIAL_LAYERS)
     117                 :     {
     118                 :         /* Does the last stored feature belong to our layer ? If so, no */
     119                 :         /* need to reset the reader */
     120              12 :         if (iNextGMLId == 0 && poDS->PeekStoredGMLFeature() != NULL &&
     121                 :             poDS->PeekStoredGMLFeature()->GetClass() == poFClass)
     122               0 :             return;
     123                 : 
     124              12 :         delete poDS->PeekStoredGMLFeature();
     125              12 :         poDS->SetStoredGMLFeature(NULL);
     126                 :     }
     127                 : 
     128             156 :     iNextGMLId = 0;
     129             156 :     poDS->GetReader()->ResetReading();
     130             156 :     CPLDebug("GML", "ResetReading()");
     131             156 :     if (poDS->GetLayerCount() > 1 && poDS->GetReadMode() == STANDARD)
     132               3 :         poDS->GetReader()->SetFilteredClassName(poFClass->GetName());
     133                 : }
     134                 : 
     135                 : /************************************************************************/
     136                 : /*                           GetNextFeature()                           */
     137                 : /************************************************************************/
     138                 : 
     139             341 : OGRFeature *OGRGMLLayer::GetNextFeature()
     140                 : 
     141                 : {
     142             341 :     GMLFeature  *poGMLFeature = NULL;
     143             341 :     OGRGeometry *poGeom = NULL;
     144                 : 
     145             341 :     if (bWriter)
     146                 :     {
     147                 :         CPLError(CE_Failure, CPLE_NotSupported,
     148               0 :                  "Cannot read features when writing a GML file");
     149               0 :         return NULL;
     150                 :     }
     151                 : 
     152             341 :     if( poDS->GetLastReadLayer() != this )
     153                 :     {
     154              67 :         if( poDS->GetReadMode() != INTERLEAVED_LAYERS )
     155              58 :             ResetReading();
     156              67 :         poDS->SetLastReadLayer(this);
     157                 :     }
     158                 : 
     159                 : /* ==================================================================== */
     160                 : /*      Loop till we find and translate a feature meeting all our       */
     161                 : /*      requirements.                                                   */
     162                 : /* ==================================================================== */
     163             195 :     while( TRUE )
     164                 :     {
     165                 : /* -------------------------------------------------------------------- */
     166                 : /*      Cleanup last feature, and get a new raw gml feature.            */
     167                 : /* -------------------------------------------------------------------- */
     168             536 :         if( poGMLFeature != NULL )
     169             195 :             delete poGMLFeature;
     170                 : 
     171             536 :         if( poGeom != NULL )
     172                 :         {
     173              17 :             delete poGeom;
     174              17 :             poGeom = NULL;
     175                 :         }
     176                 : 
     177             536 :         poGMLFeature = poDS->PeekStoredGMLFeature();
     178             536 :         if (poGMLFeature != NULL)
     179               3 :             poDS->SetStoredGMLFeature(NULL);
     180                 :         else
     181                 :         {
     182             533 :             poGMLFeature = poDS->GetReader()->NextFeature();
     183             533 :             if( poGMLFeature == NULL )
     184              41 :                 return NULL;
     185                 : 
     186                 :             // We count reading low level GML features as a feature read for
     187                 :             // work checking purposes, though at least we didn't necessary
     188                 :             // have to turn it into an OGRFeature.
     189             492 :             m_nFeaturesRead++;
     190                 :         }
     191                 : 
     192                 : /* -------------------------------------------------------------------- */
     193                 : /*      Is it of the proper feature class?                              */
     194                 : /* -------------------------------------------------------------------- */
     195                 : 
     196             495 :         if( poGMLFeature->GetClass() != poFClass )
     197                 :         {
     198             182 :             if( poDS->GetReadMode() == INTERLEAVED_LAYERS ||
     199                 :                 (poDS->GetReadMode() == SEQUENTIAL_LAYERS && iNextGMLId != 0) )
     200                 :             {
     201               4 :                 CPLAssert(poDS->PeekStoredGMLFeature() == NULL);
     202               4 :                 poDS->SetStoredGMLFeature(poGMLFeature);
     203               4 :                 return NULL;
     204                 :             }
     205                 :             else
     206             178 :                 continue;
     207                 :         }
     208                 : 
     209                 : /* -------------------------------------------------------------------- */
     210                 : /*      Extract the fid:                                                */
     211                 : /*      -Assumes the fids are non-negative integers with an optional    */
     212                 : /*       prefix                                                         */
     213                 : /*      -If a prefix differs from the prefix of the first feature from  */
     214                 : /*       the poDS then the fids from the poDS are ignored and are       */
     215                 : /*       assigned serially thereafter                                   */
     216                 : /* -------------------------------------------------------------------- */
     217             313 :         int nFID = -1;
     218             313 :         const char * pszGML_FID = poGMLFeature->GetFID();
     219             313 :         if( bInvalidFIDFound )
     220                 :         {
     221              64 :             nFID = iNextGMLId++;
     222                 :         }
     223             249 :         else if( pszGML_FID == NULL )
     224                 :         {
     225              24 :             bInvalidFIDFound = TRUE;
     226              24 :             nFID = iNextGMLId++;
     227                 :         }
     228             225 :         else if( iNextGMLId == 0 )
     229                 :         {
     230              63 :             int i = strlen( pszGML_FID )-1, j = 0;
     231             388 :             while( i >= 0 && pszGML_FID[i] >= '0'
     232             153 :                           && pszGML_FID[i] <= '9' && j<8)
     233             109 :                 i--, j++;
     234                 :             /* i points the last character of the fid */
     235              63 :             if( i >= 0 && j < 8 && pszFIDPrefix == NULL)
     236                 :             {
     237              31 :                 pszFIDPrefix = (char *) CPLMalloc(i+2);
     238              31 :                 pszFIDPrefix[i+1] = '\0';
     239              31 :                 strncpy(pszFIDPrefix, pszGML_FID, i+1);
     240                 :             }
     241                 :             /* pszFIDPrefix now contains the prefix or NULL if no prefix is found */
     242              63 :             if( j < 8 && sscanf(pszGML_FID+i+1, "%d", &nFID)==1)
     243                 :             {
     244              61 :                 if( iNextGMLId <= nFID )
     245              61 :                     iNextGMLId = nFID + 1;
     246                 :             }
     247                 :             else
     248                 :             {
     249               2 :                 bInvalidFIDFound = TRUE;
     250               2 :                 nFID = iNextGMLId++;
     251                 :             }
     252                 :         }
     253             162 :         else if( iNextGMLId != 0 )
     254                 :         {
     255             162 :             const char* pszFIDPrefix_notnull = pszFIDPrefix;
     256             162 :             if (pszFIDPrefix_notnull == NULL) pszFIDPrefix_notnull = "";
     257             162 :             int nLenPrefix = strlen(pszFIDPrefix_notnull);
     258                 : 
     259             162 :             if(  strncmp(pszGML_FID, pszFIDPrefix_notnull, nLenPrefix) == 0 &&
     260                 :                  strlen(pszGML_FID+nLenPrefix) <= 9 &&
     261                 :                  sscanf(pszGML_FID+nLenPrefix, "%d", &nFID) == 1 )
     262                 :             { /* fid with the prefix. Using its numerical part */
     263             160 :                 if( iNextGMLId < nFID )
     264              75 :                     iNextGMLId = nFID + 1;
     265                 :             }
     266                 :             else
     267                 :             { /* fid without the aforementioned prefix or a valid numerical part */
     268               2 :                 bInvalidFIDFound = TRUE;
     269               2 :                 nFID = iNextGMLId++;
     270                 :             }
     271                 :         }
     272                 : 
     273                 : /* -------------------------------------------------------------------- */
     274                 : /*      Does it satisfy the spatial query, if there is one?             */
     275                 : /* -------------------------------------------------------------------- */
     276                 : 
     277             313 :         const CPLXMLNode* const * papsGeometry = poGMLFeature->GetGeometryList();
     278             313 :         if (papsGeometry[0] != NULL)
     279                 :         {
     280             307 :             const char* pszSRSName = poDS->GetGlobalSRSName();
     281                 :             poGeom = GML_BuildOGRGeometryFromList(papsGeometry, TRUE,
     282                 :                                                   poDS->GetInvertAxisOrderIfLatLong(),
     283                 :                                                   pszSRSName,
     284                 :                                                   poDS->GetConsiderEPSGAsURN(),
     285                 :                                                   poDS->GetSecondaryGeometryOption(),
     286             307 :                                                   hCacheSRS);
     287                 : 
     288                 :             /* Force single geometry to multigeometry if needed to match layer geometry type */
     289             307 :             if (poGeom != NULL)
     290                 :             {
     291             307 :                 OGRwkbGeometryType eType = poGeom->getGeometryType();
     292             307 :                 OGRwkbGeometryType eLayerType = GetGeomType();
     293             310 :                 if (eType == wkbPoint && eLayerType == wkbMultiPoint)
     294                 :                 {
     295               3 :                     OGRMultiPoint* poNewGeom = new OGRMultiPoint();
     296               3 :                     poNewGeom->addGeometryDirectly(poGeom);
     297               3 :                     poGeom = poNewGeom;
     298                 :                 }
     299             306 :                 else if (eType == wkbLineString && eLayerType == wkbMultiLineString)
     300                 :                 {
     301               2 :                     OGRMultiLineString* poNewGeom = new OGRMultiLineString();
     302               2 :                     poNewGeom->addGeometryDirectly(poGeom);
     303               2 :                     poGeom = poNewGeom;
     304                 :                 }
     305             302 :                 else if (eType == wkbPolygon && eLayerType == wkbMultiPolygon)
     306                 :                 {
     307               3 :                     OGRMultiPolygon* poNewGeom = new OGRMultiPolygon();
     308               3 :                     poNewGeom->addGeometryDirectly(poGeom);
     309               3 :                     poGeom = poNewGeom;
     310                 :                 }
     311                 :             }
     312                 : 
     313             307 :             if (poGeom != NULL && poSRS != NULL)
     314              16 :                 poGeom->assignSpatialReference(poSRS);
     315                 : 
     316                 :             // We assume the createFromGML() function would have already
     317                 :             // reported the error.
     318             307 :             if( poGeom == NULL )
     319                 :             {
     320               0 :                 delete poGMLFeature;
     321               0 :                 return NULL;
     322                 :             }
     323                 : 
     324             307 :             if( m_poFilterGeom != NULL && !FilterGeometry( poGeom ) )
     325              10 :                 continue;
     326                 :         }
     327                 : 
     328                 :         
     329                 : /* -------------------------------------------------------------------- */
     330                 : /*      Convert the whole feature into an OGRFeature.                   */
     331                 : /* -------------------------------------------------------------------- */
     332                 :         int iField;
     333             303 :         int iDstField = 0;
     334             303 :         OGRFeature *poOGRFeature = new OGRFeature( GetLayerDefn() );
     335                 : 
     336             303 :         poOGRFeature->SetFID( nFID );
     337             303 :         if (poDS->ExposeId())
     338                 :         {
     339             296 :             if (pszGML_FID)
     340             216 :                 poOGRFeature->SetField( iDstField, pszGML_FID );
     341             296 :             iDstField ++;
     342                 :         }
     343                 : 
     344             303 :         int nPropertyCount = poFClass->GetPropertyCount();
     345            1144 :         for( iField = 0; iField < nPropertyCount; iField++, iDstField ++ )
     346                 :         {
     347             841 :             const GMLProperty *psGMLProperty = poGMLFeature->GetProperty( iField );
     348             841 :             if( psGMLProperty == NULL || psGMLProperty->nSubProperties == 0 )
     349              14 :                 continue;
     350                 : 
     351             827 :             switch( poFClass->GetProperty(iField)->GetType()  )
     352                 :             {
     353                 :               case GMLPT_Real:
     354                 :               {
     355              97 :                   poOGRFeature->SetField( iDstField, CPLAtof(psGMLProperty->papszSubProperties[0]) );
     356                 :               }
     357              97 :               break;
     358                 : 
     359                 :               case GMLPT_IntegerList:
     360                 :               {
     361               3 :                   int nCount = psGMLProperty->nSubProperties;
     362               3 :                   int *panIntList = (int *) CPLMalloc(sizeof(int) * nCount );
     363                 :                   int i;
     364                 : 
     365               9 :                   for( i = 0; i < nCount; i++ )
     366               6 :                       panIntList[i] = atoi(psGMLProperty->papszSubProperties[i]);
     367                 : 
     368               3 :                   poOGRFeature->SetField( iDstField, nCount, panIntList );
     369               3 :                   CPLFree( panIntList );
     370                 :               }
     371               3 :               break;
     372                 : 
     373                 :               case GMLPT_RealList:
     374                 :               {
     375               3 :                   int nCount = psGMLProperty->nSubProperties;
     376               3 :                   double *padfList = (double *)CPLMalloc(sizeof(double)*nCount);
     377                 :                   int i;
     378                 : 
     379               9 :                   for( i = 0; i < nCount; i++ )
     380               6 :                       padfList[i] = CPLAtof(psGMLProperty->papszSubProperties[i]);
     381                 : 
     382               3 :                   poOGRFeature->SetField( iDstField, nCount, padfList );
     383               3 :                   CPLFree( padfList );
     384                 :               }
     385               3 :               break;
     386                 : 
     387                 :               case GMLPT_StringList:
     388                 :               {
     389               5 :                   poOGRFeature->SetField( iDstField, psGMLProperty->papszSubProperties );
     390                 :               }
     391               5 :               break;
     392                 : 
     393                 :               default:
     394             719 :                 poOGRFeature->SetField( iDstField, psGMLProperty->papszSubProperties[0] );
     395                 :                 break;
     396                 :             }
     397                 :         }
     398                 : 
     399                 : /* -------------------------------------------------------------------- */
     400                 : /*      Test against the attribute query.                               */
     401                 : /* -------------------------------------------------------------------- */
     402             303 :         if( m_poAttrQuery != NULL
     403                 :             && !m_poAttrQuery->Evaluate( poOGRFeature ) )
     404                 :         {
     405               7 :             delete poOGRFeature;
     406               7 :             continue;
     407                 :         }
     408                 : 
     409                 : /* -------------------------------------------------------------------- */
     410                 : /*      Wow, we got our desired feature. Return it.                     */
     411                 : /* -------------------------------------------------------------------- */
     412             296 :         delete poGMLFeature;
     413                 : 
     414             296 :         poOGRFeature->SetGeometryDirectly( poGeom );
     415                 : 
     416             296 :         return poOGRFeature;
     417                 :     }
     418                 : 
     419                 :     return NULL;
     420                 : }
     421                 : 
     422                 : /************************************************************************/
     423                 : /*                          GetFeatureCount()                           */
     424                 : /************************************************************************/
     425                 : 
     426              14 : int OGRGMLLayer::GetFeatureCount( int bForce )
     427                 : 
     428                 : {
     429              14 :     if( poFClass == NULL )
     430               0 :         return 0;
     431                 : 
     432              14 :     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
     433               4 :         return OGRLayer::GetFeatureCount( bForce );
     434                 :     else
     435                 :     {
     436                 :         /* If the schema is read from a .xsd file, we haven't read */
     437                 :         /* the feature count, so compute it now */
     438              10 :         int nFeatureCount = poFClass->GetFeatureCount();
     439              10 :         if (nFeatureCount < 0)
     440                 :         {
     441               2 :             nFeatureCount = OGRLayer::GetFeatureCount(bForce);
     442               2 :             poFClass->SetFeatureCount(nFeatureCount);
     443                 :         }
     444              10 :         return nFeatureCount;
     445                 :     }
     446                 : }
     447                 : 
     448                 : /************************************************************************/
     449                 : /*                             GetExtent()                              */
     450                 : /************************************************************************/
     451                 : 
     452               3 : OGRErr OGRGMLLayer::GetExtent(OGREnvelope *psExtent, int bForce )
     453                 : 
     454                 : {
     455                 :     double dfXMin, dfXMax, dfYMin, dfYMax;
     456                 : 
     457               3 :     if( poFClass != NULL && 
     458                 :         poFClass->GetExtents( &dfXMin, &dfXMax, &dfYMin, &dfYMax ) )
     459                 :     {
     460               1 :         psExtent->MinX = dfXMin;
     461               1 :         psExtent->MaxX = dfXMax;
     462               1 :         psExtent->MinY = dfYMin;
     463               1 :         psExtent->MaxY = dfYMax;
     464                 : 
     465               1 :         return OGRERR_NONE;
     466                 :     }
     467                 :     else 
     468               2 :         return OGRLayer::GetExtent( psExtent, bForce );
     469                 : }
     470                 : 
     471                 : /************************************************************************/
     472                 : /*                           CreateFeature()                            */
     473                 : /************************************************************************/
     474                 : 
     475              36 : OGRErr OGRGMLLayer::CreateFeature( OGRFeature *poFeature )
     476                 : 
     477                 : {
     478              36 :     int bIsGML3Output = poDS->IsGML3Output();
     479              36 :     VSILFILE *fp = poDS->GetOutputFP();
     480              36 :     int bWriteSpaceIndentation = poDS->WriteSpaceIndentation();
     481                 : 
     482              36 :     if( !bWriter )
     483               0 :         return OGRERR_FAILURE;
     484                 : 
     485              36 :     if (bWriteSpaceIndentation)
     486              36 :         VSIFPrintfL(fp, "  ");
     487              36 :     if (bIsGML3Output)
     488              16 :         poDS->PrintLine( fp, "<ogr:featureMember>" );
     489                 :     else
     490              20 :         poDS->PrintLine( fp, "<gml:featureMember>" );
     491                 : 
     492              36 :     if( poFeature->GetFID() == OGRNullFID )
     493              36 :         poFeature->SetFID( iNextGMLId++ );
     494                 : 
     495              36 :     int nGMLIdIndex = -1;
     496              36 :     if (bWriteSpaceIndentation)
     497              36 :         VSIFPrintfL(fp, "    ");
     498              36 :     if (bIsGML3Output)
     499                 :     {
     500              16 :         nGMLIdIndex = poFeatureDefn->GetFieldIndex("gml_id");
     501              16 :         if (nGMLIdIndex >= 0 && poFeature->IsFieldSet( nGMLIdIndex ) )
     502                 :             poDS->PrintLine( fp, "<ogr:%s gml:id=\"%s\">",
     503                 :                 poFeatureDefn->GetName(),
     504               0 :                 poFeature->GetFieldAsString(nGMLIdIndex) );
     505                 :         else
     506                 :             poDS->PrintLine( fp, "<ogr:%s gml:id=\"%s.%ld\">",
     507                 :                     poFeatureDefn->GetName(),
     508                 :                     poFeatureDefn->GetName(),
     509              16 :                     poFeature->GetFID() );
     510                 :     }
     511                 :     else
     512                 :     {
     513              20 :         nGMLIdIndex = poFeatureDefn->GetFieldIndex("fid");
     514              20 :         if (bUseOldFIDFormat)
     515                 :         {
     516                 :             poDS->PrintLine( fp, "<ogr:%s fid=\"F%ld\">",
     517                 :                                 poFeatureDefn->GetName(),
     518               0 :                                 poFeature->GetFID() );
     519                 :         }
     520              20 :         else if (nGMLIdIndex >= 0 && poFeature->IsFieldSet( nGMLIdIndex ) )
     521                 :         {
     522                 :             poDS->PrintLine( fp, "<ogr:%s fid=\"%s\">",
     523                 :                 poFeatureDefn->GetName(),
     524               0 :                 poFeature->GetFieldAsString(nGMLIdIndex) );
     525                 :         }
     526                 :         else
     527                 :         {
     528                 :             poDS->PrintLine( fp, "<ogr:%s fid=\"%s.%ld\">",
     529                 :                     poFeatureDefn->GetName(),
     530                 :                     poFeatureDefn->GetName(),
     531              20 :                     poFeature->GetFID() );
     532                 :         }
     533                 :     }
     534                 : 
     535                 :     // Write out Geometry - for now it isn't indented properly.
     536                 :     /* GML geometries don't like very much the concept of empty geometry */
     537              36 :     OGRGeometry* poGeom = poFeature->GetGeometryRef();
     538              36 :     if( poGeom != NULL && !poGeom->IsEmpty())
     539                 :     {
     540                 :         char    *pszGeometry;
     541              26 :         OGREnvelope3D sGeomBounds;
     542                 : 
     543              26 :         int nCoordDimension = poGeom->getCoordinateDimension();
     544                 : 
     545              26 :         poGeom->getEnvelope( &sGeomBounds );
     546              26 :         poDS->GrowExtents( &sGeomBounds, nCoordDimension );
     547                 : 
     548              26 :         if (bIsGML3Output)
     549                 :         {
     550                 :             int bCoordSwap;
     551                 : 
     552              16 :             if (poGeom->getSpatialReference() == NULL && poSRS != NULL)
     553               6 :                 poGeom->assignSpatialReference(poSRS);
     554                 : 
     555              16 :             char* pszSRSName = GML_GetSRSName(poGeom->getSpatialReference(), poDS->IsLongSRSRequired(), &bCoordSwap);
     556                 :             char szLowerCorner[75], szUpperCorner[75];
     557              16 :             if (bCoordSwap)
     558                 :             {
     559               6 :                 OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinY, sGeomBounds.MinX, sGeomBounds.MinZ, nCoordDimension);
     560               6 :                 OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxY, sGeomBounds.MaxX, sGeomBounds.MaxZ, nCoordDimension);
     561                 :             }
     562                 :             else
     563                 :             {
     564              10 :                 OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinX, sGeomBounds.MinY, sGeomBounds.MinZ, nCoordDimension);
     565              10 :                 OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxX, sGeomBounds.MaxY, sGeomBounds.MaxZ, nCoordDimension);
     566                 :             }
     567              16 :             if (bWriteSpaceIndentation)
     568              16 :                 VSIFPrintfL(fp, "      ");
     569                 :             poDS->PrintLine( fp, "<gml:boundedBy><gml:Envelope%s%s><gml:lowerCorner>%s</gml:lowerCorner><gml:upperCorner>%s</gml:upperCorner></gml:Envelope></gml:boundedBy>",
     570              16 :                              (nCoordDimension == 3) ? " srsDimension=\"3\"" : "",pszSRSName, szLowerCorner, szUpperCorner);
     571              16 :             CPLFree(pszSRSName);
     572                 :         }
     573                 : 
     574              26 :         char** papszOptions = (bIsGML3Output) ? CSLAddString(NULL, "FORMAT=GML3") : NULL;
     575              26 :         if (bIsGML3Output && !poDS->IsLongSRSRequired())
     576               0 :             papszOptions = CSLAddString(papszOptions, "GML3_LONGSRS=NO");
     577              26 :         if (poDS->IsGML32Output())
     578               2 :             papszOptions = CSLAddString(papszOptions, CPLSPrintf("GMLID=%s.geom.%ld", poFeatureDefn->GetName(), poFeature->GetFID()));
     579              26 :         pszGeometry = poGeom->exportToGML(papszOptions);
     580              26 :         CSLDestroy(papszOptions);
     581              26 :         if (bWriteSpaceIndentation)
     582              26 :             VSIFPrintfL(fp, "      ");
     583                 :         poDS->PrintLine( fp, "<ogr:geometryProperty>%s</ogr:geometryProperty>",
     584              26 :                     pszGeometry );
     585              26 :         CPLFree( pszGeometry );
     586                 :     }
     587                 : 
     588                 :     // Write all "set" fields. 
     589             123 :     for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     590                 :     {
     591                 :         
     592              87 :         OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( iField );
     593                 : 
     594              87 :         if( poFeature->IsFieldSet( iField ) && iField != nGMLIdIndex )
     595                 :         {
     596              84 :             const char *pszRaw = poFeature->GetFieldAsString( iField );
     597                 : 
     598             372 :             while( *pszRaw == ' ' )
     599             204 :                 pszRaw++;
     600                 : 
     601              84 :             char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw );
     602                 : 
     603              84 :             if (poFieldDefn->GetType() == OFTReal)
     604                 :             {
     605                 :                 /* Use point as decimal separator */
     606              42 :                 char* pszComma = strchr(pszEscaped, ',');
     607              42 :                 if (pszComma)
     608               0 :                     *pszComma = '.';
     609                 :             }
     610                 : 
     611              84 :             if (bWriteSpaceIndentation)
     612              84 :                 VSIFPrintfL(fp, "      ");
     613                 :             poDS->PrintLine( fp, "<ogr:%s>%s</ogr:%s>",
     614                 :                         poFieldDefn->GetNameRef(), pszEscaped, 
     615              84 :                         poFieldDefn->GetNameRef() );
     616              84 :             CPLFree( pszEscaped );
     617                 :         }
     618                 :     }
     619                 : 
     620              36 :     if (bWriteSpaceIndentation)
     621              36 :         VSIFPrintfL(fp, "    ");
     622              36 :     poDS->PrintLine( fp, "</ogr:%s>", poFeatureDefn->GetName() );
     623              36 :     if (bWriteSpaceIndentation)
     624              36 :         VSIFPrintfL(fp, "  ");
     625              36 :     if (bIsGML3Output)
     626              16 :         poDS->PrintLine( fp, "</ogr:featureMember>" );
     627                 :     else
     628              20 :         poDS->PrintLine( fp, "</gml:featureMember>" );
     629                 : 
     630              36 :     return OGRERR_NONE;
     631                 : }
     632                 : 
     633                 : /************************************************************************/
     634                 : /*                           TestCapability()                           */
     635                 : /************************************************************************/
     636                 : 
     637               9 : int OGRGMLLayer::TestCapability( const char * pszCap )
     638                 : 
     639                 : {
     640               9 :     if( EQUAL(pszCap,OLCSequentialWrite) )
     641               0 :         return bWriter;
     642                 : 
     643               9 :     else if( EQUAL(pszCap,OLCCreateField) )
     644               0 :         return bWriter && iNextGMLId == 0;
     645                 : 
     646               9 :     else if( EQUAL(pszCap,OLCFastGetExtent) )
     647                 :     {
     648                 :         double  dfXMin, dfXMax, dfYMin, dfYMax;
     649                 : 
     650               1 :         if( poFClass == NULL )
     651               0 :             return FALSE;
     652                 : 
     653               1 :         return poFClass->GetExtents( &dfXMin, &dfXMax, &dfYMin, &dfYMax );
     654                 :     }
     655                 : 
     656               8 :     else if( EQUAL(pszCap,OLCFastFeatureCount) )
     657                 :     {
     658               3 :         if( poFClass == NULL 
     659                 :             || m_poFilterGeom != NULL 
     660                 :             || m_poAttrQuery != NULL )
     661               0 :             return FALSE;
     662                 : 
     663               3 :         return poFClass->GetFeatureCount() != -1;
     664                 :     }
     665                 : 
     666               5 :     else if( EQUAL(pszCap,OLCStringsAsUTF8) )
     667               2 :         return TRUE;
     668                 : 
     669                 :     else 
     670               3 :         return FALSE;
     671                 : }
     672                 : 
     673                 : /************************************************************************/
     674                 : /*                            CreateField()                             */
     675                 : /************************************************************************/
     676                 : 
     677              18 : OGRErr OGRGMLLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
     678                 : 
     679                 : {
     680              18 :     if( !bWriter || iNextGMLId != 0 )
     681               0 :         return OGRERR_FAILURE;
     682                 : 
     683                 : /* -------------------------------------------------------------------- */
     684                 : /*      Enforce XML naming semantics on element name.                   */
     685                 : /* -------------------------------------------------------------------- */
     686              18 :     OGRFieldDefn oCleanCopy( poField );
     687              18 :     char *pszName = CPLStrdup( poField->GetNameRef() );
     688              18 :     CPLCleanXMLElementName( pszName );
     689                 :     
     690              18 :     if( strcmp(pszName,poField->GetNameRef()) != 0 )
     691                 :     {
     692               0 :         if( !bApproxOK )
     693                 :         {
     694               0 :             CPLFree( pszName );
     695                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     696                 :                       "Unable to create field with name '%s', it would not\n"
     697                 :                       "be valid as an XML element name.",
     698               0 :                       poField->GetNameRef() );
     699               0 :             return OGRERR_FAILURE;
     700                 :         }
     701                 : 
     702               0 :         oCleanCopy.SetName( pszName );
     703                 :         CPLError( CE_Warning, CPLE_AppDefined, 
     704                 :                   "Field name '%s' adjusted to '%s' to be a valid\n"
     705                 :                   "XML element name.",
     706               0 :                   poField->GetNameRef(), pszName );
     707                 :     }
     708                 : 
     709              18 :     CPLFree( pszName );
     710                 : 
     711                 :     
     712              18 :     poFeatureDefn->AddFieldDefn( &oCleanCopy );
     713                 : 
     714              18 :     return OGRERR_NONE;
     715                 : }
     716                 : 
     717                 : /************************************************************************/
     718                 : /*                           GetSpatialRef()                            */
     719                 : /************************************************************************/
     720                 : 
     721               6 : OGRSpatialReference *OGRGMLLayer::GetSpatialRef()
     722                 : 
     723                 : {
     724               6 :     return poSRS;
     725                 : }
     726                 : 
     727                 : /************************************************************************/
     728                 : /*                         GetGeometryColumn()                          */
     729                 : /************************************************************************/
     730                 : 
     731               3 : const char* OGRGMLLayer::GetGeometryColumn()
     732                 : {
     733               3 :     if( poFClass == NULL || poFClass->GetGeometryElement() == NULL )
     734               0 :         return "";
     735                 : 
     736               3 :     return poFClass->GetGeometryElement();
     737                 : }

Generated by: LCOV version 1.7