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: 2013-03-30 Functions: 8 8 100.0 %

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

Generated by: LCOV version 1.7