LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/gml - ogrgmllayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 306 281 91.8 %
Date: 2012-04-28 Functions: 14 11 78.6 %

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

Generated by: LCOV version 1.7