LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/gml - parsexsd.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 246 187 76.0 %
Date: 2012-12-26 Functions: 8 8 100.0 %

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

Generated by: LCOV version 1.7