LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/gml - parsexsd.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 217 162 74.7 %
Date: 2012-04-28 Functions: 6 6 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: parsexsd.cpp 23748 2012-01-12 23:34:27Z rouault $
       3                 :  *
       4                 :  * Project:  GML Reader
       5                 :  * Purpose:  Implementation of GMLParseXSD()
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2005, 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 "parsexsd.h"
      31                 : #include "cpl_error.h"
      32                 : #include "cpl_conv.h"
      33                 : #include "ogr_core.h"
      34                 : 
      35                 : /************************************************************************/
      36                 : /*                              StripNS()                               */
      37                 : /*                                                                      */
      38                 : /*      Return potentially shortened form of string with namespace      */
      39                 : /*      stripped off if there is one.  Returns pointer into             */
      40                 : /*      original string.                                                */
      41                 : /************************************************************************/
      42                 : 
      43            1572 : const char *StripNS( const char *pszFullValue )
      44                 : 
      45                 : {
      46            1572 :     const char *pszColon = strstr( pszFullValue, ":" );
      47            1572 :     if( pszColon == NULL )
      48             926 :         return pszFullValue;
      49                 :     else
      50             646 :         return pszColon + 1;
      51                 : }
      52                 : 
      53                 : /************************************************************************/
      54                 : /*                   GetSimpleTypeProperties()                          */
      55                 : /************************************************************************/
      56                 : 
      57                 : static
      58              70 : int GetSimpleTypeProperties(CPLXMLNode *psTypeNode,
      59                 :                             GMLPropertyType *pGMLType,
      60                 :                             int *pnWidth,
      61                 :                             int *pnPrecision)
      62                 : {
      63                 :     const char *pszBase =
      64                 :             StripNS( CPLGetXMLValue( psTypeNode,
      65              70 :                                         "restriction.base", "" ));
      66                 : 
      67              70 :     if( EQUAL(pszBase,"decimal") )
      68                 :     {
      69              24 :         *pGMLType = GMLPT_Real;
      70                 :         const char *pszWidth =
      71                 :             CPLGetXMLValue( psTypeNode,
      72              24 :                         "restriction.totalDigits.value", "0" );
      73                 :         const char *pszPrecision =
      74                 :             CPLGetXMLValue( psTypeNode,
      75              24 :                         "restriction.fractionDigits.value", "0" );
      76              24 :         *pnWidth = atoi(pszWidth);
      77              24 :         *pnPrecision = atoi(pszPrecision);
      78              24 :         return TRUE;
      79                 :     }
      80                 : 
      81              46 :     else if( EQUAL(pszBase,"float")
      82                 :                 || EQUAL(pszBase,"double") )
      83                 :     {
      84               0 :         *pGMLType = GMLPT_Real;
      85               0 :         return TRUE;
      86                 :     }
      87                 : 
      88              46 :     else if( EQUAL(pszBase,"integer") )
      89                 :     {
      90              16 :         *pGMLType = GMLPT_Integer;
      91                 :         const char *pszWidth =
      92                 :             CPLGetXMLValue( psTypeNode,
      93              16 :                         "restriction.totalDigits.value", "0" );
      94              16 :         *pnWidth = atoi(pszWidth);
      95              16 :         return TRUE;
      96                 :     }
      97                 : 
      98              30 :     else if( EQUAL(pszBase,"string") )
      99                 :     {
     100              30 :         *pGMLType = GMLPT_String;
     101                 :         const char *pszWidth =
     102                 :             CPLGetXMLValue( psTypeNode,
     103              30 :                         "restriction.maxLength.value", "0" );
     104              30 :         *pnWidth = atoi(pszWidth);
     105              30 :         return TRUE;
     106                 :     }
     107                 : 
     108                 :     /* TODO: Would be nice to have a proper date type */
     109               0 :     else if( EQUAL(pszBase,"date") ||
     110                 :              EQUAL(pszBase,"dateTime") )
     111                 :     {
     112               0 :         *pGMLType = GMLPT_String;
     113               0 :         return TRUE;
     114                 :     }
     115               0 :     return FALSE;
     116                 : }
     117                 : 
     118                 : /************************************************************************/
     119                 : /*                      LookForSimpleType()                             */
     120                 : /************************************************************************/
     121                 : 
     122                 : static
     123               2 : int LookForSimpleType(CPLXMLNode *psSchemaNode,
     124                 :                       const char* pszStrippedNSType,
     125                 :                       GMLPropertyType *pGMLType,
     126                 :                       int *pnWidth,
     127                 :                       int *pnPrecision)
     128                 : {
     129                 :     CPLXMLNode *psThis;
     130              20 :     for( psThis = psSchemaNode->psChild;
     131                 :          psThis != NULL; psThis = psThis->psNext )
     132                 :     {
     133              20 :         if( psThis->eType == CXT_Element
     134                 :            && EQUAL(psThis->pszValue,"simpleType")
     135                 :            && EQUAL(CPLGetXMLValue(psThis,"name",""),pszStrippedNSType) )
     136                 :         {
     137               2 :             break;
     138                 :         }
     139                 :     }
     140               2 :     if (psThis == NULL)
     141               0 :         return FALSE;
     142                 : 
     143               2 :     return GetSimpleTypeProperties(psThis, pGMLType, pnWidth, pnPrecision);
     144                 : }
     145                 : 
     146                 : /************************************************************************/
     147                 : /*                      ParseFeatureType()                              */
     148                 : /************************************************************************/
     149                 : 
     150                 : typedef struct
     151                 : {
     152                 :     const char* pszName;
     153                 :     OGRwkbGeometryType eType;
     154                 : } AssocNameType;
     155                 : 
     156                 : static const AssocNameType apsPropertyTypes [] =
     157                 : {
     158                 :     {"GeometryPropertyType", wkbUnknown},
     159                 :     {"PointPropertyType", wkbPoint},
     160                 :     {"LineStringPropertyType", wkbLineString},
     161                 :     {"CurvePropertyType", wkbLineString},
     162                 :     {"PolygonPropertyType", wkbPolygon},
     163                 :     {"SurfacePropertyType", wkbPolygon},
     164                 :     {"MultiPointPropertyType", wkbMultiPoint},
     165                 :     {"MultiLineStringPropertyType", wkbMultiLineString},
     166                 :     {"MultiCurvePropertyType", wkbMultiLineString},
     167                 :     {"MultiPolygonPropertyType", wkbMultiPolygon},
     168                 :     {"MultiSurfacePropertyType", wkbMultiPolygon},
     169                 :     {"MultiGeometryPropertyType", wkbGeometryCollection},
     170                 :     {NULL, wkbUnknown},
     171                 : };
     172                 : 
     173                 : /* Found in FME .xsd  (e.g. <element ref="gml:curveProperty" minOccurs="0"/>) */
     174                 : static const AssocNameType apsRefTypes [] =
     175                 : {
     176                 :     {"pointProperty", wkbPoint},
     177                 :     {"curveProperty", wkbLineString},
     178                 :     {"surfaceProperty", wkbPolygon},
     179                 :     {"multiPointProperty", wkbMultiPoint},
     180                 :     {"multiCurveProperty", wkbMultiLineString},
     181                 :     {"multiSurfaceProperty", wkbMultiPolygon},
     182                 :     {NULL, wkbUnknown},
     183                 : };
     184                 : 
     185                 : static
     186                 : GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
     187                 :                                      const char* pszName,
     188                 :                                      CPLXMLNode *psThis);
     189                 : 
     190                 : static
     191              92 : GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
     192                 :                                 const char* pszName,
     193                 :                                 const char *pszType)
     194                 : {
     195                 :     CPLXMLNode *psThis;
     196            1156 :     for( psThis = psSchemaNode->psChild;
     197                 :          psThis != NULL; psThis = psThis->psNext )
     198                 :     {
     199            1156 :         if( psThis->eType == CXT_Element
     200                 :            && EQUAL(psThis->pszValue,"complexType")
     201                 :            && EQUAL(CPLGetXMLValue(psThis,"name",""),pszType) )
     202                 :         {
     203              92 :             break;
     204                 :         }
     205                 :     }
     206              92 :     if (psThis == NULL)
     207               0 :         return NULL;
     208                 : 
     209              92 :     return GMLParseFeatureType(psSchemaNode, pszName, psThis);
     210                 : }
     211                 : 
     212                 : 
     213                 : static
     214             240 : GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
     215                 :                                      const char* pszName,
     216                 :                                      CPLXMLNode *psComplexType)
     217                 : {
     218                 : 
     219                 : /* -------------------------------------------------------------------- */
     220                 : /*      Grab the sequence of extensions greatgrandchild.                */
     221                 : /* -------------------------------------------------------------------- */
     222                 :     CPLXMLNode *psAttrSeq =
     223                 :         CPLGetXMLNode( psComplexType,
     224             240 :                         "complexContent.extension.sequence" );
     225                 : 
     226             240 :     if( psAttrSeq == NULL )
     227                 :     {
     228               0 :         return NULL;
     229                 :     }
     230                 : 
     231                 : /* -------------------------------------------------------------------- */
     232                 : /*      We are pretty sure this going to be a valid Feature class       */
     233                 : /*      now, so create it.                                              */
     234                 : /* -------------------------------------------------------------------- */
     235             240 :     GMLFeatureClass *poClass = new GMLFeatureClass( pszName );
     236                 : 
     237                 : /* -------------------------------------------------------------------- */
     238                 : /*      Loop over each of the attribute elements being defined for      */
     239                 : /*      this feature class.                                             */
     240                 : /* -------------------------------------------------------------------- */
     241                 :     CPLXMLNode *psAttrDef;
     242             240 :     int nAttributeIndex = 0;
     243                 : 
     244             240 :     int bGotUnrecognizedType = FALSE;
     245                 : 
     246            1568 :     for( psAttrDef = psAttrSeq->psChild;
     247                 :             psAttrDef != NULL;
     248                 :             psAttrDef = psAttrDef->psNext )
     249                 :     {
     250            1328 :         if( strcmp(psAttrDef->pszValue,"group") == 0 )
     251                 :         {
     252                 :             /* Too complex schema for us. Aborts parsing */
     253               0 :             delete poClass;
     254               0 :             return NULL;
     255                 :         }
     256                 : 
     257            1328 :         if( !EQUAL(psAttrDef->pszValue,"element") )
     258               0 :             continue;
     259                 : 
     260                 :         /* MapServer WFS writes element type as an attribute of element */
     261                 :         /* not as a simpleType definition */
     262            1328 :         const char* pszType = CPLGetXMLValue( psAttrDef, "type", NULL );
     263            1328 :         const char* pszElementName = CPLGetXMLValue( psAttrDef, "name", NULL );
     264            1328 :         if (pszType != NULL)
     265                 :         {
     266            1224 :             const char* pszStrippedNSType = StripNS(pszType);
     267            1224 :             int nWidth = 0, nPrecision = 0;
     268                 : 
     269            1224 :             GMLPropertyType gmlType = GMLPT_Untyped;
     270            1566 :             if (EQUAL(pszStrippedNSType, "string") ||
     271                 :                 EQUAL(pszStrippedNSType, "Character"))
     272             342 :                 gmlType = GMLPT_String;
     273                 :             /* TODO: Would be nice to have a proper date type */
     274             882 :             else if (EQUAL(pszStrippedNSType, "date") ||
     275                 :                      EQUAL(pszStrippedNSType, "dateTime"))
     276               0 :                 gmlType = GMLPT_String;
     277            1474 :             else if (EQUAL(pszStrippedNSType, "real") ||
     278                 :                      EQUAL(pszStrippedNSType, "double") ||
     279                 :                      EQUAL(pszStrippedNSType, "float") ||
     280                 :                      EQUAL(pszStrippedNSType, "decimal"))
     281             592 :                 gmlType = GMLPT_Real;
     282             358 :             else if (EQUAL(pszStrippedNSType, "short") ||
     283                 :                      EQUAL(pszStrippedNSType, "int") ||
     284                 :                      EQUAL(pszStrippedNSType, "integer") ||
     285                 :                      EQUAL(pszStrippedNSType, "long"))
     286              68 :                 gmlType = GMLPT_Integer;
     287             222 :             else if (strncmp(pszType, "gml:", 4) == 0)
     288                 :             {
     289             220 :                 const AssocNameType* psIter = apsPropertyTypes;
     290            1588 :                 while(psIter->pszName)
     291                 :                 {
     292            1368 :                     if (strncmp(pszType + 4, psIter->pszName, strlen(psIter->pszName)) == 0)
     293                 :                     {
     294             220 :                         if (poClass->GetGeometryAttributeIndex() != -1)
     295                 :                         {
     296               0 :                             CPLDebug("GML", "Geometry field already found ! Ignoring the following ones");
     297                 :                         }
     298                 :                         else
     299                 :                         {
     300             220 :                             poClass->SetGeometryElement(pszElementName);
     301             220 :                             poClass->SetGeometryType(psIter->eType);
     302             220 :                             poClass->SetGeometryAttributeIndex( nAttributeIndex );
     303                 : 
     304             220 :                             nAttributeIndex ++;
     305                 :                         }
     306                 :                         
     307             220 :                         break;
     308                 :                     }
     309                 : 
     310            1148 :                     psIter ++;
     311                 :                 }
     312                 : 
     313             220 :                 if (psIter->pszName == NULL)
     314                 :                 {
     315                 :                     /* Can be a non geometry gml type */
     316                 :                     /* Too complex schema for us. Aborts parsing */
     317               0 :                     delete poClass;
     318               0 :                     return NULL;
     319                 :                 }
     320                 : 
     321             220 :                 if (poClass->GetGeometryAttributeIndex() == -1)
     322               0 :                     bGotUnrecognizedType = TRUE;
     323                 : 
     324             220 :                 continue;
     325                 :             }
     326                 : 
     327                 :             /* Integraph stuff */
     328               2 :             else if (strcmp(pszType, "G:Point_MultiPointPropertyType") == 0 ||
     329                 :                      strcmp(pszType, "gmgml:Point_MultiPointPropertyType") == 0)
     330                 :             {
     331               0 :                 poClass->SetGeometryElement(pszElementName);
     332               0 :                 poClass->SetGeometryType(wkbMultiPoint);
     333               0 :                 poClass->SetGeometryAttributeIndex( nAttributeIndex );
     334                 : 
     335               0 :                 nAttributeIndex ++;
     336               0 :                 continue;
     337                 :             }
     338               2 :             else if (strcmp(pszType, "G:LineString_MultiLineStringPropertyType") == 0 ||
     339                 :                      strcmp(pszType, "gmgml:LineString_MultiLineStringPropertyType") == 0)
     340                 :             {
     341               0 :                 poClass->SetGeometryElement(pszElementName);
     342               0 :                 poClass->SetGeometryType(wkbMultiLineString);
     343               0 :                 poClass->SetGeometryAttributeIndex( nAttributeIndex );
     344                 : 
     345               0 :                 nAttributeIndex ++;
     346               0 :                 continue;
     347                 :             }
     348               2 :             else if (strcmp(pszType, "G:Polygon_MultiPolygonPropertyType") == 0 ||
     349                 :                      strcmp(pszType, "gmgml:Polygon_MultiPolygonPropertyType") == 0 ||
     350                 :                      strcmp(pszType, "gmgml:Polygon_Surface_MultiSurface_CompositeSurfacePropertyType") == 0)
     351                 :             {
     352               0 :                 poClass->SetGeometryElement(pszElementName);
     353               0 :                 poClass->SetGeometryType(wkbMultiPolygon);
     354               0 :                 poClass->SetGeometryAttributeIndex( nAttributeIndex );
     355                 : 
     356               0 :                 nAttributeIndex ++;
     357               0 :                 continue;
     358                 :             }
     359                 : 
     360                 :             /* ERDAS Apollo stuff (like in http://apollo.erdas.com/erdas-apollo/vector/WORLDWIDE?SERVICE=WFS&VERSION=1.0.0&REQUEST=DescribeFeatureType&TYPENAME=wfs:cntry98) */
     361               2 :             else if (strcmp(pszType, "wfs:MixedPolygonPropertyType") == 0)
     362                 :             {
     363               0 :                 poClass->SetGeometryElement(pszElementName);
     364               0 :                 poClass->SetGeometryType(wkbMultiPolygon);
     365               0 :                 poClass->SetGeometryAttributeIndex( nAttributeIndex );
     366                 : 
     367               0 :                 nAttributeIndex ++;
     368               0 :                 continue;
     369                 :             }
     370                 : 
     371                 :             else
     372                 :             {
     373               2 :                 gmlType = GMLPT_Untyped;
     374               2 :                 if ( ! LookForSimpleType(psSchemaNode, pszStrippedNSType,
     375                 :                                          &gmlType, &nWidth, &nPrecision) )
     376                 :                 {
     377                 :                     /* Too complex schema for us. Aborts parsing */
     378               0 :                     delete poClass;
     379               0 :                     return NULL;
     380                 :                 }
     381                 :             }
     382                 : 
     383            1004 :             if (pszElementName == NULL)
     384               0 :                 pszElementName = "unnamed";
     385                 :             GMLPropertyDefn *poProp = new GMLPropertyDefn(
     386            1004 :                 pszElementName, pszElementName );
     387                 : 
     388            1004 :             poProp->SetType( gmlType );
     389            1004 :             poProp->SetAttributeIndex( nAttributeIndex );
     390            1004 :             poProp->SetWidth( nWidth );
     391            1004 :             poProp->SetPrecision( nPrecision );
     392                 : 
     393            1004 :             if (poClass->AddProperty( poProp ) < 0)
     394               0 :                 delete poProp;
     395                 :             else
     396            1004 :                 nAttributeIndex ++;
     397                 : 
     398            1004 :             continue;
     399                 :         }
     400                 : 
     401                 :         // For now we skip geometries .. fixup later.
     402             104 :         CPLXMLNode* psSimpleType = CPLGetXMLNode( psAttrDef, "simpleType" );
     403             104 :         if( psSimpleType == NULL )
     404                 :         {
     405              36 :             const char* pszRef = CPLGetXMLValue( psAttrDef, "ref", NULL );
     406                 : 
     407                 :             /* FME .xsd */
     408              36 :             if (pszRef != NULL && strncmp(pszRef, "gml:", 4) == 0)
     409                 :             {
     410              36 :                 const AssocNameType* psIter = apsRefTypes;
     411             162 :                 while(psIter->pszName)
     412                 :                 {
     413             126 :                     if (strncmp(pszRef + 4, psIter->pszName, strlen(psIter->pszName)) == 0)
     414                 :                     {
     415              36 :                         if (poClass->GetGeometryAttributeIndex() != -1)
     416                 :                         {
     417              18 :                             OGRwkbGeometryType eNewType = psIter->eType;
     418              18 :                             OGRwkbGeometryType eOldType = (OGRwkbGeometryType)poClass->GetGeometryType();
     419              36 :                             if ((eNewType == wkbMultiPoint && eOldType == wkbPoint) ||
     420                 :                                 (eNewType == wkbMultiLineString && eOldType == wkbLineString) ||
     421                 :                                 (eNewType == wkbMultiPolygon && eOldType == wkbPolygon))
     422                 :                             {
     423              18 :                                 poClass->SetGeometryType(eNewType);
     424                 :                             }
     425                 :                             else
     426                 :                             {
     427               0 :                                 CPLDebug("GML", "Geometry field already found ! Ignoring the following ones");
     428                 :                             }
     429                 :                         }
     430                 :                         else
     431                 :                         {
     432              18 :                             poClass->SetGeometryElement(pszElementName);
     433              18 :                             poClass->SetGeometryType(psIter->eType);
     434              18 :                             poClass->SetGeometryAttributeIndex( nAttributeIndex );
     435                 : 
     436              18 :                             nAttributeIndex ++;
     437                 :                         }
     438                 : 
     439              36 :                         break;
     440                 :                     }
     441                 : 
     442              90 :                     psIter ++;
     443                 :                 }
     444                 : 
     445              36 :                 if (psIter->pszName == NULL)
     446                 :                 {
     447                 :                     /* Can be a non geometry gml type */
     448                 :                     /* Too complex schema for us. Aborts parsing */
     449               0 :                     delete poClass;
     450               0 :                     return NULL;
     451                 :                 }
     452                 : 
     453              36 :                 if (poClass->GetGeometryAttributeIndex() == -1)
     454               0 :                     bGotUnrecognizedType = TRUE;
     455                 : 
     456              36 :                 continue;
     457                 :             }
     458                 :             else
     459                 :             {
     460                 :                 /* Too complex schema for us. Aborts parsing */
     461               0 :                 delete poClass;
     462               0 :                 return NULL;
     463                 :             }
     464                 :         }
     465                 : 
     466              68 :         if (pszElementName == NULL)
     467               0 :             pszElementName = "unnamed";
     468                 :         GMLPropertyDefn *poProp = new GMLPropertyDefn(
     469              68 :             pszElementName, pszElementName );
     470                 : 
     471              68 :         GMLPropertyType eType = GMLPT_Untyped;
     472              68 :         int nWidth = 0, nPrecision = 0;
     473              68 :         GetSimpleTypeProperties(psSimpleType, &eType, &nWidth, &nPrecision);
     474              68 :         poProp->SetType( eType );
     475              68 :         poProp->SetWidth( nWidth );
     476              68 :         poProp->SetPrecision( nPrecision );
     477              68 :         poProp->SetAttributeIndex( nAttributeIndex );
     478                 : 
     479              68 :         if (poClass->AddProperty( poProp ) < 0)
     480               0 :             delete poProp;
     481                 :         else
     482              68 :             nAttributeIndex ++;
     483                 :     }
     484                 : 
     485                 :     /* Only report wkbNone if we didn't find a known geometry type */
     486                 :     /* and there were not any unknown types (in case this unknown type */
     487                 :     /* would be a geometry type) */
     488             240 :     if (poClass->GetGeometryAttributeIndex() == -1 &&
     489                 :         !bGotUnrecognizedType)
     490                 :     {
     491               2 :         poClass->SetGeometryType(wkbNone);
     492                 :     }
     493                 : 
     494                 : /* -------------------------------------------------------------------- */
     495                 : /*      Class complete, add to reader class list.                       */
     496                 : /* -------------------------------------------------------------------- */
     497             240 :     poClass->SetSchemaLocked( TRUE );
     498                 : 
     499             240 :     return poClass;
     500                 : }
     501                 : 
     502                 : /************************************************************************/
     503                 : /*                          GMLParseXSD()                               */
     504                 : /************************************************************************/
     505                 : 
     506             164 : int GMLParseXSD( const char *pszFile,
     507                 :                  std::vector<GMLFeatureClass*> & aosClasses)
     508                 : 
     509                 : {
     510             164 :     if( pszFile == NULL )
     511               0 :         return FALSE;
     512                 : 
     513                 : /* -------------------------------------------------------------------- */
     514                 : /*      Load the raw XML file.                                          */
     515                 : /* -------------------------------------------------------------------- */
     516             164 :     CPLXMLNode *psXSDTree = CPLParseXMLFile( pszFile );
     517                 :     
     518             164 :     if( psXSDTree == NULL )
     519               0 :         return FALSE;
     520                 : 
     521                 : /* -------------------------------------------------------------------- */
     522                 : /*      Strip off any namespace qualifiers.                             */
     523                 : /* -------------------------------------------------------------------- */
     524             164 :     CPLStripXMLNamespace( psXSDTree, NULL, TRUE );
     525                 : 
     526                 : /* -------------------------------------------------------------------- */
     527                 : /*      Find <schema> root element.                                     */
     528                 : /* -------------------------------------------------------------------- */
     529             164 :     CPLXMLNode *psSchemaNode = CPLGetXMLNode( psXSDTree, "=schema" );
     530             164 :     if( psSchemaNode == NULL )
     531                 :     {
     532               0 :         CPLDestroyXMLNode( psXSDTree );
     533               0 :         return FALSE;
     534                 :     }
     535                 : 
     536                 : /* ==================================================================== */
     537                 : /*      Process each feature class definition.                          */
     538                 : /* ==================================================================== */
     539                 :     CPLXMLNode *psThis;
     540                 : 
     541            2028 :     for( psThis = psSchemaNode->psChild; 
     542                 :          psThis != NULL; psThis = psThis->psNext )
     543                 :     {
     544                 : /* -------------------------------------------------------------------- */
     545                 : /*      Check for <xs:element> node.                                    */
     546                 : /* -------------------------------------------------------------------- */
     547            1864 :         if( psThis->eType != CXT_Element 
     548                 :             || !EQUAL(psThis->pszValue,"element") )
     549            1586 :             continue;
     550                 : 
     551                 : /* -------------------------------------------------------------------- */
     552                 : /*      Check the substitution group.                                   */
     553                 : /* -------------------------------------------------------------------- */
     554                 :         const char *pszSubGroup = 
     555             278 :             StripNS(CPLGetXMLValue(psThis,"substitutionGroup",""));
     556                 : 
     557                 :         // Old OGR produced elements for the feature collection.
     558             278 :         if( EQUAL(pszSubGroup, "_FeatureCollection") )
     559              22 :             continue;
     560                 : 
     561             256 :         if( !EQUAL(pszSubGroup, "_Feature") &&
     562                 :             !EQUAL(pszSubGroup, "AbstractFeature") /* AbstractFeature used by GML 3.2 */ )
     563                 :         {
     564              10 :             continue;
     565                 :         }
     566                 :         
     567                 : /* -------------------------------------------------------------------- */
     568                 : /*      Get name                                                        */
     569                 : /* -------------------------------------------------------------------- */
     570                 :         const char *pszName;
     571                 : 
     572             246 :         pszName = CPLGetXMLValue( psThis, "name", NULL );
     573             246 :         if( pszName == NULL )
     574                 :         {
     575               0 :             continue;
     576                 :         }
     577                 : 
     578                 : /* -------------------------------------------------------------------- */
     579                 : /*      Get type and verify relationship with name.                     */
     580                 : /* -------------------------------------------------------------------- */
     581                 :         const char *pszType;
     582                 : 
     583             246 :         pszType = CPLGetXMLValue( psThis, "type", NULL );
     584             246 :         if (pszType == NULL)
     585                 :         {
     586             148 :             CPLXMLNode *psComplexType = CPLGetXMLNode( psThis, "complexType" );
     587             148 :             if (psComplexType)
     588                 :             {
     589                 :                 GMLFeatureClass* poClass =
     590             148 :                         GMLParseFeatureType(psSchemaNode, pszName, psComplexType);
     591             148 :                 if (poClass)
     592             148 :                     aosClasses.push_back(poClass);
     593                 :             }
     594             148 :             continue;
     595                 :         }
     596              98 :         if( strstr( pszType, ":" ) != NULL )
     597              98 :             pszType = strstr( pszType, ":" ) + 1;
     598              98 :         if( EQUAL(pszType, pszName) )
     599                 :         {
     600                 :             /* A few WFS servers return a type name which is the element name */
     601                 :             /* without any _Type or Type suffix */
     602                 :             /* e.g. : http://apollo.erdas.com/erdas-apollo/vector/Cherokee?SERVICE=WFS&VERSION=1.0.0&REQUEST=DescribeFeatureType&TYPENAME=iwfs:Air */
     603                 :         }
     604              98 :         else if( !EQUALN(pszType,pszName,strlen(pszName))
     605                 :             || !(EQUAL(pszType+strlen(pszName),"_Type") ||
     606                 :                     EQUAL(pszType+strlen(pszName),"Type")) )
     607                 :         {
     608               0 :             continue;
     609                 :         }
     610                 : 
     611                 :         /* CanVec .xsd contains weird types that are not used in the related GML */
     612              98 :         if (strncmp(pszName, "XyZz", 4) == 0 ||
     613                 :             strncmp(pszName, "XyZ1", 4) == 0 ||
     614                 :             strncmp(pszName, "XyZ2", 4) == 0)
     615               6 :             continue;
     616                 : 
     617                 :         GMLFeatureClass* poClass =
     618              92 :                 GMLParseFeatureType(psSchemaNode, pszName, pszType);
     619              92 :         if (poClass)
     620              92 :             aosClasses.push_back(poClass);
     621                 :     }
     622                 : 
     623             164 :     CPLDestroyXMLNode( psXSDTree );
     624                 : 
     625             164 :     if( aosClasses.size() > 0 )
     626                 :     {
     627             158 :         return TRUE;
     628                 :     }
     629                 :     else
     630               6 :         return FALSE;
     631                 : }

Generated by: LCOV version 1.7