LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/nas - nashandler.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 209 184 88.0 %
Date: 2012-12-26 Functions: 11 7 63.6 %

       1                 : /**********************************************************************
       2                 :  * $Id: nashandler.cpp 25170 2012-10-21 20:02:05Z rouault $
       3                 :  *
       4                 :  * Project:  NAS Reader
       5                 :  * Purpose:  Implementation of NASHandler 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 <ctype.h>
      31                 : #include "nasreaderp.h"
      32                 : #include "cpl_conv.h"
      33                 : #include "cpl_string.h"
      34                 : 
      35                 : #define MAX_TOKEN_SIZE  1000
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                             NASHandler()                             */
      39                 : /************************************************************************/
      40                 : 
      41               9 : NASHandler::NASHandler( NASReader *poReader )
      42                 : 
      43                 : {
      44               9 :     m_poReader = poReader;
      45               9 :     m_pszCurField = NULL;
      46               9 :     m_pszGeometry = NULL;
      47               9 :     m_nGeomAlloc = m_nGeomLen = 0;
      48               9 :     m_nDepthFeature = m_nDepthElement = m_nDepth = 0;
      49               9 :     m_bIgnoreFeature = FALSE;
      50               9 : }
      51                 : 
      52                 : /************************************************************************/
      53                 : /*                            ~NASHandler()                             */
      54                 : /************************************************************************/
      55                 : 
      56               9 : NASHandler::~NASHandler()
      57                 : 
      58                 : {
      59               9 :     CPLFree( m_pszCurField );
      60               9 :     CPLFree( m_pszGeometry );
      61               9 : }
      62                 : 
      63                 : /************************************************************************/
      64                 : /*                        GetAttributes()                               */
      65                 : /************************************************************************/
      66                 : 
      67          449744 : CPLString NASHandler::GetAttributes(const Attributes* attrs)
      68                 : {
      69          449744 :     CPLString osRes;
      70                 :     char *pszString;
      71                 : 
      72          459649 :     for(unsigned int i=0; i < attrs->getLength(); i++)
      73                 :     {
      74            9905 :         osRes += " ";
      75            9905 :         pszString = tr_strdup(attrs->getQName(i));
      76            9905 :         osRes += pszString;
      77            9905 :         CPLFree( pszString );
      78            9905 :         osRes += "=\"";
      79            9905 :         pszString = tr_strdup(attrs->getValue(i));
      80            9905 :         osRes += pszString;
      81            9905 :         CPLFree( pszString );
      82            9905 :         osRes += "\"";
      83                 :     }
      84               0 :     return osRes;
      85                 : }
      86                 : 
      87                 : 
      88                 : /************************************************************************/
      89                 : /*                            startElement()                            */
      90                 : /************************************************************************/
      91                 : 
      92         2235313 : void NASHandler::startElement(const XMLCh* const    uri,
      93                 :                               const XMLCh* const    localname,
      94                 :                               const XMLCh* const    qname,
      95                 :                               const Attributes& attrs )
      96                 : 
      97                 : {
      98                 :     char        szElementName[MAX_TOKEN_SIZE];
      99         2235313 :     GMLReadState *poState = m_poReader->GetState();
     100         2235313 :     const char *pszLast = NULL;
     101                 : 
     102         2235313 :     tr_strcpy( szElementName, localname );
     103                 : 
     104         2235313 :     if ( ( m_bIgnoreFeature && m_nDepth >= m_nDepthFeature ) ||
     105                 :          ( m_osIgnoredElement != "" && m_nDepth >= m_nDepthElement ) )
     106                 :     {
     107         1563631 :         m_nDepth ++;
     108         1563631 :         return;
     109                 :     }
     110                 : 
     111                 :     // ignore attributes of external references and "objektkoordinaten"
     112                 :     // (see PostNAS #3 and #15)
     113          671682 :     if ( EQUAL( szElementName, "zeigtAufExternes" ) ||
     114                 :          EQUAL( szElementName, "objektkoordinaten" ) )
     115                 :     {
     116             339 :         m_osIgnoredElement = szElementName;
     117             339 :         m_nDepthElement    = m_nDepth;
     118             339 :         m_nDepth ++;
     119                 : 
     120             339 :         return;
     121                 :     }
     122                 : 
     123                 : #ifdef DEBUG_VERBOSE
     124                 :     CPLDebug("NAS",
     125                 :               "%*sstartElement %s m_bIgnoreFeature:%d depth:%d depthFeature:%d featureClass:%s",
     126                 :               m_nDepth, "", szElementName,
     127                 :               m_bIgnoreFeature, m_nDepth, m_nDepthFeature,
     128                 :               poState->m_poFeature ? poState->m_poFeature->GetClass()->GetElementName() : "(no feature)"
     129                 :             );
     130                 : #endif
     131                 : 
     132                 : /* -------------------------------------------------------------------- */
     133                 : /*      If we are in the midst of collecting a feature attribute        */
     134                 : /*      value, then this must be a complex attribute which we don't     */
     135                 : /*      try to collect for now, so just terminate the field             */
     136                 : /*      collection.                                                     */
     137                 : /* -------------------------------------------------------------------- */
     138          671343 :     if( m_pszCurField != NULL )
     139                 :     {
     140              26 :         CPLFree( m_pszCurField );
     141              26 :         m_pszCurField = NULL;
     142                 :     }
     143                 : 
     144                 : /* -------------------------------------------------------------------- */
     145                 : /*      If we are collecting geometry, or if we determine this is a     */
     146                 : /*      geometry element then append to the geometry info.              */
     147                 : /* -------------------------------------------------------------------- */
     148          671343 :     if( m_pszGeometry != NULL
     149                 :         || IsGeometryElement( szElementName ) )
     150                 :     {
     151          449744 :         int nLNLen = tr_strlen( localname );
     152          449744 :         CPLString osAttributes = GetAttributes( &attrs );
     153                 : 
     154                 :         /* should save attributes too! */
     155                 : 
     156          449744 :         if( m_pszGeometry == NULL )
     157            6684 :             m_nGeometryDepth = poState->m_nPathLength;
     158                 : 
     159          449744 :         if( m_nGeomLen + nLNLen + 4 + (int)osAttributes.size() > m_nGeomAlloc )
     160                 :         {
     161            6684 :             m_nGeomAlloc = (int) (m_nGeomAlloc * 1.3 + nLNLen + osAttributes.size() + 1000);
     162                 :             m_pszGeometry = (char *)
     163            6684 :                 CPLRealloc( m_pszGeometry, m_nGeomAlloc);
     164                 :         }
     165                 : 
     166          449744 :         strcpy( m_pszGeometry+m_nGeomLen, "<" );
     167          449744 :         tr_strcpy( m_pszGeometry+m_nGeomLen+1, localname );
     168                 : 
     169          449744 :         if( osAttributes.size() > 0 )
     170                 :         {
     171            9572 :             strcat( m_pszGeometry+m_nGeomLen, " " );
     172            9572 :             strcat( m_pszGeometry+m_nGeomLen, osAttributes );
     173                 :         }
     174                 : 
     175          449744 :         strcat( m_pszGeometry+m_nGeomLen, ">" );
     176          449744 :         m_nGeomLen += strlen(m_pszGeometry+m_nGeomLen);
     177                 :     }
     178                 : 
     179                 : /* -------------------------------------------------------------------- */
     180                 : /*      Is this the ogc:Filter element in a wfs:Delete or               */
     181                 : /*      wfsext:Replace operation?  If so we translate it as a           */
     182                 : /*      specialized sort of feature.                                    */
     183                 : /* -------------------------------------------------------------------- */
     184          221599 :     else if( EQUAL(szElementName,"Filter")
     185                 :              && (pszLast = m_poReader->GetState()->GetLastComponent()) != NULL
     186                 :              && (EQUAL(pszLast,"Delete") || EQUAL(pszLast,"Replace")) )
     187                 :     {
     188               6 :         const char* pszFilteredClassName = m_poReader->GetFilteredClassName();
     189               6 :         if ( pszFilteredClassName != NULL &&
     190                 :              strcmp("Delete", pszFilteredClassName) != 0 )
     191                 :         {
     192               0 :             m_bIgnoreFeature = TRUE;
     193               0 :             m_nDepthFeature = m_nDepth;
     194               0 :             m_nDepth ++;
     195                 : 
     196               0 :             return;
     197                 :         }
     198                 : 
     199               6 :         m_bIgnoreFeature = FALSE;
     200                 : 
     201               6 :         m_poReader->PushFeature( "Delete", attrs );
     202                 : 
     203               6 :         m_nDepthFeature = m_nDepth;
     204               6 :         m_nDepth ++;
     205                 : 
     206               6 :         CPLAssert( m_osLastTypeName != "" );
     207               6 :         m_poReader->SetFeaturePropertyDirectly( "typeName", CPLStrdup(m_osLastTypeName) );
     208               6 :         m_poReader->SetFeaturePropertyDirectly( "context", CPLStrdup(pszLast) );
     209                 : 
     210               6 :         if( EQUAL( pszLast, "Replace" ) )
     211                 :         {
     212               2 :             CPLAssert( m_osLastReplacingFID != "" );
     213               2 :             CPLAssert( m_osLastSafeToIgnore != "" );
     214               2 :             m_poReader->SetFeaturePropertyDirectly( "replacedBy", CPLStrdup(m_osLastReplacingFID) );
     215               2 :             m_poReader->SetFeaturePropertyDirectly( "safeToIgnore", CPLStrdup(m_osLastSafeToIgnore) );
     216                 :         }
     217                 : 
     218               6 :         return;
     219                 :     }
     220                 : 
     221                 : /* -------------------------------------------------------------------- */
     222                 : /*      Is it a feature?  If so push a whole new state, and return.     */
     223                 : /* -------------------------------------------------------------------- */
     224          221593 :     else if( m_poReader->IsFeatureElement( szElementName ) )
     225                 :     {
     226           69646 :         m_osLastTypeName = szElementName;
     227                 : 
     228           69646 :         const char* pszFilteredClassName = m_poReader->GetFilteredClassName();
     229                 : 
     230           69646 :         pszLast = m_poReader->GetState()->GetLastComponent();
     231          139292 :         if( pszLast != NULL && EQUAL(pszLast,"Replace") )
     232                 :         {
     233                 :             int nIndex;
     234                 :             XMLCh  Name[100];
     235                 : 
     236               3 :             tr_strcpy( Name, "gml:id" );
     237               3 :             nIndex = attrs.getIndex( Name );
     238                 : 
     239               3 :             CPLAssert( nIndex!=-1 );
     240               3 :             CPLAssert( m_osLastReplacingFID=="" );
     241                 : 
     242                 :             // Capture "gml:id" attribute as part of the property value -
     243                 :             // primarily this is for the wfsext:Replace operation's attribute.
     244               3 :             char *pszReplacingFID = tr_strdup( attrs.getValue( nIndex ) );
     245               3 :             m_osLastReplacingFID = pszReplacingFID;
     246               3 :             CPLFree( pszReplacingFID );
     247                 : 
     248                 : #ifdef DEBUG_VERBOSE
     249                 :             CPLDebug("NAS", "%*s### Replace typeName=%s replacedBy=%s", m_nDepth, "", m_osLastTypeName.c_str(), m_osLastReplacingFID.c_str() );
     250                 : #endif
     251                 :         }
     252                 : 
     253           69646 :         if ( pszFilteredClassName != NULL &&
     254                 :              strcmp(szElementName, pszFilteredClassName) != 0 )
     255                 :         {
     256           60918 :             m_bIgnoreFeature = TRUE;
     257           60918 :             m_nDepthFeature = m_nDepth;
     258           60918 :             m_nDepth ++;
     259                 : 
     260           60918 :             return;
     261                 :         }
     262                 : 
     263            8728 :         m_bIgnoreFeature = FALSE;
     264                 : 
     265            8728 :         m_poReader->PushFeature( szElementName, attrs );
     266                 : 
     267            8728 :         m_nDepthFeature = m_nDepth;
     268            8728 :         m_nDepth ++;
     269                 : 
     270            8728 :         return;
     271                 :     }
     272                 : 
     273                 : /* -------------------------------------------------------------------- */
     274                 : /*      If it is the wfs:Delete element, then remember the typeName     */
     275                 : /*      attribute so we can assign it to the feature that will be       */
     276                 : /*      produced when we process the Filter element.                    */
     277                 : /* -------------------------------------------------------------------- */
     278          151947 :     else if( EQUAL(szElementName,"Delete") )
     279                 :     {
     280                 :         int nIndex;
     281                 :         XMLCh  Name[100];
     282                 : 
     283               4 :         tr_strcpy( Name, "typeName" );
     284               4 :         nIndex = attrs.getIndex( Name );
     285                 : 
     286               4 :         if( nIndex != -1 )
     287                 :         {
     288               4 :             char *pszTypeName = tr_strdup( attrs.getValue( nIndex ) );
     289               4 :             m_osLastTypeName = pszTypeName;
     290               4 :             CPLFree( pszTypeName );
     291                 :         }
     292                 : 
     293               4 :         m_osLastSafeToIgnore = "";
     294               8 :         m_osLastReplacingFID = "";
     295                 :     }
     296                 : 
     297                 : /* -------------------------------------------------------------------- */
     298                 : /*      If it is the wfsext:Replace element, then remember the          */
     299                 : /*      safeToIgnore attribute so we can assign it to the feature       */
     300                 : /*      that will be produced when we process the Filter element.       */
     301                 : /* -------------------------------------------------------------------- */
     302          151943 :     else if( EQUAL(szElementName,"Replace") )
     303                 :     {
     304                 :         int nIndex;
     305                 :         XMLCh  Name[100];
     306                 : 
     307               3 :         tr_strcpy( Name, "safeToIgnore" );
     308               3 :         nIndex = attrs.getIndex( Name );
     309                 : 
     310               3 :         if( nIndex != -1 )
     311                 :         {
     312               3 :             char *pszSafeToIgnore = tr_strdup( attrs.getValue( nIndex ) );
     313               3 :             m_osLastSafeToIgnore = pszSafeToIgnore;
     314               3 :             CPLFree( pszSafeToIgnore );
     315                 :         }
     316                 :         else
     317                 :         {
     318               0 :             CPLError( CE_Warning, CPLE_AppDefined, "NAS: safeToIgnore attribute missing" );
     319               0 :             m_osLastSafeToIgnore = "false";
     320                 :         }
     321                 : 
     322               3 :         m_osLastReplacingFID = "";
     323                 :     }
     324                 : 
     325                 : /* -------------------------------------------------------------------- */
     326                 : /*      If it is (or at least potentially is) a simple attribute,       */
     327                 : /*      then start collecting it.                                       */
     328                 : /* -------------------------------------------------------------------- */
     329          151940 :     else if( m_poReader->IsAttributeElement( szElementName ) )
     330                 :     {
     331           37877 :         CPLFree( m_pszCurField );
     332           37877 :         m_pszCurField = CPLStrdup("");
     333                 : 
     334                 :         // Capture href as OB property.
     335           37877 :         m_poReader->CheckForRelations( szElementName, attrs );
     336                 : 
     337                 :         // Capture "fid" attribute as part of the property value -
     338                 :         // primarily this is for wfs:Delete operation's FeatureId attribute.
     339           37877 :         if( EQUAL(szElementName,"FeatureId") )
     340               6 :             m_poReader->CheckForFID( attrs, &m_pszCurField );
     341                 :     }
     342                 : 
     343                 : /* -------------------------------------------------------------------- */
     344                 : /*      Push the element onto the current state's path.                 */
     345                 : /* -------------------------------------------------------------------- */
     346          601691 :     poState->PushPath( szElementName );
     347                 : 
     348          601691 :     m_nDepth ++;
     349                 : }
     350                 : 
     351                 : /************************************************************************/
     352                 : /*                             endElement()                             */
     353                 : /************************************************************************/
     354         2235294 : void NASHandler::endElement(const   XMLCh* const    uri,
     355                 :                             const   XMLCh* const    localname,
     356                 :                             const   XMLCh* const    qname )
     357                 : 
     358                 : {
     359                 :     char        szElementName[MAX_TOKEN_SIZE];
     360         2235294 :     GMLReadState *poState = m_poReader->GetState();
     361                 : 
     362         2235294 :     tr_strcpy( szElementName, localname );
     363                 : 
     364                 : 
     365         2235294 :     m_nDepth --;
     366                 : 
     367         2235294 :     if (m_bIgnoreFeature && m_nDepth >= m_nDepthFeature)
     368                 :     {
     369         1622854 :         if (m_nDepth == m_nDepthFeature)
     370                 :         {
     371           60918 :             m_bIgnoreFeature = FALSE;
     372           60918 :             m_nDepthFeature = 0;
     373                 :         }
     374         1622854 :         return;
     375                 :     }
     376                 : 
     377          612440 :     if ( m_osIgnoredElement != "" && m_nDepth >= m_nDepthElement )
     378                 :     {
     379            2034 :         if ( m_nDepth == m_nDepthElement )
     380                 :         {
     381             339 :             m_osIgnoredElement = "";
     382             339 :             m_nDepthElement    = 0;
     383                 :         }
     384            2034 :         return;
     385                 :     }
     386                 : 
     387                 : #ifdef DEBUG_VERBOSE
     388                 :     CPLDebug("NAS",
     389                 :               "%*sendElement %s m_bIgnoreFeature:%d depth:%d depthFeature:%d featureClass:%s",
     390                 :               m_nDepth, "", szElementName,
     391                 :               m_bIgnoreFeature, m_nDepth, m_nDepthFeature,
     392                 :               poState->m_poFeature ? poState->m_poFeature->GetClass()->GetElementName() : "(no feature)"
     393                 :             );
     394                 : #endif
     395                 : 
     396                 : /* -------------------------------------------------------------------- */
     397                 : /*      Is this closing off an attribute value?  We assume so if        */
     398                 : /*      we are collecting an attribute value and got to this point.     */
     399                 : /*      We don't bother validating that the closing tag matches the     */
     400                 : /*      opening tag.                                                    */
     401                 : /* -------------------------------------------------------------------- */
     402          610406 :     if( m_pszCurField != NULL )
     403                 :     {
     404           37851 :         CPLAssert( poState->m_poFeature != NULL );
     405                 : 
     406           37851 :         m_poReader->SetFeaturePropertyDirectly( poState->osPath.c_str(), m_pszCurField );
     407           37851 :         m_pszCurField = NULL;
     408                 :     }
     409                 : 
     410                 : /* -------------------------------------------------------------------- */
     411                 : /*      If we are collecting Geometry than store it, and consider if    */
     412                 : /*      this is the end of the geometry.                                */
     413                 : /* -------------------------------------------------------------------- */
     414          610406 :     if( m_pszGeometry != NULL )
     415                 :     {
     416          449744 :         int nLNLen = tr_strlen( localname );
     417                 : 
     418                 :         /* should save attributes too! */
     419                 : 
     420          449744 :         if( m_nGeomLen + nLNLen + 4 > m_nGeomAlloc )
     421                 :         {
     422               0 :             m_nGeomAlloc = (int) (m_nGeomAlloc * 1.3 + nLNLen + 1000);
     423                 :             m_pszGeometry = (char *)
     424               0 :                 CPLRealloc( m_pszGeometry, m_nGeomAlloc);
     425                 :         }
     426                 : 
     427          449744 :         strcat( m_pszGeometry+m_nGeomLen, "</" );
     428          449744 :         tr_strcpy( m_pszGeometry+m_nGeomLen+2, localname );
     429          449744 :         strcat( m_pszGeometry+m_nGeomLen+nLNLen+2, ">" );
     430          449744 :         m_nGeomLen += strlen(m_pszGeometry+m_nGeomLen);
     431                 : 
     432          449744 :         if( poState->m_nPathLength == m_nGeometryDepth+1 )
     433                 :         {
     434            6684 :             if( poState->m_poFeature != NULL )
     435                 :             {
     436            6684 :                 CPLXMLNode* psNode = CPLParseXMLString(m_pszGeometry);
     437            6684 :                 if (psNode)
     438                 :                 {
     439                 :                     /* workaround common malformed gml:pos with just a
     440                 :                      * elevation value instead of a full 3D coordinate:
     441                 :                      *
     442                 :                      * <gml:Point gml:id="BII2H">
     443                 :                      *    <gml:pos srsName="urn:adv:crs:ETRS89_h">41.394</gml:pos>
     444                 :                      * </gml:Point>
     445                 :                      *
     446                 :                      */
     447                 :                     const char *pszPos;
     448            6684 :                     if( (pszPos = CPLGetXMLValue( psNode, "=Point.pos", NULL ) ) != NULL
     449                 :                         && strstr(pszPos, " ") == NULL )
     450                 :                     {
     451               0 :                         CPLSetXMLValue( psNode, "pos", CPLSPrintf("0 0 %s", pszPos) );
     452                 :                     }
     453                 : 
     454           13368 :                     if ( poState->m_poFeature->GetGeometryList() &&
     455            6684 :                          poState->m_poFeature->GetGeometryList()[0] )
     456                 :                     {
     457               0 :                         int iId = poState->m_poFeature->GetClass()->GetPropertyIndex( "gml_id" );
     458               0 :                         const GMLProperty *poIdProp = poState->m_poFeature->GetProperty(iId);
     459                 : #if DEBUG_VERBOSE
     460                 :                         char *pszOldGeom = CPLSerializeXMLTree( poState->m_poFeature->GetGeometryList()[0] );
     461                 : 
     462                 :                         CPLDebug("NAS", "Overwriting other geometry (%s; replace:%s; with:%s)",
     463                 :                                  poIdProp && poIdProp->nSubProperties>0 && poIdProp->papszSubProperties[0] ? poIdProp->papszSubProperties[0] : "(null)",
     464                 :                                  m_pszGeometry,
     465                 :                                  pszOldGeom
     466                 :                                 );
     467                 : 
     468                 :                         CPLFree( pszOldGeom );
     469                 : #else
     470                 :                 CPLError( CE_Warning, CPLE_AppDefined, "NAS: Overwriting other geometry (%s)",
     471               0 :                                  poIdProp && poIdProp->nSubProperties>0 && poIdProp->papszSubProperties[0] ? poIdProp->papszSubProperties[0] : "(null)" );
     472                 : #endif
     473                 :                     }
     474                 : 
     475            6684 :                     poState->m_poFeature->SetGeometryDirectly( psNode );
     476                 :                 }
     477                 :                 else
     478               0 :                     CPLError( CE_Warning, CPLE_AppDefined, "NAS: Invalid geometry skipped" );
     479                 :             }
     480                 :             else
     481               0 :                 CPLError( CE_Warning, CPLE_AppDefined, "NAS: Skipping geometry without feature" );
     482                 : 
     483            6684 :             CPLFree( m_pszGeometry );
     484            6684 :             m_pszGeometry = NULL;
     485            6684 :             m_nGeomAlloc = m_nGeomLen = 0;
     486                 :         }
     487                 :     }
     488                 : 
     489                 : /* -------------------------------------------------------------------- */
     490                 : /*      If we are collecting a feature, and this element tag matches    */
     491                 : /*      element name for the class, then we have finished the           */
     492                 : /*      feature, and we pop the feature read state.                     */
     493                 : /* -------------------------------------------------------------------- */
     494          610406 :     if( m_nDepth == m_nDepthFeature && poState->m_poFeature != NULL
     495                 :         && EQUAL(szElementName,
     496                 :                  poState->m_poFeature->GetClass()->GetElementName()) )
     497                 :     {
     498            8728 :         m_nDepthFeature = 0;
     499            8728 :         m_poReader->PopState();
     500                 :     }
     501                 : 
     502                 : /* -------------------------------------------------------------------- */
     503                 : /*      Ends of a wfs:Delete should be triggered on the close of the    */
     504                 : /*      <Filter> element.                                               */
     505                 : /* -------------------------------------------------------------------- */
     506          601678 :     else if( m_nDepth == m_nDepthFeature
     507                 :              && poState->m_poFeature != NULL
     508                 :              && EQUAL(szElementName,"Filter")
     509                 :              && EQUAL(poState->m_poFeature->GetClass()->GetElementName(),
     510                 :                       "Delete") )
     511                 :     {
     512               6 :         m_nDepthFeature = 0;
     513               6 :         m_poReader->PopState();
     514                 :     }
     515                 : 
     516                 : /* -------------------------------------------------------------------- */
     517                 : /*      Otherwise, we just pop the element off the local read states    */
     518                 : /*      element stack.                                                  */
     519                 : /* -------------------------------------------------------------------- */
     520                 :     else
     521                 :     {
     522          601672 :         if( EQUAL(szElementName,poState->GetLastComponent()) )
     523          601672 :             poState->PopPath();
     524                 :         else
     525                 :         {
     526               0 :             CPLAssert( FALSE );
     527                 :         }
     528                 :     }
     529                 : }
     530                 : 
     531                 : /************************************************************************/
     532                 : /*                             characters()                             */
     533                 : /************************************************************************/
     534                 : 
     535                 : #if XERCES_VERSION_MAJOR >= 3
     536                 : void NASHandler::characters( const XMLCh *const chars_in,
     537                 :                              const XMLSize_t length )
     538                 : #else
     539         4417187 : void NASHandler::characters(const XMLCh* const chars_in,
     540                 :                             const unsigned int length )
     541                 : #endif
     542                 : 
     543                 : {
     544         4417187 :     const XMLCh *chars = chars_in;
     545                 : 
     546         4417187 :     if( m_pszCurField != NULL )
     547                 :     {
     548           35363 :         int     nCurFieldLength = strlen(m_pszCurField);
     549                 : 
     550           35363 :         if (nCurFieldLength == 0)
     551                 :         {
     552                 :             // Ignore white space
     553           70920 :             while( *chars == ' ' || *chars == 10 || *chars == 13 || *chars == '\t')
     554             194 :                 chars++;
     555                 :         }
     556                 : 
     557           35363 :         char *pszTranslated = tr_strdup(chars);
     558                 : 
     559           35363 :         if( m_pszCurField == NULL )
     560                 :         {
     561               0 :             m_pszCurField = pszTranslated;
     562               0 :             nCurFieldLength = strlen(m_pszCurField);
     563                 :         }
     564                 :         else
     565                 :         {
     566                 :             m_pszCurField = (char *)
     567                 :                 CPLRealloc( m_pszCurField,
     568           35363 :                             nCurFieldLength+strlen(pszTranslated)+1 );
     569           35363 :             strcpy( m_pszCurField + nCurFieldLength, pszTranslated );
     570           35363 :             CPLFree( pszTranslated );
     571                 :         }
     572                 :     }
     573         4381824 :     else if( m_pszGeometry != NULL )
     574                 :     {
     575          892804 :         if (m_nGeomLen == 0)
     576                 :         {
     577                 :             // Ignore white space
     578               0 :             while( *chars == ' ' || *chars == 10 || *chars == 13 || *chars == '\t')
     579               0 :                 chars++;
     580                 :         }
     581                 : 
     582          892804 :         int nCharsLen = tr_strlen(chars);
     583                 : 
     584          892804 :         if( m_nGeomLen + nCharsLen*4 + 4 > m_nGeomAlloc )
     585                 :         {
     586           11966 :             m_nGeomAlloc = (int) (m_nGeomAlloc * 1.3 + nCharsLen*4 + 1000);
     587                 :             m_pszGeometry = (char *)
     588           11966 :                 CPLRealloc( m_pszGeometry, m_nGeomAlloc);
     589                 :         }
     590                 : 
     591          892804 :         tr_strcpy( m_pszGeometry+m_nGeomLen, chars );
     592          892804 :         m_nGeomLen += strlen(m_pszGeometry+m_nGeomLen);
     593                 :     }
     594         4417187 : }
     595                 : 
     596                 : /************************************************************************/
     597                 : /*                             fatalError()                             */
     598                 : /************************************************************************/
     599                 : 
     600               0 : void NASHandler::fatalError( const SAXParseException &exception)
     601                 : 
     602                 : {
     603                 :     char *pszErrorMessage;
     604                 : 
     605               0 :     pszErrorMessage = tr_strdup( exception.getMessage() );
     606                 :     CPLError( CE_Failure, CPLE_AppDefined,
     607                 :               "XML Parsing Error: %s at line %d, column %d\n",
     608               0 :               pszErrorMessage, (int)exception.getLineNumber(), (int)exception.getColumnNumber() );
     609                 : 
     610               0 :     CPLFree( pszErrorMessage );
     611               0 : }
     612                 : 
     613                 : /************************************************************************/
     614                 : /*                         IsGeometryElement()                          */
     615                 : /************************************************************************/
     616                 : 
     617          228283 : int NASHandler::IsGeometryElement( const char *pszElement )
     618                 : 
     619                 : {
     620                 :     return strcmp(pszElement,"Polygon") == 0
     621                 :         || strcmp(pszElement,"MultiPolygon") == 0
     622                 :         || strcmp(pszElement,"MultiPoint") == 0
     623                 :         || strcmp(pszElement,"MultiLineString") == 0
     624                 :         || strcmp(pszElement,"MultiSurface") == 0
     625                 :         || strcmp(pszElement,"GeometryCollection") == 0
     626                 :         || strcmp(pszElement,"Point") == 0
     627                 :         || strcmp(pszElement,"Curve") == 0
     628                 :         || strcmp(pszElement,"MultiCurve") == 0
     629                 :         || strcmp(pszElement,"CompositeCurve") == 0
     630                 :         || strcmp(pszElement,"Surface") == 0
     631                 :         || strcmp(pszElement,"PolygonPatch") == 0
     632          228283 :         || strcmp(pszElement,"LineString") == 0;
     633                 : }

Generated by: LCOV version 1.7