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

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

Generated by: LCOV version 1.7