LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/gml - parsexsd.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 213 163 76.5 %
Date: 2011-12-18 Functions: 6 6 100.0 %

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

Generated by: LCOV version 1.7