LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/gml - gmlreader.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 289 254 87.9 %
Date: 2010-01-09 Functions: 27 26 96.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: gmlreader.cpp 18190 2009-12-06 05:25:31Z chaitanya $
       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                 : 
      33                 : #define SUPPORT_GEOMETRY
      34                 : 
      35                 : #ifdef SUPPORT_GEOMETRY
      36                 : #  include "ogr_geometry.h"
      37                 : #endif
      38                 : 
      39                 : /************************************************************************/
      40                 : /*                            ~IGMLReader()                             */
      41                 : /************************************************************************/
      42                 : 
      43              17 : IGMLReader::~IGMLReader()
      44                 : 
      45                 : {
      46              17 : }
      47                 : 
      48                 : /************************************************************************/
      49                 : /* ==================================================================== */
      50                 : /*                  No XERCES or EXPAT Library                          */
      51                 : /* ==================================================================== */
      52                 : /************************************************************************/
      53                 : #if HAVE_XERCES == 0 && !defined(HAVE_EXPAT)
      54                 : 
      55                 : /************************************************************************/
      56                 : /*                          CreateGMLReader()                           */
      57                 : /************************************************************************/
      58                 : 
      59                 : IGMLReader *CreateGMLReader()
      60                 : 
      61                 : {
      62                 :     CPLError( CE_Failure, CPLE_AppDefined,
      63                 :               "Unable to create Xerces C++ or Expat based GML reader, Xerces or Expat support\n"
      64                 :               "not configured into GDAL/OGR." );
      65                 :     return NULL;
      66                 : }
      67                 : 
      68                 : /************************************************************************/
      69                 : /* ==================================================================== */
      70                 : /*                  With XERCES or EXPAT Library                        */
      71                 : /* ==================================================================== */
      72                 : /************************************************************************/
      73                 : #else /* HAVE_XERCES == 1 or HAVE_EXPAT */
      74                 : 
      75                 : #include "gmlreaderp.h"
      76                 : #include "cpl_conv.h"
      77                 : 
      78                 : /************************************************************************/
      79                 : /*                          CreateGMLReader()                           */
      80                 : /************************************************************************/
      81                 : 
      82              17 : IGMLReader *CreateGMLReader()
      83                 : 
      84                 : {
      85              17 :     return new GMLReader();
      86                 : }
      87                 : 
      88                 : int GMLReader::m_bXercesInitialized = FALSE;
      89                 : int GMLReader::m_nInstanceCount = 0;
      90                 : 
      91                 : /************************************************************************/
      92                 : /*                             GMLReader()                              */
      93                 : /************************************************************************/
      94                 : 
      95              17 : GMLReader::GMLReader()
      96                 : 
      97                 : {
      98              17 :     m_nInstanceCount++;
      99              17 :     m_nClassCount = 0;
     100              17 :     m_papoClass = NULL;
     101                 : 
     102              17 :     m_bClassListLocked = FALSE;
     103                 : 
     104              17 :     m_poGMLHandler = NULL;
     105                 : #if HAVE_XERCES == 1
     106                 :     m_poSAXReader = NULL;
     107                 :     m_poCompleteFeature = NULL;
     108                 : #else
     109              17 :     oParser = NULL;
     110              17 :     ppoFeatureTab = NULL;
     111              17 :     nFeatureTabIndex = 0;
     112              17 :     nFeatureTabLength = 0;
     113              17 :     fpGML = NULL;
     114                 : #endif
     115              17 :     m_bReadStarted = FALSE;
     116                 :     
     117              17 :     m_poState = NULL;
     118                 : 
     119              17 :     m_pszFilename = NULL;
     120                 : 
     121              17 :     m_bStopParsing = FALSE;
     122              17 : }
     123                 : 
     124                 : /************************************************************************/
     125                 : /*                             ~GMLReader()                             */
     126                 : /************************************************************************/
     127                 : 
     128              34 : GMLReader::~GMLReader()
     129                 : 
     130                 : {
     131              17 :     ClearClasses();
     132                 : 
     133              17 :     CPLFree( m_pszFilename );
     134                 : 
     135              17 :     CleanupParser();
     136                 : 
     137              17 :     --m_nInstanceCount;
     138                 : #if HAVE_XERCES == 1
     139                 :     if( m_nInstanceCount == 0 && m_bXercesInitialized )
     140                 :     {
     141                 :         XMLPlatformUtils::Terminate();
     142                 :         m_bXercesInitialized = FALSE;
     143                 :     }
     144                 : #endif
     145                 : 
     146                 : #ifdef HAVE_EXPAT
     147              17 :     if (fpGML)
     148              16 :         VSIFCloseL(fpGML);
     149              17 :     fpGML = NULL;
     150                 : #endif
     151              34 : }
     152                 : 
     153                 : /************************************************************************/
     154                 : /*                             SetSource()                              */
     155                 : /************************************************************************/
     156                 : 
     157              17 : void GMLReader::SetSourceFile( const char *pszFilename )
     158                 : 
     159                 : {
     160              17 :     CPLFree( m_pszFilename );
     161              17 :     m_pszFilename = CPLStrdup( pszFilename );
     162              17 : }
     163                 : 
     164                 : #ifdef HAVE_EXPAT
     165                 : 
     166             702 : static void XMLCALL startElementCbk(void *pUserData, const char *pszName,
     167                 :                                     const char **ppszAttr)
     168                 : {
     169             702 :     ((GMLHandler*)pUserData)->startElement(pszName, ppszAttr);
     170             702 : }
     171                 : 
     172             702 : static void XMLCALL endElementCbk(void *pUserData, const char *pszName)
     173                 : {
     174             702 :     ((GMLHandler*)pUserData)->endElement(pszName);
     175             702 : }
     176                 : 
     177            1801 : static void XMLCALL dataHandlerCbk(void *pUserData, const char *data, int nLen)
     178                 : {
     179            1801 :     ((GMLHandler*)pUserData)->dataHandler(data, nLen);
     180            1801 : }
     181                 : 
     182                 : #endif
     183                 : 
     184                 : /************************************************************************/
     185                 : /*                            SetupParser()                             */
     186                 : /************************************************************************/
     187                 : 
     188              23 : int GMLReader::SetupParser()
     189                 : 
     190                 : {
     191                 : #if HAVE_XERCES == 1
     192                 : 
     193                 :     if( !m_bXercesInitialized )
     194                 :     {
     195                 :         try
     196                 :         {
     197                 :             XMLPlatformUtils::Initialize();
     198                 :         }
     199                 :         
     200                 :         catch (const XMLException& toCatch)
     201                 :         {
     202                 :             CPLError( CE_Warning, CPLE_AppDefined,
     203                 :                       "Exception initializing Xerces based GML reader.\n%s", 
     204                 :                       tr_strdup(toCatch.getMessage()) );
     205                 :             return FALSE;
     206                 :         }
     207                 :         m_bXercesInitialized = TRUE;
     208                 :     }
     209                 : 
     210                 :     // Cleanup any old parser.
     211                 :     if( m_poSAXReader != NULL )
     212                 :         CleanupParser();
     213                 : 
     214                 :     // Create and initialize parser.
     215                 :     XMLCh* xmlUriValid = NULL;
     216                 :     XMLCh* xmlUriNS = NULL;
     217                 : 
     218                 :     try{
     219                 :         m_poSAXReader = XMLReaderFactory::createXMLReader();
     220                 :     
     221                 :         m_poGMLHandler = new GMLXercesHandler( this );
     222                 : 
     223                 :         m_poSAXReader->setContentHandler( m_poGMLHandler );
     224                 :         m_poSAXReader->setErrorHandler( m_poGMLHandler );
     225                 :         m_poSAXReader->setLexicalHandler( m_poGMLHandler );
     226                 :         m_poSAXReader->setEntityResolver( m_poGMLHandler );
     227                 :         m_poSAXReader->setDTDHandler( m_poGMLHandler );
     228                 : 
     229                 :         xmlUriValid = XMLString::transcode("http://xml.org/sax/features/validation");
     230                 :         xmlUriNS = XMLString::transcode("http://xml.org/sax/features/namespaces");
     231                 : 
     232                 : #if (OGR_GML_VALIDATION)
     233                 :         m_poSAXReader->setFeature( xmlUriValid, true);
     234                 :         m_poSAXReader->setFeature( xmlUriNS, true);
     235                 : 
     236                 :         m_poSAXReader->setFeature( XMLUni::fgSAX2CoreNameSpaces, true );
     237                 :         m_poSAXReader->setFeature( XMLUni::fgXercesSchema, true );
     238                 : 
     239                 : //    m_poSAXReader->setDoSchema(true);
     240                 : //    m_poSAXReader->setValidationSchemaFullChecking(true);
     241                 : #else
     242                 :         m_poSAXReader->setFeature( XMLUni::fgSAX2CoreValidation, false);
     243                 : 
     244                 : #if XERCES_VERSION_MAJOR >= 3
     245                 :         m_poSAXReader->setFeature( XMLUni::fgXercesSchema, false);
     246                 : #else
     247                 :         m_poSAXReader->setFeature( XMLUni::fgSAX2CoreNameSpaces, false);
     248                 : #endif
     249                 : 
     250                 : #endif
     251                 :         XMLString::release( &xmlUriValid );
     252                 :         XMLString::release( &xmlUriNS );
     253                 :     }
     254                 :     catch (...)
     255                 :     {
     256                 :         XMLString::release( &xmlUriValid );
     257                 :         XMLString::release( &xmlUriNS );
     258                 : 
     259                 :         CPLError( CE_Warning, CPLE_AppDefined,
     260                 :                   "Exception initializing Xerces based GML reader.\n" );
     261                 :         return FALSE;
     262                 :     }
     263                 : #else
     264                 :     // Cleanup any old parser.
     265              23 :     if( oParser != NULL )
     266               0 :         CleanupParser();
     267                 : 
     268              23 :     oParser = OGRCreateExpatXMLParser();
     269              23 :     m_poGMLHandler = new GMLExpatHandler( this, oParser );
     270                 : 
     271              23 :     XML_SetElementHandler(oParser, ::startElementCbk, ::endElementCbk);
     272              23 :     XML_SetCharacterDataHandler(oParser, ::dataHandlerCbk);
     273              23 :     XML_SetUserData(oParser, m_poGMLHandler);
     274                 : 
     275              23 :     if (fpGML != NULL)
     276               7 :         VSIFSeekL( fpGML, 0, SEEK_SET );
     277                 : #endif
     278                 : 
     279              23 :     m_bReadStarted = FALSE;
     280                 : 
     281                 :     // Push an empty state.
     282              23 :     PushState( new GMLReadState() );
     283                 : 
     284              23 :     return TRUE;
     285                 : }
     286                 : 
     287                 : /************************************************************************/
     288                 : /*                           CleanupParser()                            */
     289                 : /************************************************************************/
     290                 : 
     291              43 : void GMLReader::CleanupParser()
     292                 : 
     293                 : {
     294                 : #if HAVE_XERCES == 1
     295                 :     if( m_poSAXReader == NULL )
     296                 :         return;
     297                 : #else
     298              43 :     if (oParser == NULL )
     299              20 :         return;
     300                 : #endif
     301                 : 
     302              69 :     while( m_poState )
     303              23 :         PopState();
     304                 : 
     305                 : #if HAVE_XERCES == 1
     306                 :     delete m_poSAXReader;
     307                 :     m_poSAXReader = NULL;
     308                 : #else
     309              23 :     if (oParser)
     310              23 :         XML_ParserFree(oParser);
     311              23 :     oParser = NULL;
     312                 : 
     313                 :     int i;
     314              24 :     for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
     315               1 :         delete ppoFeatureTab[i];
     316              23 :     CPLFree(ppoFeatureTab);
     317              23 :     nFeatureTabIndex = 0;
     318              23 :     nFeatureTabLength = 0;
     319              23 :     ppoFeatureTab = NULL;
     320                 : 
     321                 : #endif
     322                 : 
     323              23 :     delete m_poGMLHandler;
     324              23 :     m_poGMLHandler = NULL;
     325                 : 
     326              23 :     m_bReadStarted = FALSE;
     327                 : }
     328                 : 
     329                 : /************************************************************************/
     330                 : /*                            NextFeature()                             */
     331                 : /************************************************************************/
     332                 : 
     333                 : #if HAVE_XERCES == 1
     334                 : GMLFeature *GMLReader::NextFeature()
     335                 : 
     336                 : {
     337                 :     GMLFeature *poReturn = NULL;
     338                 : 
     339                 :     try
     340                 :     {
     341                 :         if( !m_bReadStarted )
     342                 :         {
     343                 :             if( m_poSAXReader == NULL )
     344                 :                 SetupParser();
     345                 : 
     346                 :             if( !m_poSAXReader->parseFirst( m_pszFilename, m_oToFill ) )
     347                 :                 return NULL;
     348                 :             m_bReadStarted = TRUE;
     349                 :         }
     350                 : 
     351                 :         while( m_poCompleteFeature == NULL 
     352                 :                && !m_bStopParsing
     353                 :                && m_poSAXReader->parseNext( m_oToFill ) ) {}
     354                 : 
     355                 :         poReturn = m_poCompleteFeature;
     356                 :         m_poCompleteFeature = NULL;
     357                 : 
     358                 :     }
     359                 :     catch (const XMLException& toCatch)
     360                 :     {
     361                 :         char *pszErrorMessage = tr_strdup( toCatch.getMessage() );
     362                 :         CPLDebug( "GML", 
     363                 :                   "Error during NextFeature()! Message:\n%s", 
     364                 :                   pszErrorMessage );
     365                 :         CPLFree(pszErrorMessage);
     366                 :         m_bStopParsing = TRUE;
     367                 :     }
     368                 :     catch (const SAXException& toCatch)
     369                 :     {
     370                 :         char *pszErrorMessage = tr_strdup( toCatch.getMessage() );
     371                 :         CPLError(CE_Failure, CPLE_AppDefined, "%s", pszErrorMessage);
     372                 :         CPLFree(pszErrorMessage);
     373                 :         m_bStopParsing = TRUE;
     374                 :     }
     375                 : 
     376                 :     return poReturn;
     377                 : }
     378                 : #else
     379              74 : GMLFeature *GMLReader::NextFeature()
     380                 : 
     381                 : {
     382              74 :     if (!m_bReadStarted)
     383                 :     {
     384              23 :         if (oParser == NULL)
     385              13 :             SetupParser();
     386                 : 
     387              23 :         if (fpGML == NULL)
     388              16 :             fpGML = VSIFOpenL(m_pszFilename, "rt");
     389                 : 
     390              23 :         m_bReadStarted = TRUE;
     391                 :     }
     392                 : 
     393              74 :     if (fpGML == NULL || m_bStopParsing)
     394               0 :         return NULL;
     395                 : 
     396              74 :     if (nFeatureTabIndex < nFeatureTabLength)
     397                 :     {
     398              35 :         return ppoFeatureTab[nFeatureTabIndex++];
     399                 :     }
     400                 : 
     401              39 :     if (VSIFEofL(fpGML))
     402              16 :         return NULL;
     403                 : 
     404                 :     char aBuf[BUFSIZ];
     405                 : 
     406              23 :     CPLFree(ppoFeatureTab);
     407              23 :     ppoFeatureTab = NULL;
     408              23 :     nFeatureTabLength = 0;
     409              23 :     nFeatureTabIndex = 0;
     410                 : 
     411                 :     int nDone;
     412              23 :     do
     413                 :     {
     414              23 :         m_poGMLHandler->ResetDataHandlerCounter();
     415                 : 
     416                 :         unsigned int nLen =
     417              23 :                 (unsigned int)VSIFReadL( aBuf, 1, sizeof(aBuf), fpGML );
     418              23 :         nDone = VSIFEofL(fpGML);
     419              23 :         if (XML_Parse(oParser, aBuf, nLen, nDone) == XML_STATUS_ERROR)
     420                 :         {
     421                 :             CPLError(CE_Failure, CPLE_AppDefined,
     422                 :                      "XML parsing of GML file failed : %s "
     423                 :                      "at line %d, column %d",
     424                 :                      XML_ErrorString(XML_GetErrorCode(oParser)),
     425                 :                      (int)XML_GetCurrentLineNumber(oParser),
     426               0 :                      (int)XML_GetCurrentColumnNumber(oParser));
     427               0 :             m_bStopParsing = TRUE;
     428                 :         }
     429              23 :         if (!m_bStopParsing)
     430              23 :             m_bStopParsing = m_poGMLHandler->HasStoppedParsing();
     431                 : 
     432                 :     } while (!nDone && !m_bStopParsing && nFeatureTabLength == 0);
     433                 : 
     434              23 :     return (nFeatureTabLength) ? ppoFeatureTab[nFeatureTabIndex++] : NULL;
     435                 : }
     436                 : #endif
     437                 : 
     438                 : /************************************************************************/
     439                 : /*                            PushFeature()                             */
     440                 : /*                                                                      */
     441                 : /*      Create a feature based on the named element.  If the            */
     442                 : /*      corresponding feature class doesn't exist yet, then create      */
     443                 : /*      it now.  A new GMLReadState will be created for the feature,    */
     444                 : /*      and it will be placed within that state.  The state is          */
     445                 : /*      pushed onto the readstate stack.                                */
     446                 : /************************************************************************/
     447                 : 
     448              56 : void GMLReader::PushFeature( const char *pszElement, 
     449                 :                              const char *pszFID )
     450                 : 
     451                 : {
     452                 :     int iClass;
     453                 : 
     454                 : /* -------------------------------------------------------------------- */
     455                 : /*      Find the class of this element.                                 */
     456                 : /* -------------------------------------------------------------------- */
     457              58 :     for( iClass = 0; iClass < GetClassCount(); iClass++ )
     458                 :     {
     459              50 :         if( EQUAL(pszElement,GetClass(iClass)->GetElementName()) )
     460              48 :             break;
     461                 :     }
     462                 : 
     463                 : /* -------------------------------------------------------------------- */
     464                 : /*      Create a new feature class for this element, if there is no     */
     465                 : /*      existing class for it.                                          */
     466                 : /* -------------------------------------------------------------------- */
     467              56 :     if( iClass == GetClassCount() )
     468                 :     {
     469                 :         CPLAssert( !IsClassListLocked() );
     470                 : 
     471               8 :         GMLFeatureClass *poNewClass = new GMLFeatureClass( pszElement );
     472                 : 
     473               8 :         AddClass( poNewClass );
     474                 :     }
     475                 : 
     476                 : /* -------------------------------------------------------------------- */
     477                 : /*      Create a feature of this feature class.  Try to set the fid     */
     478                 : /*      if available.                                                   */
     479                 : /* -------------------------------------------------------------------- */
     480              56 :     GMLFeature *poFeature = new GMLFeature( GetClass( iClass ) );
     481              56 :     if( pszFID != NULL )
     482                 :     {
     483              52 :         poFeature->SetFID( pszFID );
     484                 :     }
     485                 : 
     486                 : /* -------------------------------------------------------------------- */
     487                 : /*      Create and push a new read state.                               */
     488                 : /* -------------------------------------------------------------------- */
     489                 :     GMLReadState *poState;
     490                 : 
     491              56 :     poState = new GMLReadState();
     492              56 :     poState->m_poFeature = poFeature;
     493              56 :     PushState( poState );
     494              56 : }
     495                 : 
     496                 : /************************************************************************/
     497                 : /*                          IsFeatureElement()                          */
     498                 : /*                                                                      */
     499                 : /*      Based on context and the element name, is this element a new    */
     500                 : /*      GML feature element?                                            */
     501                 : /************************************************************************/
     502                 : 
     503             566 : int GMLReader::IsFeatureElement( const char *pszElement )
     504                 : 
     505                 : {
     506                 :     CPLAssert( m_poState != NULL );
     507                 : 
     508             566 :     const char *pszLast = m_poState->GetLastComponent();
     509             566 :     int        nLen = strlen(pszLast);
     510                 : 
     511             566 :     if( nLen < 6 || !(EQUAL(pszLast+nLen-6,"member") ||
     512                 :                       EQUAL(pszLast+nLen-7,"members")) )
     513             510 :         return FALSE;
     514                 : 
     515                 :     // If the class list isn't locked, any element that is a featureMember
     516                 :     // will do. 
     517              56 :     if( !IsClassListLocked() )
     518              44 :         return TRUE;
     519                 : 
     520                 :     // otherwise, find a class with the desired element name.
     521              12 :     for( int i = 0; i < GetClassCount(); i++ )
     522                 :     {
     523              12 :         if( EQUAL(pszElement,GetClass(i)->GetElementName()) )
     524              12 :             return TRUE;
     525                 :     }
     526                 : 
     527               0 :     return FALSE;
     528                 : }
     529                 : 
     530                 : /************************************************************************/
     531                 : /*                         IsAttributeElement()                         */
     532                 : /************************************************************************/
     533                 : 
     534             510 : int GMLReader::IsAttributeElement( const char *pszElement )
     535                 : 
     536                 : {
     537             510 :     if( m_poState->m_poFeature == NULL )
     538             260 :         return FALSE;
     539                 : 
     540             250 :     if( m_poState->m_nPathLength > 0 )
     541              14 :         return FALSE;
     542                 : 
     543             236 :     GMLFeatureClass *poClass = m_poState->m_poFeature->GetClass();
     544                 : 
     545             236 :     if( !poClass->IsSchemaLocked() )
     546             170 :         return TRUE;
     547                 : 
     548             275 :     for( int i = 0; i < poClass->GetPropertyCount(); i++ )
     549             262 :         if( EQUAL(poClass->GetProperty(i)->GetSrcElement(),pszElement) )
     550              53 :             return TRUE;
     551                 : 
     552              13 :     return FALSE;
     553                 : }
     554                 : 
     555                 : /************************************************************************/
     556                 : /*                              PopState()                              */
     557                 : /************************************************************************/
     558                 : 
     559              79 : void GMLReader::PopState()
     560                 : 
     561                 : {
     562              79 :     if( m_poState != NULL )
     563                 :     {
     564                 : #if HAVE_XERCES == 1
     565                 :         if( m_poState->m_poFeature != NULL && m_poCompleteFeature == NULL )
     566                 :         {
     567                 :             m_poCompleteFeature = m_poState->m_poFeature;
     568                 :             m_poState->m_poFeature = NULL;
     569                 :         }
     570                 : #else
     571              79 :         if ( m_poState->m_poFeature != NULL )
     572                 :         {
     573                 :             ppoFeatureTab = (GMLFeature**)
     574                 :                     CPLRealloc(ppoFeatureTab,
     575              56 :                                 sizeof(GMLFeature*) * (nFeatureTabLength + 1));
     576              56 :             ppoFeatureTab[nFeatureTabLength] = m_poState->m_poFeature;
     577              56 :             nFeatureTabLength++;
     578                 : 
     579              56 :             m_poState->m_poFeature = NULL;
     580                 :         }
     581                 : #endif
     582                 : 
     583                 :         GMLReadState *poParent;
     584                 : 
     585              79 :         poParent = m_poState->m_poParentState;
     586                 :         
     587              79 :         delete m_poState;
     588              79 :         m_poState = poParent;
     589                 :     }
     590              79 : }
     591                 : 
     592                 : /************************************************************************/
     593                 : /*                             PushState()                              */
     594                 : /************************************************************************/
     595                 : 
     596              79 : void GMLReader::PushState( GMLReadState *poState )
     597                 : 
     598                 : {
     599              79 :     poState->m_poParentState = m_poState;
     600              79 :     m_poState = poState;
     601              79 : }
     602                 : 
     603                 : /************************************************************************/
     604                 : /*                              GetClass()                              */
     605                 : /************************************************************************/
     606                 : 
     607             172 : GMLFeatureClass *GMLReader::GetClass( int iClass ) const
     608                 : 
     609                 : {
     610             172 :     if( iClass < 0 || iClass >= m_nClassCount )
     611               0 :         return NULL;
     612                 :     else
     613             172 :         return m_papoClass[iClass];
     614                 : }
     615                 : 
     616                 : /************************************************************************/
     617                 : /*                              GetClass()                              */
     618                 : /************************************************************************/
     619                 : 
     620              15 : GMLFeatureClass *GMLReader::GetClass( const char *pszName ) const
     621                 : 
     622                 : {
     623              16 :     for( int iClass = 0; iClass < m_nClassCount; iClass++ )
     624                 :     {
     625              16 :         if( EQUAL(GetClass(iClass)->GetName(),pszName) )
     626              15 :             return GetClass(iClass);
     627                 :     }
     628                 : 
     629               0 :     return NULL;
     630                 : }
     631                 : 
     632                 : /************************************************************************/
     633                 : /*                              AddClass()                              */
     634                 : /************************************************************************/
     635                 : 
     636              15 : int GMLReader::AddClass( GMLFeatureClass *poNewClass )
     637                 : 
     638                 : {
     639                 :     CPLAssert( GetClass( poNewClass->GetName() ) == NULL );
     640                 : 
     641              15 :     m_nClassCount++;
     642                 :     m_papoClass = (GMLFeatureClass **) 
     643              15 :         CPLRealloc( m_papoClass, sizeof(void*) * m_nClassCount );
     644              15 :     m_papoClass[m_nClassCount-1] = poNewClass;
     645                 : 
     646              15 :     return m_nClassCount-1;
     647                 : }
     648                 : 
     649                 : /************************************************************************/
     650                 : /*                            ClearClasses()                            */
     651                 : /************************************************************************/
     652                 : 
     653              27 : void GMLReader::ClearClasses()
     654                 : 
     655                 : {
     656              42 :     for( int i = 0; i < m_nClassCount; i++ )
     657              15 :         delete m_papoClass[i];
     658              27 :     CPLFree( m_papoClass );
     659                 : 
     660              27 :     m_nClassCount = 0;
     661              27 :     m_papoClass = NULL;
     662              27 : }
     663                 : 
     664                 : /************************************************************************/
     665                 : /*                         SetFeatureProperty()                         */
     666                 : /*                                                                      */
     667                 : /*      Set the property value on the current feature, adding the       */
     668                 : /*      property name to the GMLFeatureClass if required.               */
     669                 : /*      Eventually this function may also "refine" the property         */
     670                 : /*      type based on what is encountered.                              */
     671                 : /************************************************************************/
     672                 : 
     673             179 : void GMLReader::SetFeatureProperty( const char *pszElement, 
     674                 :                                     const char *pszValue )
     675                 : 
     676                 : {
     677             179 :     GMLFeature *poFeature = GetState()->m_poFeature;
     678                 : 
     679                 :     CPLAssert( poFeature  != NULL );
     680                 : 
     681                 : /* -------------------------------------------------------------------- */
     682                 : /*      Does this property exist in the feature class?  If not, add     */
     683                 : /*      it.                                                             */
     684                 : /* -------------------------------------------------------------------- */
     685             179 :     GMLFeatureClass *poClass = poFeature->GetClass();
     686                 :     int      iProperty;
     687                 : 
     688             434 :     for( iProperty=0; iProperty < poClass->GetPropertyCount(); iProperty++ )
     689                 :     {
     690             413 :         if( EQUAL(poClass->GetProperty( iProperty )->GetSrcElement(),
     691                 :                   pszElement ) )
     692             158 :             break;
     693                 :     }
     694                 :     
     695             179 :     if( iProperty == poClass->GetPropertyCount() )
     696                 :     {
     697              21 :         if( poClass->IsSchemaLocked() )
     698                 :         {
     699               0 :             CPLDebug("GML","Encountered property missing from class schema.");
     700               0 :             return;
     701                 :         }
     702                 : 
     703              21 :         GMLPropertyDefn *poPDefn = new GMLPropertyDefn(pszElement,pszElement);
     704                 : 
     705              21 :         if( EQUAL(CPLGetConfigOption( "GML_FIELDTYPES", ""), "ALWAYS_STRING") )
     706               0 :             poPDefn->SetType( GMLPT_String );
     707                 : 
     708              21 :         poClass->AddProperty( poPDefn );
     709                 : 
     710                 :     }
     711                 : 
     712                 : /* -------------------------------------------------------------------- */
     713                 : /*      Set the property                                                */
     714                 : /* -------------------------------------------------------------------- */
     715             179 :     poFeature->SetProperty( iProperty, pszValue );
     716                 : 
     717                 : /* -------------------------------------------------------------------- */
     718                 : /*      Do we need to update the property type?                         */
     719                 : /* -------------------------------------------------------------------- */
     720             179 :     if( !poClass->IsSchemaLocked() )
     721             126 :         poClass->GetProperty( iProperty )->AnalysePropertyValue(pszValue);
     722                 : }
     723                 : 
     724                 : /************************************************************************/
     725                 : /*                            LoadClasses()                             */
     726                 : /************************************************************************/
     727                 : 
     728               4 : int GMLReader::LoadClasses( const char *pszFile )
     729                 : 
     730                 : {
     731                 :     // Add logic later to determine reasonable default schema file. 
     732               4 :     if( pszFile == NULL )
     733               0 :         return FALSE;
     734                 : 
     735                 : /* -------------------------------------------------------------------- */
     736                 : /*      Load the raw XML file.                                          */
     737                 : /* -------------------------------------------------------------------- */
     738                 :     FILE       *fp;
     739                 :     int         nLength;
     740                 :     char        *pszWholeText;
     741                 : 
     742               4 :     fp = VSIFOpen( pszFile, "rb" );
     743                 : 
     744               4 :     if( fp == NULL )
     745                 :     {
     746                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     747               0 :                   "Failed to open file %s.", pszFile );
     748               0 :         return FALSE;
     749                 :     }
     750                 : 
     751               4 :     VSIFSeek( fp, 0, SEEK_END );
     752               4 :     nLength = VSIFTell( fp );
     753               4 :     VSIFSeek( fp, 0, SEEK_SET );
     754                 : 
     755               4 :     pszWholeText = (char *) VSIMalloc(nLength+1);
     756               4 :     if( pszWholeText == NULL )
     757                 :     {
     758                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     759                 :                   "Failed to allocate %d byte buffer for %s,\n"
     760                 :                   "is this really a GMLFeatureClassList file?",
     761               0 :                   nLength, pszFile );
     762               0 :         VSIFClose( fp );
     763               0 :         return FALSE;
     764                 :     }
     765                 :     
     766               4 :     if( VSIFRead( pszWholeText, nLength, 1, fp ) != 1 )
     767                 :     {
     768               0 :         VSIFree( pszWholeText );
     769               0 :         VSIFClose( fp );
     770                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     771               0 :                   "Read failed on %s.", pszFile );
     772               0 :         return FALSE;
     773                 :     }
     774               4 :     pszWholeText[nLength] = '\0';
     775                 : 
     776               4 :     VSIFClose( fp );
     777                 : 
     778               4 :     if( strstr( pszWholeText, "<GMLFeatureClassList>" ) == NULL )
     779                 :     {
     780               0 :         VSIFree( pszWholeText );
     781                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     782                 :                   "File %s does not contain a GMLFeatureClassList tree.",
     783               0 :                   pszFile );
     784               0 :         return FALSE;
     785                 :     }
     786                 : 
     787                 : /* -------------------------------------------------------------------- */
     788                 : /*      Convert to XML parse tree.                                      */
     789                 : /* -------------------------------------------------------------------- */
     790                 :     CPLXMLNode *psRoot;
     791                 : 
     792               4 :     psRoot = CPLParseXMLString( pszWholeText );
     793               4 :     VSIFree( pszWholeText );
     794                 : 
     795                 :     // We assume parser will report errors via CPL.
     796               4 :     if( psRoot == NULL )
     797               0 :         return FALSE;
     798                 : 
     799               4 :     if( psRoot->eType != CXT_Element 
     800                 :         || !EQUAL(psRoot->pszValue,"GMLFeatureClassList") )
     801                 :     {
     802               0 :         CPLDestroyXMLNode(psRoot);
     803                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     804                 :                   "File %s is not a GMLFeatureClassList document.",
     805               0 :                   pszFile );
     806               0 :         return FALSE;
     807                 :     }
     808                 : 
     809                 : /* -------------------------------------------------------------------- */
     810                 : /*      Extract feature classes for all definitions found.              */
     811                 : /* -------------------------------------------------------------------- */
     812                 :     CPLXMLNode *psThis;
     813                 : 
     814               8 :     for( psThis = psRoot->psChild; psThis != NULL; psThis = psThis->psNext )
     815                 :     {
     816               4 :         if( psThis->eType == CXT_Element 
     817                 :             && EQUAL(psThis->pszValue,"GMLFeatureClass") )
     818                 :         {
     819                 :             GMLFeatureClass   *poClass;
     820                 : 
     821               4 :             poClass = new GMLFeatureClass();
     822                 : 
     823               4 :             if( !poClass->InitializeFromXML( psThis ) )
     824                 :             {
     825               0 :                 delete poClass;
     826               0 :                 CPLDestroyXMLNode( psRoot );
     827               0 :                 return FALSE;
     828                 :             }
     829                 : 
     830               4 :             poClass->SetSchemaLocked( TRUE );
     831                 : 
     832               4 :             AddClass( poClass );
     833                 :         }
     834                 :     }
     835                 : 
     836               4 :     CPLDestroyXMLNode( psRoot );
     837                 :     
     838               4 :     SetClassListLocked( TRUE );
     839                 : 
     840               4 :     return TRUE;
     841                 : }
     842                 : 
     843                 : /************************************************************************/
     844                 : /*                            SaveClasses()                             */
     845                 : /************************************************************************/
     846                 : 
     847               7 : int GMLReader::SaveClasses( const char *pszFile )
     848                 : 
     849                 : {
     850                 :     // Add logic later to determine reasonable default schema file. 
     851               7 :     if( pszFile == NULL )
     852               0 :         return FALSE;
     853                 : 
     854                 : /* -------------------------------------------------------------------- */
     855                 : /*      Create in memory schema tree.                                   */
     856                 : /* -------------------------------------------------------------------- */
     857                 :     CPLXMLNode *psRoot;
     858                 : 
     859               7 :     psRoot = CPLCreateXMLNode( NULL, CXT_Element, "GMLFeatureClassList" );
     860                 : 
     861              15 :     for( int iClass = 0; iClass < GetClassCount(); iClass++ )
     862                 :     {
     863               8 :         GMLFeatureClass *poClass = GetClass( iClass );
     864                 :         
     865               8 :         CPLAddXMLChild( psRoot, poClass->SerializeToXML() );
     866                 :     }
     867                 : 
     868                 : /* -------------------------------------------------------------------- */
     869                 : /*      Serialize to disk.                                              */
     870                 : /* -------------------------------------------------------------------- */
     871                 :     FILE        *fp;
     872               7 :     int         bSuccess = TRUE;
     873               7 :     char        *pszWholeText = CPLSerializeXMLTree( psRoot );
     874                 :     
     875               7 :     CPLDestroyXMLNode( psRoot );
     876                 :  
     877               7 :     fp = VSIFOpen( pszFile, "wb" );
     878                 :     
     879               7 :     if( fp == NULL )
     880               0 :         bSuccess = FALSE;
     881               7 :     else if( VSIFWrite( pszWholeText, strlen(pszWholeText), 1, fp ) != 1 )
     882               0 :         bSuccess = FALSE;
     883                 :     else
     884               7 :         VSIFClose( fp );
     885                 : 
     886               7 :     CPLFree( pszWholeText );
     887                 : 
     888               7 :     return bSuccess;
     889                 : }
     890                 : 
     891                 : /************************************************************************/
     892                 : /*                          PrescanForSchema()                          */
     893                 : /*                                                                      */
     894                 : /*      For now we use a pretty dumb approach of just doing a normal    */
     895                 : /*      scan of the whole file, building up the schema information.     */
     896                 : /*      Eventually we hope to do a more efficient scan when just        */
     897                 : /*      looking for schema information.                                 */
     898                 : /************************************************************************/
     899                 : 
     900              10 : int GMLReader::PrescanForSchema( int bGetExtents )
     901                 : 
     902                 : {
     903                 :     GMLFeature  *poFeature;
     904                 : 
     905              10 :     if( m_pszFilename == NULL )
     906               0 :         return FALSE;
     907                 : 
     908              10 :     SetClassListLocked( FALSE );
     909                 : 
     910              10 :     ClearClasses();
     911              10 :     if( !SetupParser() )
     912               0 :         return FALSE;
     913                 : 
     914              42 :     while( (poFeature = NextFeature()) != NULL )
     915                 :     {
     916              22 :         GMLFeatureClass *poClass = poFeature->GetClass();
     917                 : 
     918              22 :         if( poClass->GetFeatureCount() == -1 )
     919               8 :             poClass->SetFeatureCount( 1 );
     920                 :         else
     921              14 :             poClass->SetFeatureCount( poClass->GetFeatureCount() + 1 );
     922                 : 
     923                 : #ifdef SUPPORT_GEOMETRY
     924              22 :         if( bGetExtents )
     925                 :         {
     926              22 :             OGRGeometry *poGeometry = NULL;
     927                 : 
     928              22 :             if( poFeature->GetGeometry() != NULL 
     929                 :                 && strlen(poFeature->GetGeometry()) != 0 )
     930                 :             {
     931                 :                 poGeometry = OGRGeometryFactory::createFromGML( 
     932              22 :                     poFeature->GetGeometry() );
     933                 :             }
     934                 : 
     935              22 :             if( poGeometry != NULL )
     936                 :             {
     937                 :                 double  dfXMin, dfXMax, dfYMin, dfYMax;
     938              22 :                 OGREnvelope sEnvelope;
     939                 : 
     940              22 :                 poGeometry->getEnvelope( &sEnvelope );
     941              22 :                 delete poGeometry;
     942              22 :                 if( poClass->GetExtents(&dfXMin, &dfXMax, &dfYMin, &dfYMax) )
     943                 :                 {
     944              14 :                     dfXMin = MIN(dfXMin,sEnvelope.MinX);
     945              14 :                     dfXMax = MAX(dfXMax,sEnvelope.MaxX);
     946              14 :                     dfYMin = MIN(dfYMin,sEnvelope.MinY);
     947              14 :                     dfYMax = MAX(dfYMax,sEnvelope.MaxY);
     948                 :                 }
     949                 :                 else
     950                 :                 {
     951               8 :                     dfXMin = sEnvelope.MinX;
     952               8 :                     dfXMax = sEnvelope.MaxX;
     953               8 :                     dfYMin = sEnvelope.MinY;
     954               8 :                     dfYMax = sEnvelope.MaxY;
     955                 :                 }
     956                 : 
     957              22 :                 poClass->SetExtents( dfXMin, dfXMax, dfYMin, dfYMax );
     958                 :             }
     959                 : #endif /* def SUPPORT_GEOMETRY */
     960                 :         }
     961                 :         
     962              22 :         delete poFeature;
     963                 :     }
     964                 : 
     965              10 :     CleanupParser();
     966                 : 
     967              10 :     return GetClassCount() > 0;
     968                 : }
     969                 : 
     970                 : /************************************************************************/
     971                 : /*                            ResetReading()                            */
     972                 : /************************************************************************/
     973                 : 
     974              16 : void GMLReader::ResetReading()
     975                 : 
     976                 : {
     977              16 :     CleanupParser();
     978              16 : }
     979                 : 
     980                 : #endif /* HAVE_XERCES == 1 or HAVE_EXPAT */
     981                 : 

Generated by: LCOV version 1.7