LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/gml - gmlreader.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 536 392 73.1 %
Date: 2011-12-18 Functions: 49 27 55.1 %

       1                 : /******************************************************************************
       2                 :  * $Id: gmlreader.cpp 23566 2011-12-13 20:51:04Z rouault $
       3                 :  *
       4                 :  * Project:  GML Reader
       5                 :  * Purpose:  Implementation of GMLReader class.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2002, Frank Warmerdam
      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 OR
      22                 :  * 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 "gmlreader.h"
      31                 : #include "cpl_error.h"
      32                 : #include "cpl_string.h"
      33                 : #include "gmlutils.h"
      34                 : #include "gmlreaderp.h"
      35                 : #include "cpl_conv.h"
      36                 : #include <map>
      37                 : 
      38                 : #define SUPPORT_GEOMETRY
      39                 : 
      40                 : #ifdef SUPPORT_GEOMETRY
      41                 : #  include "ogr_geometry.h"
      42                 : #endif
      43                 : 
      44                 : /************************************************************************/
      45                 : /*                            ~IGMLReader()                             */
      46                 : /************************************************************************/
      47                 : 
      48              72 : IGMLReader::~IGMLReader()
      49                 : 
      50                 : {
      51              72 : }
      52                 : 
      53                 : /************************************************************************/
      54                 : /* ==================================================================== */
      55                 : /*                  No XERCES or EXPAT Library                          */
      56                 : /* ==================================================================== */
      57                 : /************************************************************************/
      58                 : #if !defined(HAVE_XERCES) && !defined(HAVE_EXPAT)
      59                 : 
      60                 : /************************************************************************/
      61                 : /*                          CreateGMLReader()                           */
      62                 : /************************************************************************/
      63                 : 
      64                 : IGMLReader *CreateGMLReader(int bUseExpatParserPreferably,
      65                 :                             int bInvertAxisOrderIfLatLong,
      66                 :                             int bConsiderEPSGAsURN,
      67                 :                             int bGetSecondaryGeometryOption)
      68                 : 
      69                 : {
      70                 :     CPLError( CE_Failure, CPLE_AppDefined,
      71                 :               "Unable to create Xerces C++ or Expat based GML reader, Xerces or Expat support\n"
      72                 :               "not configured into GDAL/OGR." );
      73                 :     return NULL;
      74                 : }
      75                 : 
      76                 : /************************************************************************/
      77                 : /* ==================================================================== */
      78                 : /*                  With XERCES or EXPAT Library                        */
      79                 : /* ==================================================================== */
      80                 : /************************************************************************/
      81                 : #else /* defined(HAVE_XERCES) || defined(HAVE_EXPAT) */
      82                 : 
      83                 : /************************************************************************/
      84                 : /*                          CreateGMLReader()                           */
      85                 : /************************************************************************/
      86                 : 
      87              67 : IGMLReader *CreateGMLReader(int bUseExpatParserPreferably,
      88                 :                             int bInvertAxisOrderIfLatLong,
      89                 :                             int bConsiderEPSGAsURN,
      90                 :                             int bGetSecondaryGeometryOption)
      91                 : 
      92                 : {
      93                 :     return new GMLReader(bUseExpatParserPreferably,
      94                 :                          bInvertAxisOrderIfLatLong,
      95                 :                          bConsiderEPSGAsURN,
      96              67 :                          bGetSecondaryGeometryOption);
      97                 : }
      98                 : 
      99                 : #endif
     100                 : 
     101                 : int GMLReader::m_bXercesInitialized = FALSE;
     102                 : int GMLReader::m_nInstanceCount = 0;
     103                 : 
     104                 : /************************************************************************/
     105                 : /*                             GMLReader()                              */
     106                 : /************************************************************************/
     107                 : 
     108              67 : GMLReader::GMLReader(int bUseExpatParserPreferably,
     109                 :                      int bInvertAxisOrderIfLatLong,
     110                 :                      int bConsiderEPSGAsURN,
     111              67 :                      int bGetSecondaryGeometryOption)
     112                 : 
     113                 : {
     114                 : #ifndef HAVE_XERCES
     115                 :     bUseExpatReader = TRUE;
     116                 : #else
     117              67 :     bUseExpatReader = FALSE;
     118                 : #ifdef HAVE_EXPAT
     119              67 :     if(bUseExpatParserPreferably)
     120              67 :         bUseExpatReader = TRUE;
     121                 : #endif
     122                 : #endif
     123                 : 
     124                 : #if defined(HAVE_EXPAT) && defined(HAVE_XERCES)
     125              67 :     if (bUseExpatReader)
     126              67 :         CPLDebug("GML", "Using Expat reader");
     127                 :     else
     128               0 :         CPLDebug("GML", "Using Xerces reader");
     129                 : #endif
     130                 : 
     131              67 :     m_nInstanceCount++;
     132              67 :     m_nClassCount = 0;
     133              67 :     m_papoClass = NULL;
     134                 : 
     135              67 :     m_bClassListLocked = FALSE;
     136                 : 
     137              67 :     m_poGMLHandler = NULL;
     138                 : #ifdef HAVE_XERCES
     139              67 :     m_poSAXReader = NULL;
     140              67 :     m_poCompleteFeature = NULL;
     141              67 :     m_GMLInputSource = NULL;
     142              67 :     m_bEOF = FALSE;
     143                 : #endif
     144                 : #ifdef HAVE_EXPAT
     145              67 :     oParser = NULL;
     146              67 :     ppoFeatureTab = NULL;
     147              67 :     nFeatureTabIndex = 0;
     148              67 :     nFeatureTabLength = 0;
     149              67 :     nFeatureTabAlloc = 0;
     150              67 :     pabyBuf = NULL;
     151                 : #endif
     152              67 :     fpGML = NULL;
     153              67 :     m_bReadStarted = FALSE;
     154                 :     
     155              67 :     m_poState = NULL;
     156              67 :     m_poRecycledState = NULL;
     157                 : 
     158              67 :     m_pszFilename = NULL;
     159                 : 
     160              67 :     m_bStopParsing = FALSE;
     161                 : 
     162                 :     /* A bit experimental. Not publicly advertized. See commented doc in drv_gml.html */
     163              67 :     m_bFetchAllGeometries = CSLTestBoolean(CPLGetConfigOption("GML_FETCH_ALL_GEOMETRIES", "NO"));
     164                 : 
     165              67 :     m_bInvertAxisOrderIfLatLong = bInvertAxisOrderIfLatLong;
     166              67 :     m_bConsiderEPSGAsURN = bConsiderEPSGAsURN;
     167              67 :     m_bGetSecondaryGeometryOption = bGetSecondaryGeometryOption;
     168                 : 
     169              67 :     m_pszGlobalSRSName = NULL;
     170              67 :     m_bCanUseGlobalSRSName = FALSE;
     171                 : 
     172              67 :     m_pszFilteredClassName = NULL;
     173                 : 
     174              67 :     m_bSequentialLayers = -1;
     175              67 : }
     176                 : 
     177                 : /************************************************************************/
     178                 : /*                             ~GMLReader()                             */
     179                 : /************************************************************************/
     180                 : 
     181              67 : GMLReader::~GMLReader()
     182                 : 
     183                 : {
     184              67 :     ClearClasses();
     185                 : 
     186              67 :     CPLFree( m_pszFilename );
     187                 : 
     188              67 :     CleanupParser();
     189                 : 
     190              67 :     delete m_poRecycledState;
     191                 : 
     192              67 :     --m_nInstanceCount;
     193                 : #ifdef HAVE_XERCES
     194              67 :     if( m_nInstanceCount == 0 && m_bXercesInitialized )
     195                 :     {
     196               0 :         XMLPlatformUtils::Terminate();
     197               0 :         m_bXercesInitialized = FALSE;
     198                 :     }
     199                 : #endif
     200                 : #ifdef HAVE_EXPAT
     201              67 :     CPLFree(pabyBuf);
     202                 : #endif
     203                 : 
     204              67 :     if (fpGML)
     205              57 :         VSIFCloseL(fpGML);
     206              67 :     fpGML = NULL;
     207                 : 
     208              67 :     CPLFree(m_pszGlobalSRSName);
     209                 : 
     210              67 :     CPLFree(m_pszFilteredClassName);
     211              67 : }
     212                 : 
     213                 : /************************************************************************/
     214                 : /*                          SetSourceFile()                             */
     215                 : /************************************************************************/
     216                 : 
     217              69 : void GMLReader::SetSourceFile( const char *pszFilename )
     218                 : 
     219                 : {
     220              69 :     CPLFree( m_pszFilename );
     221              69 :     m_pszFilename = CPLStrdup( pszFilename );
     222              69 : }
     223                 : 
     224                 : /************************************************************************/
     225                 : /*                       GetSourceFileName()                           */
     226                 : /************************************************************************/
     227                 : 
     228               0 : const char* GMLReader::GetSourceFileName()
     229                 : 
     230                 : {
     231               0 :     return m_pszFilename;
     232                 : }
     233                 : 
     234                 : /************************************************************************/
     235                 : /*                            SetupParser()                             */
     236                 : /************************************************************************/
     237                 : 
     238             111 : int GMLReader::SetupParser()
     239                 : 
     240                 : {
     241             111 :     if (fpGML == NULL)
     242              58 :         fpGML = VSIFOpenL(m_pszFilename, "rt");
     243             111 :     if (fpGML != NULL)
     244             111 :         VSIFSeekL( fpGML, 0, SEEK_SET );
     245                 : 
     246             111 :     int bRet = -1;
     247                 : #ifdef HAVE_EXPAT
     248             111 :     if (bUseExpatReader)
     249             111 :         bRet = SetupParserExpat();
     250                 : #endif
     251                 : 
     252                 : #ifdef HAVE_XERCES
     253             111 :     if (!bUseExpatReader)
     254               0 :         bRet = SetupParserXerces();
     255                 : #endif
     256             111 :     if (bRet < 0)
     257                 :     {
     258               0 :         CPLError(CE_Failure, CPLE_AppDefined, "SetupParser(): shouldn't happen");
     259               0 :         return FALSE;
     260                 :     }
     261                 : 
     262             111 :     if (!bRet)
     263               0 :         return FALSE;
     264                 : 
     265             111 :     m_bReadStarted = FALSE;
     266                 : 
     267                 :     // Push an empty state.
     268             111 :     PushState( m_poRecycledState ? m_poRecycledState : new GMLReadState() );
     269             111 :     m_poRecycledState = NULL;
     270                 : 
     271             111 :     return TRUE;
     272                 : }
     273                 : 
     274                 : #ifdef HAVE_XERCES
     275                 : /************************************************************************/
     276                 : /*                        SetupParserXerces()                           */
     277                 : /************************************************************************/
     278                 : 
     279               0 : int GMLReader::SetupParserXerces()
     280                 : {
     281               0 :     if( !m_bXercesInitialized )
     282                 :     {
     283                 :         try
     284                 :         {
     285               0 :             XMLPlatformUtils::Initialize();
     286                 :         }
     287                 :         
     288               0 :         catch (const XMLException& toCatch)
     289                 :         {
     290                 :             CPLError( CE_Warning, CPLE_AppDefined,
     291                 :                       "Exception initializing Xerces based GML reader.\n%s", 
     292               0 :                       tr_strdup(toCatch.getMessage()) );
     293               0 :             return FALSE;
     294                 :         }
     295               0 :         m_bXercesInitialized = TRUE;
     296                 :     }
     297                 : 
     298                 :     // Cleanup any old parser.
     299               0 :     if( m_poSAXReader != NULL )
     300               0 :         CleanupParser();
     301                 : 
     302                 :     // Create and initialize parser.
     303               0 :     XMLCh* xmlUriValid = NULL;
     304               0 :     XMLCh* xmlUriNS = NULL;
     305                 : 
     306                 :     try{
     307               0 :         m_poSAXReader = XMLReaderFactory::createXMLReader();
     308                 :     
     309               0 :         GMLXercesHandler* poXercesHandler = new GMLXercesHandler( this );
     310               0 :         m_poGMLHandler = poXercesHandler;
     311                 : 
     312               0 :         m_poSAXReader->setContentHandler( poXercesHandler );
     313               0 :         m_poSAXReader->setErrorHandler( poXercesHandler );
     314               0 :         m_poSAXReader->setLexicalHandler( poXercesHandler );
     315               0 :         m_poSAXReader->setEntityResolver( poXercesHandler );
     316               0 :         m_poSAXReader->setDTDHandler( poXercesHandler );
     317                 : 
     318               0 :         xmlUriValid = XMLString::transcode("http://xml.org/sax/features/validation");
     319               0 :         xmlUriNS = XMLString::transcode("http://xml.org/sax/features/namespaces");
     320                 : 
     321                 : #if (OGR_GML_VALIDATION)
     322                 :         m_poSAXReader->setFeature( xmlUriValid, true);
     323                 :         m_poSAXReader->setFeature( xmlUriNS, true);
     324                 : 
     325                 :         m_poSAXReader->setFeature( XMLUni::fgSAX2CoreNameSpaces, true );
     326                 :         m_poSAXReader->setFeature( XMLUni::fgXercesSchema, true );
     327                 : 
     328                 : //    m_poSAXReader->setDoSchema(true);
     329                 : //    m_poSAXReader->setValidationSchemaFullChecking(true);
     330                 : #else
     331               0 :         m_poSAXReader->setFeature( XMLUni::fgSAX2CoreValidation, false);
     332                 : 
     333                 : #if XERCES_VERSION_MAJOR >= 3
     334               0 :         m_poSAXReader->setFeature( XMLUni::fgXercesSchema, false);
     335                 : #else
     336                 :         m_poSAXReader->setFeature( XMLUni::fgSAX2CoreNameSpaces, false);
     337                 : #endif
     338                 : 
     339                 : #endif
     340               0 :         XMLString::release( &xmlUriValid );
     341               0 :         XMLString::release( &xmlUriNS );
     342                 :     }
     343               0 :     catch (...)
     344                 :     {
     345               0 :         XMLString::release( &xmlUriValid );
     346               0 :         XMLString::release( &xmlUriNS );
     347                 : 
     348                 :         CPLError( CE_Warning, CPLE_AppDefined,
     349               0 :                   "Exception initializing Xerces based GML reader.\n" );
     350               0 :         return FALSE;
     351                 :     }
     352                 : 
     353               0 :     if (m_GMLInputSource == NULL && fpGML != NULL)
     354               0 :         m_GMLInputSource = new GMLInputSource(fpGML);
     355                 : 
     356               0 :     return TRUE;
     357                 : }
     358                 : #endif
     359                 : 
     360                 : /************************************************************************/
     361                 : /*                        SetupParserExpat()                            */
     362                 : /************************************************************************/
     363                 : 
     364                 : #ifdef HAVE_EXPAT
     365             111 : int GMLReader::SetupParserExpat()
     366                 : {
     367                 :     // Cleanup any old parser.
     368             111 :     if( oParser != NULL )
     369               1 :         CleanupParser();
     370                 : 
     371             111 :     oParser = OGRCreateExpatXMLParser();
     372             111 :     m_poGMLHandler = new GMLExpatHandler( this, oParser );
     373                 : 
     374             111 :     XML_SetElementHandler(oParser, GMLExpatHandler::startElementCbk, GMLExpatHandler::endElementCbk);
     375             111 :     XML_SetCharacterDataHandler(oParser, GMLExpatHandler::dataHandlerCbk);
     376             111 :     XML_SetUserData(oParser, m_poGMLHandler);
     377                 : 
     378             111 :     if (pabyBuf == NULL)
     379              57 :         pabyBuf = (char*)VSIMalloc(PARSER_BUF_SIZE);
     380             111 :     if (pabyBuf == NULL)
     381               0 :         return FALSE;
     382                 : 
     383             111 :     return TRUE;
     384                 : }
     385                 : #endif
     386                 : 
     387                 : /************************************************************************/
     388                 : /*                           CleanupParser()                            */
     389                 : /************************************************************************/
     390                 : 
     391             246 : void GMLReader::CleanupParser()
     392                 : 
     393                 : {
     394                 : #ifdef HAVE_XERCES
     395             246 :     if( !bUseExpatReader && m_poSAXReader == NULL )
     396               0 :         return;
     397                 : #endif
     398                 : 
     399                 : #ifdef HAVE_EXPAT
     400             246 :     if ( bUseExpatReader && oParser == NULL )
     401             135 :         return;
     402                 : #endif
     403                 : 
     404             334 :     while( m_poState )
     405             112 :         PopState();
     406                 : 
     407                 : #ifdef HAVE_XERCES
     408             111 :     delete m_poSAXReader;
     409             111 :     m_poSAXReader = NULL;
     410             111 :     delete m_GMLInputSource;
     411             111 :     m_GMLInputSource = NULL;
     412             111 :     delete m_poCompleteFeature;
     413             111 :     m_poCompleteFeature = NULL;
     414             111 :     m_bEOF = FALSE;
     415                 : #endif
     416                 : 
     417                 : #ifdef HAVE_EXPAT
     418             111 :     if (oParser)
     419             111 :         XML_ParserFree(oParser);
     420             111 :     oParser = NULL;
     421                 : 
     422                 :     int i;
     423             295 :     for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
     424             184 :         delete ppoFeatureTab[i];
     425             111 :     CPLFree(ppoFeatureTab);
     426             111 :     nFeatureTabIndex = 0;
     427             111 :     nFeatureTabLength = 0;
     428             111 :     nFeatureTabAlloc = 0;
     429             111 :     ppoFeatureTab = NULL;
     430                 : 
     431                 : #endif
     432                 : 
     433             111 :     delete m_poGMLHandler;
     434             111 :     m_poGMLHandler = NULL;
     435                 : 
     436             111 :     m_bReadStarted = FALSE;
     437                 : }
     438                 : 
     439                 : #ifdef HAVE_XERCES
     440                 : 
     441               0 : GMLBinInputStream::GMLBinInputStream(VSILFILE* fp)
     442                 : {
     443               0 :     this->fp = fp;
     444               0 :     emptyString = 0;
     445               0 : }
     446                 : 
     447               0 : GMLBinInputStream::~ GMLBinInputStream()
     448                 : {
     449               0 : }
     450                 : 
     451                 : #if XERCES_VERSION_MAJOR >= 3
     452               0 : XMLFilePos GMLBinInputStream::curPos() const
     453                 : {
     454               0 :     return (XMLFilePos)VSIFTellL(fp);
     455                 : }
     456                 : 
     457               0 : XMLSize_t GMLBinInputStream::readBytes(XMLByte* const toFill, const XMLSize_t maxToRead)
     458                 : {
     459               0 :     return (XMLSize_t)VSIFReadL(toFill, 1, maxToRead, fp);
     460                 : }
     461                 : 
     462               0 : const XMLCh* GMLBinInputStream::getContentType() const
     463                 : {
     464               0 :     return &emptyString;
     465                 : }
     466                 : #else
     467                 : unsigned int GMLBinInputStream::curPos() const
     468                 : {
     469                 :     return (unsigned int)VSIFTellL(fp);
     470                 : }
     471                 : 
     472                 : unsigned int GMLBinInputStream::readBytes(XMLByte* const toFill, const unsigned int maxToRead)
     473                 : {
     474                 :     return (unsigned int)VSIFReadL(toFill, 1, maxToRead, fp);
     475                 : }
     476                 : #endif
     477                 : 
     478               0 : GMLInputSource::GMLInputSource(VSILFILE* fp, MemoryManager* const manager) : InputSource(manager)
     479                 : {
     480               0 :     binInputStream = new GMLBinInputStream(fp);
     481               0 : }
     482                 : 
     483               0 : GMLInputSource::~GMLInputSource()
     484                 : {
     485               0 : }
     486                 : 
     487               0 : BinInputStream* GMLInputSource::makeStream() const
     488                 : {
     489               0 :     return binInputStream;
     490                 : }
     491                 : 
     492                 : #endif // HAVE_XERCES
     493                 : 
     494                 : /************************************************************************/
     495                 : /*                        NextFeatureXerces()                           */
     496                 : /************************************************************************/
     497                 : 
     498                 : #ifdef HAVE_XERCES
     499               0 : GMLFeature *GMLReader::NextFeatureXerces()
     500                 : 
     501                 : {
     502               0 :     GMLFeature *poReturn = NULL;
     503                 : 
     504               0 :     if (m_bEOF)
     505               0 :         return NULL;
     506                 : 
     507                 :     try
     508                 :     {
     509               0 :         if( !m_bReadStarted )
     510                 :         {
     511               0 :             if( m_poSAXReader == NULL )
     512               0 :                 SetupParser();
     513                 : 
     514               0 :             m_bReadStarted = TRUE;
     515                 : 
     516               0 :             if (m_GMLInputSource == NULL)
     517               0 :                 return NULL;
     518                 : 
     519               0 :             if( !m_poSAXReader->parseFirst( *m_GMLInputSource, m_oToFill ) )
     520               0 :                 return NULL;
     521                 :         }
     522                 : 
     523               0 :         while( m_poCompleteFeature == NULL 
     524                 :                && !m_bStopParsing
     525               0 :                && m_poSAXReader->parseNext( m_oToFill ) ) {}
     526                 : 
     527               0 :         if (m_poCompleteFeature == NULL)
     528               0 :             m_bEOF = TRUE;
     529                 : 
     530               0 :         poReturn = m_poCompleteFeature;
     531               0 :         m_poCompleteFeature = NULL;
     532                 : 
     533                 :     }
     534               0 :     catch (const XMLException& toCatch)
     535                 :     {
     536               0 :         char *pszErrorMessage = tr_strdup( toCatch.getMessage() );
     537                 :         CPLDebug( "GML", 
     538                 :                   "Error during NextFeature()! Message:\n%s", 
     539               0 :                   pszErrorMessage );
     540               0 :         CPLFree(pszErrorMessage);
     541               0 :         m_bStopParsing = TRUE;
     542                 :     }
     543               0 :     catch (const SAXException& toCatch)
     544                 :     {
     545               0 :         char *pszErrorMessage = tr_strdup( toCatch.getMessage() );
     546               0 :         CPLError(CE_Failure, CPLE_AppDefined, "%s", pszErrorMessage);
     547               0 :         CPLFree(pszErrorMessage);
     548               0 :         m_bStopParsing = TRUE;
     549                 :     }
     550                 : 
     551               0 :     return poReturn;
     552                 : }
     553                 : #endif
     554                 : 
     555                 : #ifdef HAVE_EXPAT
     556             840 : GMLFeature *GMLReader::NextFeatureExpat()
     557                 : 
     558                 : {
     559             840 :     if (!m_bReadStarted)
     560                 :     {
     561             111 :         if (oParser == NULL)
     562              88 :             SetupParser();
     563                 : 
     564             111 :         m_bReadStarted = TRUE;
     565                 :     }
     566                 : 
     567             840 :     if (fpGML == NULL || m_bStopParsing)
     568               0 :         return NULL;
     569                 : 
     570             840 :     if (nFeatureTabIndex < nFeatureTabLength)
     571                 :     {
     572             665 :         return ppoFeatureTab[nFeatureTabIndex++];
     573                 :     }
     574                 : 
     575             175 :     if (VSIFEofL(fpGML))
     576              63 :         return NULL;
     577                 : 
     578             112 :     nFeatureTabLength = 0;
     579             112 :     nFeatureTabIndex = 0;
     580                 : 
     581                 :     int nDone;
     582             112 :     do
     583                 :     {
     584                 :         /* Reset counter that is used to detect billion laugh attacks */
     585             112 :         ((GMLExpatHandler*)m_poGMLHandler)->ResetDataHandlerCounter();
     586                 : 
     587                 :         unsigned int nLen =
     588             112 :                 (unsigned int)VSIFReadL( pabyBuf, 1, PARSER_BUF_SIZE, fpGML );
     589             112 :         nDone = VSIFEofL(fpGML);
     590             112 :         if (XML_Parse(oParser, pabyBuf, nLen, nDone) == XML_STATUS_ERROR)
     591                 :         {
     592                 :             CPLError(CE_Failure, CPLE_AppDefined,
     593                 :                      "XML parsing of GML file failed : %s "
     594                 :                      "at line %d, column %d",
     595                 :                      XML_ErrorString(XML_GetErrorCode(oParser)),
     596                 :                      (int)XML_GetCurrentLineNumber(oParser),
     597               0 :                      (int)XML_GetCurrentColumnNumber(oParser));
     598               0 :             m_bStopParsing = TRUE;
     599                 :         }
     600             112 :         if (!m_bStopParsing)
     601             112 :             m_bStopParsing = ((GMLExpatHandler*)m_poGMLHandler)->HasStoppedParsing();
     602                 : 
     603                 :     } while (!nDone && !m_bStopParsing && nFeatureTabLength == 0);
     604                 : 
     605             112 :     return (nFeatureTabLength) ? ppoFeatureTab[nFeatureTabIndex++] : NULL;
     606                 : }
     607                 : #endif
     608                 : 
     609             840 : GMLFeature *GMLReader::NextFeature()
     610                 : {
     611                 : #ifdef HAVE_EXPAT
     612             840 :     if (bUseExpatReader)
     613             840 :         return NextFeatureExpat();
     614                 : #endif
     615                 : 
     616                 : #ifdef HAVE_XERCES
     617               0 :     if (!bUseExpatReader)
     618               0 :         return NextFeatureXerces();
     619                 : #endif
     620                 : 
     621               0 :     CPLError(CE_Failure, CPLE_AppDefined, "NextFeature(): Should not happen");
     622               0 :     return NULL;
     623                 : }
     624                 : 
     625                 : /************************************************************************/
     626                 : /*                            PushFeature()                             */
     627                 : /*                                                                      */
     628                 : /*      Create a feature based on the named element.  If the            */
     629                 : /*      corresponding feature class doesn't exist yet, then create      */
     630                 : /*      it now.  A new GMLReadState will be created for the feature,    */
     631                 : /*      and it will be placed within that state.  The state is          */
     632                 : /*      pushed onto the readstate stack.                                */
     633                 : /************************************************************************/
     634                 : 
     635             960 : void GMLReader::PushFeature( const char *pszElement, 
     636                 :                              const char *pszFID,
     637                 :                              int nClassIndex )
     638                 : 
     639                 : {
     640                 :     int iClass;
     641                 : 
     642             960 :     if( nClassIndex != INT_MAX )
     643                 :     {
     644             482 :         iClass = nClassIndex;
     645                 :     }
     646                 :     else
     647                 :     {
     648                 :     /* -------------------------------------------------------------------- */
     649                 :     /*      Find the class of this element.                                 */
     650                 :     /* -------------------------------------------------------------------- */
     651             625 :         for( iClass = 0; iClass < m_nClassCount; iClass++ )
     652                 :         {
     653             595 :             if( EQUAL(pszElement,m_papoClass[iClass]->GetElementName()) )
     654             448 :                 break;
     655                 :         }
     656                 : 
     657                 :     /* -------------------------------------------------------------------- */
     658                 :     /*      Create a new feature class for this element, if there is no     */
     659                 :     /*      existing class for it.                                          */
     660                 :     /* -------------------------------------------------------------------- */
     661             478 :         if( iClass == m_nClassCount )
     662                 :         {
     663              30 :             CPLAssert( !m_bClassListLocked );
     664                 : 
     665              30 :             GMLFeatureClass *poNewClass = new GMLFeatureClass( pszElement );
     666                 : 
     667              30 :             AddClass( poNewClass );
     668                 :         }
     669                 :     }
     670                 : 
     671                 : /* -------------------------------------------------------------------- */
     672                 : /*      Create a feature of this feature class.  Try to set the fid     */
     673                 : /*      if available.                                                   */
     674                 : /* -------------------------------------------------------------------- */
     675             960 :     GMLFeature *poFeature = new GMLFeature( m_papoClass[iClass] );
     676             960 :     if( pszFID != NULL )
     677                 :     {
     678             443 :         poFeature->SetFID( pszFID );
     679                 :     }
     680                 : 
     681                 : /* -------------------------------------------------------------------- */
     682                 : /*      Create and push a new read state.                               */
     683                 : /* -------------------------------------------------------------------- */
     684                 :     GMLReadState *poState;
     685                 : 
     686             960 :     poState = m_poRecycledState ? m_poRecycledState : new GMLReadState();
     687             960 :     m_poRecycledState = NULL;
     688             960 :     poState->m_poFeature = poFeature;
     689             960 :     PushState( poState );
     690             960 : }
     691                 : 
     692                 : /************************************************************************/
     693                 : /*                          IsFeatureElement()                          */
     694                 : /*                                                                      */
     695                 : /*      Based on context and the element name, is this element a new    */
     696                 : /*      GML feature element?                                            */
     697                 : /************************************************************************/
     698                 : 
     699            1836 : int GMLReader::GetFeatureElementIndex( const char *pszElement, int nElementLength )
     700                 : 
     701                 : {
     702            1836 :     const char *pszLast = m_poState->GetLastComponent();
     703            1836 :     size_t      nLenLast = m_poState->GetLastComponentLen();
     704                 : 
     705            1836 :     if( nLenLast >= 6 && (EQUAL(pszLast+nLenLast-6,"member") ||
     706                 :                           EQUAL(pszLast+nLenLast-7,"members")) )
     707                 :     {
     708                 :         /* Default feature name */
     709                 :     }
     710                 :     else
     711                 :     {
     712             875 :         if (nLenLast == 4 && strcmp(pszLast, "dane") == 0)
     713                 :         {
     714                 :             /* Polish TBD GML */
     715                 :         }
     716                 : 
     717                 :         /* Begin of OpenLS */
     718             875 :         else if (nLenLast == 19 && nElementLength == 15 &&
     719                 :                  strcmp(pszLast, "GeocodeResponseList") == 0 &&
     720                 :                  strcmp(pszElement, "GeocodedAddress") == 0)
     721                 :         {
     722                 :         }
     723             877 :         else if (nLenLast == 22 &&
     724                 :                  strcmp(pszLast, "DetermineRouteResponse") == 0)
     725                 :         {
     726                 :             /* We don't want the children of RouteInstructionsList */
     727                 :             /* to be a single feature. We want each RouteInstruction */
     728                 :             /* to be a feature */
     729               3 :             if (strcmp(pszElement, "RouteInstructionsList") == 0)
     730               1 :                 return -1;
     731                 :         }
     732             872 :         else if (nElementLength == 16 && nLenLast == 21 &&
     733                 :                  strcmp(pszElement, "RouteInstruction") == 0 &&
     734                 :                  strcmp(pszLast, "RouteInstructionsList") == 0)
     735                 :         {
     736                 :         }
     737                 :         /* End of OpenLS */
     738                 : 
     739             863 :         else if (nLenLast > 6 && strcmp(pszLast + nLenLast - 6, "_layer") == 0 &&
     740                 :                  nElementLength > 8 && strcmp(pszElement + nElementLength - 8, "_feature") == 0)
     741                 :         {
     742                 :             /* GML answer of MapServer WMS GetFeatureInfo request */
     743                 :         }
     744                 :         else
     745             863 :             return -1;
     746                 :     }
     747                 : 
     748                 :     // If the class list isn't locked, any element that is a featureMember
     749                 :     // will do. 
     750             972 :     if( !m_bClassListLocked )
     751             478 :         return INT_MAX;
     752                 : 
     753                 :     // otherwise, find a class with the desired element name.
     754             598 :     for( int i = 0; i < m_nClassCount; i++ )
     755                 :     {
     756            1146 :         if( nElementLength == (int)m_papoClass[i]->GetElementNameLen() &&
     757             548 :             memcmp(pszElement,m_papoClass[i]->GetElementName(), nElementLength) == 0 )
     758             494 :             return i;
     759                 :     }
     760                 : 
     761               0 :     return -1;
     762                 : }
     763                 : 
     764                 : /************************************************************************/
     765                 : /*                IsCityGMLGenericAttributeElement()                    */
     766                 : /************************************************************************/
     767                 : 
     768              12 : int GMLReader::IsCityGMLGenericAttributeElement( const char *pszElement, void* attr )
     769                 : 
     770                 : {
     771              12 :     if( strcmp(pszElement, "stringAttribute") != 0 &&
     772                 :         strcmp(pszElement, "intAttribute") != 0 &&
     773                 :         strcmp(pszElement, "doubleAttribute") != 0 )
     774               6 :         return FALSE;
     775                 : 
     776               6 :     char* pszVal = m_poGMLHandler->GetAttributeValue(attr, "name");
     777               6 :     if (pszVal == NULL)
     778               0 :         return FALSE;
     779                 : 
     780               6 :     GMLFeatureClass *poClass = m_poState->m_poFeature->GetClass();
     781                 : 
     782                 :     // If the schema is not yet locked, then any simple element
     783                 :     // is potentially an attribute.
     784               6 :     if( !poClass->IsSchemaLocked() )
     785                 :     {
     786               6 :         CPLFree(pszVal);
     787               6 :         return TRUE;
     788                 :     }
     789                 : 
     790               0 :     for( int i = 0; i < poClass->GetPropertyCount(); i++ )
     791                 :     {
     792               0 :         if( strcmp(poClass->GetProperty(i)->GetSrcElement(),pszVal) == 0 )
     793                 :         {
     794               0 :             CPLFree(pszVal);
     795               0 :             return TRUE;
     796                 :         }
     797                 :     }
     798                 : 
     799               0 :     CPLFree(pszVal);
     800               0 :     return FALSE;
     801                 : }
     802                 : 
     803                 : /************************************************************************/
     804                 : /*                       GetAttributeElementIndex()                     */
     805                 : /************************************************************************/
     806                 : 
     807            3392 : int GMLReader::GetAttributeElementIndex( const char *pszElement, int nLen )
     808                 : 
     809                 : {
     810            3392 :     GMLFeatureClass *poClass = m_poState->m_poFeature->GetClass();
     811                 : 
     812                 :     // If the schema is not yet locked, then any simple element
     813                 :     // is potentially an attribute.
     814            3392 :     if( !poClass->IsSchemaLocked() )
     815            1758 :         return INT_MAX;
     816                 : 
     817                 :     // Otherwise build the path to this element into a single string
     818                 :     // and compare against known attributes.
     819            1634 :     if( m_poState->m_nPathLength == 0 )
     820            1622 :         return poClass->GetPropertyIndexBySrcElement(pszElement, nLen);
     821                 :     else
     822                 :     {
     823              12 :         int nFullLen = nLen + m_poState->osPath.size() + 1;
     824              12 :         osElemPath.reserve(nFullLen);
     825              12 :         osElemPath.assign(m_poState->osPath);
     826              12 :         osElemPath.append(1, '|');
     827              12 :         osElemPath.append(pszElement, nLen);
     828              12 :         return poClass->GetPropertyIndexBySrcElement(osElemPath.c_str(), nFullLen);
     829                 :     }
     830                 : }
     831                 : 
     832                 : /************************************************************************/
     833                 : /*                              PopState()                              */
     834                 : /************************************************************************/
     835                 : 
     836            1071 : void GMLReader::PopState()
     837                 : 
     838                 : {
     839            1071 :     if( m_poState != NULL )
     840                 :     {
     841                 : #ifdef HAVE_XERCES
     842            1071 :         if( !bUseExpatReader && m_poState->m_poFeature != NULL &&
     843                 :             m_poCompleteFeature == NULL )
     844                 :         {
     845               0 :             m_poCompleteFeature = m_poState->m_poFeature;
     846               0 :             m_poState->m_poFeature = NULL;
     847                 :         }
     848                 : #endif
     849                 : 
     850                 : #ifdef HAVE_EXPAT
     851            1071 :         if ( bUseExpatReader && m_poState->m_poFeature != NULL )
     852                 :         {
     853             960 :             if (nFeatureTabLength >= nFeatureTabAlloc)
     854                 :             {
     855             129 :                 nFeatureTabAlloc = nFeatureTabLength * 4 / 3 + 16;
     856                 :                 ppoFeatureTab = (GMLFeature**)
     857                 :                         CPLRealloc(ppoFeatureTab,
     858             129 :                                     sizeof(GMLFeature*) * (nFeatureTabAlloc));
     859                 :             }
     860             960 :             ppoFeatureTab[nFeatureTabLength] = m_poState->m_poFeature;
     861             960 :             nFeatureTabLength++;
     862                 : 
     863             960 :             m_poState->m_poFeature = NULL;
     864                 :         }
     865                 : #endif
     866                 : 
     867                 :         GMLReadState *poParent;
     868                 : 
     869            1071 :         poParent = m_poState->m_poParentState;
     870                 :         
     871            1071 :         delete m_poRecycledState;
     872            1071 :         m_poRecycledState = m_poState;
     873            1071 :         m_poRecycledState->Reset();
     874            1071 :         m_poState = poParent;
     875                 :     }
     876            1071 : }
     877                 : 
     878                 : /************************************************************************/
     879                 : /*                             PushState()                              */
     880                 : /************************************************************************/
     881                 : 
     882            1071 : void GMLReader::PushState( GMLReadState *poState )
     883                 : 
     884                 : {
     885            1071 :     poState->m_poParentState = m_poState;
     886            1071 :     m_poState = poState;
     887            1071 : }
     888                 : 
     889                 : /************************************************************************/
     890                 : /*                              GetClass()                              */
     891                 : /************************************************************************/
     892                 : 
     893             358 : GMLFeatureClass *GMLReader::GetClass( int iClass ) const
     894                 : 
     895                 : {
     896             358 :     if( iClass < 0 || iClass >= m_nClassCount )
     897               0 :         return NULL;
     898                 :     else
     899             358 :         return m_papoClass[iClass];
     900                 : }
     901                 : 
     902                 : /************************************************************************/
     903                 : /*                              GetClass()                              */
     904                 : /************************************************************************/
     905                 : 
     906             185 : GMLFeatureClass *GMLReader::GetClass( const char *pszName ) const
     907                 : 
     908                 : {
     909             256 :     for( int iClass = 0; iClass < m_nClassCount; iClass++ )
     910                 :     {
     911             162 :         if( EQUAL(GetClass(iClass)->GetName(),pszName) )
     912              91 :             return GetClass(iClass);
     913                 :     }
     914                 : 
     915              94 :     return NULL;
     916                 : }
     917                 : 
     918                 : /************************************************************************/
     919                 : /*                              AddClass()                              */
     920                 : /************************************************************************/
     921                 : 
     922              93 : int GMLReader::AddClass( GMLFeatureClass *poNewClass )
     923                 : 
     924                 : {
     925              93 :     CPLAssert( GetClass( poNewClass->GetName() ) == NULL );
     926                 : 
     927              93 :     m_nClassCount++;
     928                 :     m_papoClass = (GMLFeatureClass **) 
     929              93 :         CPLRealloc( m_papoClass, sizeof(void*) * m_nClassCount );
     930              93 :     m_papoClass[m_nClassCount-1] = poNewClass;
     931                 : 
     932              93 :     return m_nClassCount-1;
     933                 : }
     934                 : 
     935                 : /************************************************************************/
     936                 : /*                            ClearClasses()                            */
     937                 : /************************************************************************/
     938                 : 
     939              88 : void GMLReader::ClearClasses()
     940                 : 
     941                 : {
     942             179 :     for( int i = 0; i < m_nClassCount; i++ )
     943              91 :         delete m_papoClass[i];
     944              88 :     CPLFree( m_papoClass );
     945                 : 
     946              88 :     m_nClassCount = 0;
     947              88 :     m_papoClass = NULL;
     948              88 : }
     949                 : 
     950                 : /************************************************************************/
     951                 : /*                     SetFeaturePropertyDirectly()                     */
     952                 : /*                                                                      */
     953                 : /*      Set the property value on the current feature, adding the       */
     954                 : /*      property name to the GMLFeatureClass if required.               */
     955                 : /*      The pszValue ownership is passed to this function.              */
     956                 : /************************************************************************/
     957                 : 
     958            2443 : void GMLReader::SetFeaturePropertyDirectly( const char *pszElement, 
     959                 :                                             char *pszValue,
     960                 :                                             int iPropertyIn )
     961                 : 
     962                 : {
     963            2443 :     GMLFeature *poFeature = GetState()->m_poFeature;
     964                 : 
     965            2443 :     CPLAssert( poFeature  != NULL );
     966                 : 
     967                 : /* -------------------------------------------------------------------- */
     968                 : /*      Does this property exist in the feature class?  If not, add     */
     969                 : /*      it.                                                             */
     970                 : /* -------------------------------------------------------------------- */
     971            2443 :     GMLFeatureClass *poClass = poFeature->GetClass();
     972                 :     int      iProperty;
     973                 : 
     974            2443 :     int nPropertyCount = poClass->GetPropertyCount();
     975            3588 :     if (iPropertyIn >= 0 && iPropertyIn < nPropertyCount)
     976                 :     {
     977            1145 :         iProperty = iPropertyIn;
     978                 :     }
     979                 :     else
     980                 :     {
     981            2797 :         for( iProperty=0; iProperty < nPropertyCount; iProperty++ )
     982                 :         {
     983            2723 :             if( strcmp(poClass->GetProperty( iProperty )->GetSrcElement(),
     984                 :                     pszElement ) == 0 )
     985            1224 :                 break;
     986                 :         }
     987                 : 
     988            1298 :         if( iProperty == nPropertyCount )
     989                 :         {
     990              74 :             if( poClass->IsSchemaLocked() )
     991                 :             {
     992               0 :                 CPLDebug("GML","Encountered property missing from class schema.");
     993               0 :                 CPLFree(pszValue);
     994               0 :                 return;
     995                 :             }
     996                 : 
     997              74 :             CPLString osFieldName;
     998                 : 
     999              74 :             if( strchr(pszElement,'|') == NULL )
    1000              69 :                 osFieldName = pszElement;
    1001                 :             else
    1002                 :             {
    1003               5 :                 osFieldName = strrchr(pszElement,'|') + 1;
    1004               5 :                 if( poClass->GetPropertyIndex(osFieldName) != -1 )
    1005               0 :                     osFieldName = pszElement;
    1006                 :             }
    1007                 : 
    1008                 :             // Does this conflict with an existing property name?
    1009             149 :             while( poClass->GetProperty(osFieldName) != NULL )
    1010                 :             {
    1011               1 :                 osFieldName += "_";
    1012                 :             }
    1013                 : 
    1014              74 :             GMLPropertyDefn *poPDefn = new GMLPropertyDefn(osFieldName,pszElement);
    1015                 : 
    1016             148 :             if( EQUAL(CPLGetConfigOption( "GML_FIELDTYPES", ""), "ALWAYS_STRING") )
    1017               0 :                 poPDefn->SetType( GMLPT_String );
    1018                 : 
    1019              74 :             if (poClass->AddProperty( poPDefn ) < 0)
    1020                 :             {
    1021               0 :                 delete poPDefn;
    1022               0 :                 CPLFree(pszValue);
    1023                 :                 return;
    1024               0 :             }
    1025                 :         }
    1026                 :     }
    1027                 : 
    1028                 : /* -------------------------------------------------------------------- */
    1029                 : /*      Set the property                                                */
    1030                 : /* -------------------------------------------------------------------- */
    1031            2443 :     poFeature->SetPropertyDirectly( iProperty, pszValue );
    1032                 : 
    1033                 : /* -------------------------------------------------------------------- */
    1034                 : /*      Do we need to update the property type?                         */
    1035                 : /* -------------------------------------------------------------------- */
    1036            2443 :     if( !poClass->IsSchemaLocked() )
    1037                 :     {
    1038                 :         poClass->GetProperty(iProperty)->AnalysePropertyValue(
    1039            1298 :                              poFeature->GetProperty(iProperty));
    1040                 :     }
    1041                 : }
    1042                 : 
    1043                 : /************************************************************************/
    1044                 : /*                            LoadClasses()                             */
    1045                 : /************************************************************************/
    1046                 : 
    1047              15 : int GMLReader::LoadClasses( const char *pszFile )
    1048                 : 
    1049                 : {
    1050                 :     // Add logic later to determine reasonable default schema file. 
    1051              15 :     if( pszFile == NULL )
    1052               0 :         return FALSE;
    1053                 : 
    1054                 : /* -------------------------------------------------------------------- */
    1055                 : /*      Load the raw XML file.                                          */
    1056                 : /* -------------------------------------------------------------------- */
    1057                 :     VSILFILE       *fp;
    1058                 :     int         nLength;
    1059                 :     char        *pszWholeText;
    1060                 : 
    1061              15 :     fp = VSIFOpenL( pszFile, "rb" );
    1062                 : 
    1063              15 :     if( fp == NULL )
    1064                 :     {
    1065                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
    1066               0 :                   "Failed to open file %s.", pszFile );
    1067               0 :         return FALSE;
    1068                 :     }
    1069                 : 
    1070              15 :     VSIFSeekL( fp, 0, SEEK_END );
    1071              15 :     nLength = (int) VSIFTellL( fp );
    1072              15 :     VSIFSeekL( fp, 0, SEEK_SET );
    1073                 : 
    1074              15 :     pszWholeText = (char *) VSIMalloc(nLength+1);
    1075              15 :     if( pszWholeText == NULL )
    1076                 :     {
    1077                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1078                 :                   "Failed to allocate %d byte buffer for %s,\n"
    1079                 :                   "is this really a GMLFeatureClassList file?",
    1080               0 :                   nLength, pszFile );
    1081               0 :         VSIFCloseL( fp );
    1082               0 :         return FALSE;
    1083                 :     }
    1084                 :     
    1085              15 :     if( VSIFReadL( pszWholeText, nLength, 1, fp ) != 1 )
    1086                 :     {
    1087               0 :         VSIFree( pszWholeText );
    1088               0 :         VSIFCloseL( fp );
    1089                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1090               0 :                   "Read failed on %s.", pszFile );
    1091               0 :         return FALSE;
    1092                 :     }
    1093              15 :     pszWholeText[nLength] = '\0';
    1094                 : 
    1095              15 :     VSIFCloseL( fp );
    1096                 : 
    1097              15 :     if( strstr( pszWholeText, "<GMLFeatureClassList>" ) == NULL )
    1098                 :     {
    1099               0 :         VSIFree( pszWholeText );
    1100                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1101                 :                   "File %s does not contain a GMLFeatureClassList tree.",
    1102               0 :                   pszFile );
    1103               0 :         return FALSE;
    1104                 :     }
    1105                 : 
    1106                 : /* -------------------------------------------------------------------- */
    1107                 : /*      Convert to XML parse tree.                                      */
    1108                 : /* -------------------------------------------------------------------- */
    1109                 :     CPLXMLNode *psRoot;
    1110                 : 
    1111              15 :     psRoot = CPLParseXMLString( pszWholeText );
    1112              15 :     VSIFree( pszWholeText );
    1113                 : 
    1114                 :     // We assume parser will report errors via CPL.
    1115              15 :     if( psRoot == NULL )
    1116               0 :         return FALSE;
    1117                 : 
    1118              15 :     if( psRoot->eType != CXT_Element 
    1119                 :         || !EQUAL(psRoot->pszValue,"GMLFeatureClassList") )
    1120                 :     {
    1121               0 :         CPLDestroyXMLNode(psRoot);
    1122                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1123                 :                   "File %s is not a GMLFeatureClassList document.",
    1124               0 :                   pszFile );
    1125               0 :         return FALSE;
    1126                 :     }
    1127                 : 
    1128              15 :     const char* pszSequentialLayers = CPLGetXMLValue(psRoot, "SequentialLayers", NULL);
    1129              15 :     if (pszSequentialLayers)
    1130               3 :         m_bSequentialLayers = CSLTestBoolean(pszSequentialLayers);
    1131                 : 
    1132                 : /* -------------------------------------------------------------------- */
    1133                 : /*      Extract feature classes for all definitions found.              */
    1134                 : /* -------------------------------------------------------------------- */
    1135                 :     CPLXMLNode *psThis;
    1136                 : 
    1137              42 :     for( psThis = psRoot->psChild; psThis != NULL; psThis = psThis->psNext )
    1138                 :     {
    1139              27 :         if( psThis->eType == CXT_Element 
    1140                 :             && EQUAL(psThis->pszValue,"GMLFeatureClass") )
    1141                 :         {
    1142                 :             GMLFeatureClass   *poClass;
    1143                 : 
    1144              24 :             poClass = new GMLFeatureClass();
    1145                 : 
    1146              24 :             if( !poClass->InitializeFromXML( psThis ) )
    1147                 :             {
    1148               0 :                 delete poClass;
    1149               0 :                 CPLDestroyXMLNode( psRoot );
    1150               0 :                 return FALSE;
    1151                 :             }
    1152                 : 
    1153              24 :             poClass->SetSchemaLocked( TRUE );
    1154                 : 
    1155              24 :             AddClass( poClass );
    1156                 :         }
    1157                 :     }
    1158                 : 
    1159              15 :     CPLDestroyXMLNode( psRoot );
    1160                 :     
    1161              15 :     SetClassListLocked( TRUE );
    1162                 : 
    1163              15 :     return TRUE;
    1164                 : }
    1165                 : 
    1166                 : /************************************************************************/
    1167                 : /*                            SaveClasses()                             */
    1168                 : /************************************************************************/
    1169                 : 
    1170              20 : int GMLReader::SaveClasses( const char *pszFile )
    1171                 : 
    1172                 : {
    1173                 :     // Add logic later to determine reasonable default schema file. 
    1174              20 :     if( pszFile == NULL )
    1175               0 :         return FALSE;
    1176                 : 
    1177                 : /* -------------------------------------------------------------------- */
    1178                 : /*      Create in memory schema tree.                                   */
    1179                 : /* -------------------------------------------------------------------- */
    1180                 :     CPLXMLNode *psRoot;
    1181                 : 
    1182              20 :     psRoot = CPLCreateXMLNode( NULL, CXT_Element, "GMLFeatureClassList" );
    1183                 : 
    1184              20 :     if (m_bSequentialLayers != -1 && m_nClassCount > 1)
    1185                 :     {
    1186                 :         CPLCreateXMLElementAndValue( psRoot, "SequentialLayers",
    1187               5 :                                      m_bSequentialLayers ? "true" : "false" );
    1188                 :     }
    1189                 : 
    1190              48 :     for( int iClass = 0; iClass < m_nClassCount; iClass++ )
    1191                 :     {
    1192              28 :         CPLAddXMLChild( psRoot, m_papoClass[iClass]->SerializeToXML() );
    1193                 :     }
    1194                 : 
    1195                 : /* -------------------------------------------------------------------- */
    1196                 : /*      Serialize to disk.                                              */
    1197                 : /* -------------------------------------------------------------------- */
    1198                 :     VSILFILE        *fp;
    1199              20 :     int         bSuccess = TRUE;
    1200              20 :     char        *pszWholeText = CPLSerializeXMLTree( psRoot );
    1201                 :     
    1202              20 :     CPLDestroyXMLNode( psRoot );
    1203                 :  
    1204              20 :     fp = VSIFOpenL( pszFile, "wb" );
    1205                 :     
    1206              20 :     if( fp == NULL )
    1207               0 :         bSuccess = FALSE;
    1208              20 :     else if( VSIFWriteL( pszWholeText, strlen(pszWholeText), 1, fp ) != 1 )
    1209               0 :         bSuccess = FALSE;
    1210                 :     else
    1211              20 :         VSIFCloseL( fp );
    1212                 : 
    1213              20 :     CPLFree( pszWholeText );
    1214                 : 
    1215              20 :     return bSuccess;
    1216                 : }
    1217                 : 
    1218                 : /************************************************************************/
    1219                 : /*                          PrescanForSchema()                          */
    1220                 : /*                                                                      */
    1221                 : /*      For now we use a pretty dumb approach of just doing a normal    */
    1222                 : /*      scan of the whole file, building up the schema information.     */
    1223                 : /*      Eventually we hope to do a more efficient scan when just        */
    1224                 : /*      looking for schema information.                                 */
    1225                 : /************************************************************************/
    1226                 : 
    1227              21 : int GMLReader::PrescanForSchema( int bGetExtents )
    1228                 : 
    1229                 : {
    1230                 :     GMLFeature  *poFeature;
    1231                 : 
    1232              21 :     if( m_pszFilename == NULL )
    1233               0 :         return FALSE;
    1234                 : 
    1235              21 :     SetClassListLocked( FALSE );
    1236                 : 
    1237              21 :     ClearClasses();
    1238              21 :     if( !SetupParser() )
    1239               0 :         return FALSE;
    1240                 : 
    1241              21 :     m_bCanUseGlobalSRSName = TRUE;
    1242                 : 
    1243              21 :     std::map<GMLFeatureClass*, int> osMapCountFeatureWithoutGeometry;
    1244              21 :     GMLFeatureClass *poLastClass = NULL;
    1245                 : 
    1246              21 :     m_bSequentialLayers = TRUE;
    1247                 : 
    1248              21 :     void* hCacheSRS = GML_BuildOGRGeometryFromList_CreateCache();
    1249                 : 
    1250              21 :     std::string osWork;
    1251                 : 
    1252             254 :     while( (poFeature = NextFeature()) != NULL )
    1253                 :     {
    1254             212 :         GMLFeatureClass *poClass = poFeature->GetClass();
    1255                 : 
    1256             212 :         if (poLastClass != NULL && poClass != poLastClass &&
    1257                 :             poClass->GetFeatureCount() != -1)
    1258               0 :             m_bSequentialLayers = FALSE;
    1259             212 :         poLastClass = poClass;
    1260                 : 
    1261             212 :         if( poClass->GetFeatureCount() == -1 )
    1262              28 :             poClass->SetFeatureCount( 1 );
    1263                 :         else
    1264             184 :             poClass->SetFeatureCount( poClass->GetFeatureCount() + 1 );
    1265                 : 
    1266             212 :         const CPLXMLNode* const * papsGeometry = poFeature->GetGeometryList();
    1267             212 :         if (papsGeometry[0] == NULL)
    1268                 :         {
    1269                 :             std::map<GMLFeatureClass*, int>::iterator oIter =
    1270               8 :                 osMapCountFeatureWithoutGeometry.find(poClass);
    1271               8 :             if (oIter == osMapCountFeatureWithoutGeometry.end())
    1272               2 :                 osMapCountFeatureWithoutGeometry[poClass] = 1;
    1273                 :             else
    1274               6 :                 oIter->second ++;
    1275                 :         }
    1276                 : 
    1277                 : 
    1278                 : #ifdef SUPPORT_GEOMETRY
    1279             212 :         if( bGetExtents )
    1280                 :         {
    1281                 :             OGRGeometry *poGeometry = GML_BuildOGRGeometryFromList(
    1282                 :                 papsGeometry, TRUE, m_bInvertAxisOrderIfLatLong,
    1283             212 :                 NULL, m_bConsiderEPSGAsURN, m_bGetSecondaryGeometryOption, hCacheSRS);
    1284                 : 
    1285             212 :             if( poGeometry != NULL )
    1286                 :             {
    1287                 :                 double  dfXMin, dfXMax, dfYMin, dfYMax;
    1288             204 :                 OGREnvelope sEnvelope;
    1289                 :                 OGRwkbGeometryType eGType = (OGRwkbGeometryType) 
    1290             204 :                     poClass->GetGeometryType();
    1291                 : 
    1292                 :                 const char* pszSRSName = GML_ExtractSrsNameFromGeometry(papsGeometry,
    1293                 :                                                                         osWork,
    1294             204 :                                                                         m_bConsiderEPSGAsURN);
    1295             204 :                 if (pszSRSName != NULL)
    1296             107 :                     m_bCanUseGlobalSRSName = FALSE;
    1297             204 :                 poClass->MergeSRSName(pszSRSName);
    1298                 : 
    1299                 :                 // Merge geometry type into layer.
    1300             204 :                 if( poClass->GetFeatureCount() == 1 && eGType == wkbUnknown )
    1301              26 :                     eGType = wkbNone;
    1302                 : 
    1303                 :                 poClass->SetGeometryType( 
    1304                 :                     (int) OGRMergeGeometryTypes(
    1305             204 :                         eGType, poGeometry->getGeometryType() ) );
    1306                 : 
    1307                 :                 // merge extents.
    1308             204 :                 if (!poGeometry->IsEmpty())
    1309                 :                 {
    1310             204 :                     poGeometry->getEnvelope( &sEnvelope );
    1311             204 :                     if( poClass->GetExtents(&dfXMin, &dfXMax, &dfYMin, &dfYMax) )
    1312                 :                     {
    1313             178 :                         dfXMin = MIN(dfXMin,sEnvelope.MinX);
    1314             178 :                         dfXMax = MAX(dfXMax,sEnvelope.MaxX);
    1315             178 :                         dfYMin = MIN(dfYMin,sEnvelope.MinY);
    1316             178 :                         dfYMax = MAX(dfYMax,sEnvelope.MaxY);
    1317                 :                     }
    1318                 :                     else
    1319                 :                     {
    1320              26 :                         dfXMin = sEnvelope.MinX;
    1321              26 :                         dfXMax = sEnvelope.MaxX;
    1322              26 :                         dfYMin = sEnvelope.MinY;
    1323              26 :                         dfYMax = sEnvelope.MaxY;
    1324                 :                     }
    1325                 : 
    1326             204 :                     poClass->SetExtents( dfXMin, dfXMax, dfYMin, dfYMax );
    1327                 :                 }
    1328             204 :                 delete poGeometry;
    1329                 : 
    1330                 :             }
    1331                 : #endif /* def SUPPORT_GEOMETRY */
    1332                 :         }
    1333                 :         
    1334             212 :         delete poFeature;
    1335                 :     }
    1336                 : 
    1337              21 :     GML_BuildOGRGeometryFromList_DestroyCache(hCacheSRS);
    1338                 : 
    1339              49 :     for( int i = 0; i < m_nClassCount; i++ )
    1340                 :     {
    1341              28 :         GMLFeatureClass *poClass = m_papoClass[i];
    1342              28 :         const char* pszSRSName = poClass->GetSRSName();
    1343                 : 
    1344              28 :         if (m_bCanUseGlobalSRSName)
    1345              13 :             pszSRSName = m_pszGlobalSRSName;
    1346                 :         
    1347              28 :         if (m_bInvertAxisOrderIfLatLong && GML_IsSRSLatLongOrder(pszSRSName))
    1348                 :         {
    1349               6 :             OGRSpatialReference oSRS;
    1350               6 :             if (oSRS.SetFromUserInput(pszSRSName) == OGRERR_NONE)
    1351                 :             {
    1352               6 :                 OGR_SRSNode *poGEOGCS = oSRS.GetAttrNode( "GEOGCS" );
    1353               6 :                 if( poGEOGCS != NULL )
    1354                 :                 {
    1355               6 :                     poGEOGCS->StripNodes( "AXIS" );
    1356                 : 
    1357               6 :                     char* pszWKT = NULL;
    1358               6 :                     if (oSRS.exportToWkt(&pszWKT) == OGRERR_NONE)
    1359               6 :                         poClass->SetSRSName(pszWKT);
    1360               6 :                     CPLFree(pszWKT);
    1361                 : 
    1362                 :                     /* So when we have computed the extent, we didn't know yet */
    1363                 :                     /* the SRS to use. Now we know it, we have to fix the extent */
    1364                 :                     /* order */
    1365               6 :                     if (m_bCanUseGlobalSRSName)
    1366                 :                     {
    1367                 :                         double  dfXMin, dfXMax, dfYMin, dfYMax;
    1368               1 :                         if( poClass->GetExtents(&dfXMin, &dfXMax, &dfYMin, &dfYMax) )
    1369               1 :                             poClass->SetExtents( dfYMin, dfYMax, dfXMin, dfXMax );
    1370                 :                     }
    1371                 :                 }
    1372               6 :             }
    1373                 :         }
    1374                 : 
    1375                 :         std::map<GMLFeatureClass*, int>::iterator oIter =
    1376              28 :                 osMapCountFeatureWithoutGeometry.find(poClass);
    1377              28 :         if (oIter != osMapCountFeatureWithoutGeometry.end() &&
    1378                 :             oIter->second == poClass->GetFeatureCount())
    1379                 :         {
    1380               2 :             poClass->SetGeometryType(wkbNone);
    1381                 :         }
    1382                 :     }
    1383                 : 
    1384              21 :     CleanupParser();
    1385                 : 
    1386              21 :     return m_nClassCount > 0;
    1387                 : }
    1388                 : 
    1389                 : /************************************************************************/
    1390                 : /*                            ResetReading()                            */
    1391                 : /************************************************************************/
    1392                 : 
    1393             156 : void GMLReader::ResetReading()
    1394                 : 
    1395                 : {
    1396             156 :     CleanupParser();
    1397             156 :     SetFilteredClassName(NULL);
    1398             156 : }
    1399                 : 
    1400                 : /************************************************************************/
    1401                 : /*                          SetGlobalSRSName()                          */
    1402                 : /************************************************************************/
    1403                 : 
    1404              51 : void GMLReader::SetGlobalSRSName( const char* pszGlobalSRSName )
    1405                 : {
    1406              51 :     if (m_pszGlobalSRSName == NULL && pszGlobalSRSName != NULL)
    1407                 :     {
    1408              31 :         if (strncmp(pszGlobalSRSName, "EPSG:", 5) == 0 &&
    1409                 :             m_bConsiderEPSGAsURN)
    1410                 :         {
    1411                 :             m_pszGlobalSRSName = CPLStrdup(CPLSPrintf("urn:ogc:def:crs:EPSG::%s",
    1412               5 :                                                       pszGlobalSRSName+5));
    1413                 :         }
    1414                 :         else
    1415                 :         {
    1416              21 :             m_pszGlobalSRSName = CPLStrdup(pszGlobalSRSName);
    1417                 :         }
    1418                 :     }
    1419              51 : }
    1420                 : 
    1421                 : /************************************************************************/
    1422                 : /*                       SetFilteredClassName()                         */
    1423                 : /************************************************************************/
    1424                 : 
    1425             159 : int GMLReader::SetFilteredClassName(const char* pszClassName)
    1426                 : {
    1427             159 :     CPLFree(m_pszFilteredClassName);
    1428             159 :     m_pszFilteredClassName = (pszClassName) ? CPLStrdup(pszClassName) : NULL;
    1429             159 :     return TRUE;
    1430                 : }

Generated by: LCOV version 1.7