Esempio n. 1
0
void GMLReader::SetFeatureProperty( const char *pszElement, 
                                    const char *pszValue )

{
    GMLFeature *poFeature = GetState()->m_poFeature;

    CPLAssert( poFeature  != NULL );

/* -------------------------------------------------------------------- */
/*      Does this property exist in the feature class?  If not, add     */
/*      it.                                                             */
/* -------------------------------------------------------------------- */
    GMLFeatureClass *poClass = poFeature->GetClass();
    int      iProperty;

    for( iProperty=0; iProperty < poClass->GetPropertyCount(); iProperty++ )
    {
        if( EQUAL(poClass->GetProperty( iProperty )->GetSrcElement(),
                  pszElement ) )
            break;
    }
    
    if( iProperty == poClass->GetPropertyCount() )
    {
        if( poClass->IsSchemaLocked() )
        {
            CPLDebug("GML","Encountered property missing from class schema.");
            return;
        }

        GMLPropertyDefn *poPDefn = new GMLPropertyDefn(pszElement,pszElement);

        if( EQUAL(CPLGetConfigOption( "GML_FIELDTYPES", ""), "ALWAYS_STRING") )
            poPDefn->SetType( GMLPT_String );

        poClass->AddProperty( poPDefn );

    }

/* -------------------------------------------------------------------- */
/*      Set the property                                                */
/* -------------------------------------------------------------------- */
    poFeature->SetProperty( iProperty, pszValue );

/* -------------------------------------------------------------------- */
/*      Do we need to update the property type?                         */
/* -------------------------------------------------------------------- */
    if( !poClass->IsSchemaLocked() )
        poClass->GetProperty( iProperty )->AnalysePropertyValue(pszValue);
}
Esempio n. 2
0
OGRNASLayer *OGRNASDataSource::TranslateNASSchema( GMLFeatureClass *poClass )

{
    OGRwkbGeometryType eGType = wkbNone;

    if( poClass->GetGeometryPropertyCount() != 0 )
    {
        eGType = static_cast<OGRwkbGeometryType>(
            poClass->GetGeometryProperty(0)->GetType() );

        if( poClass->GetFeatureCount() == 0 )
            eGType = wkbUnknown;
    }

/* -------------------------------------------------------------------- */
/*      Translate SRS.                                                  */
/* -------------------------------------------------------------------- */
    const char* pszSRSName = poClass->GetSRSName();
    OGRSpatialReference* poSRS = NULL;
    if (pszSRSName)
    {
        const char *pszHandle = strrchr( pszSRSName, ':' );
        if( pszHandle != NULL )
        {
            pszHandle += 1;

            poSRS = new OGRSpatialReference();

            for( int i = 0; apszURNNames[i*2+0] != NULL; i++ )
            {
                const char *pszTarget = apszURNNames[i*2+0];
                const int nTLen = static_cast<int>(strlen(pszTarget));

                // Are we just looking for a prefix match?
                if( pszTarget[nTLen-1] == '*' )
                {
                    if( EQUALN(pszTarget,pszHandle,nTLen-1) )
                        pszSRSName = apszURNNames[i*2+1];
                }
                else
                {
                    if( EQUAL(pszTarget,pszHandle) )
                        pszSRSName = apszURNNames[i*2+1];
                }
            }

            if (poSRS->SetFromUserInput(pszSRSName) != OGRERR_NONE)
            {
                CPLDebug( "NAS", "Failed to translate srsName='%s'",
                        pszSRSName );
                delete poSRS;
                poSRS = NULL;
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Create an empty layer.                                          */
/* -------------------------------------------------------------------- */
    OGRNASLayer *poLayer =
        new OGRNASLayer( poClass->GetName(), poSRS, eGType, this );
    delete poSRS;

/* -------------------------------------------------------------------- */
/*      Added attributes (properties).                                  */
/* -------------------------------------------------------------------- */
    for( int iField = 0; iField < poClass->GetPropertyCount(); iField++ )
    {
        GMLPropertyDefn *poProperty = poClass->GetProperty( iField );
        OGRFieldType eFType;

        if( poProperty->GetType() == GMLPT_Untyped )
            eFType = OFTString;
        else if( poProperty->GetType() == GMLPT_String )
            eFType = OFTString;
        else if( poProperty->GetType() == GMLPT_Integer )
            eFType = OFTInteger;
        else if( poProperty->GetType() == GMLPT_Real )
            eFType = OFTReal;
        else if( poProperty->GetType() == GMLPT_StringList )
            eFType = OFTStringList;
        else if( poProperty->GetType() == GMLPT_IntegerList )
            eFType = OFTIntegerList;
        else if( poProperty->GetType() == GMLPT_RealList )
            eFType = OFTRealList;
        else
            eFType = OFTString;

        OGRFieldDefn oField( poProperty->GetName(), eFType );
        if ( STARTS_WITH_CI(oField.GetNameRef(), "ogr:") )
          oField.SetName(poProperty->GetName()+4);
        if( poProperty->GetWidth() > 0 )
            oField.SetWidth( poProperty->GetWidth() );

        poLayer->GetLayerDefn()->AddFieldDefn( &oField );
    }

    return poLayer;
}
Esempio n. 3
0
static
GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                                     const char* pszName,
                                     CPLXMLNode *psComplexType)
{

/* -------------------------------------------------------------------- */
/*      Grab the sequence of extensions greatgrandchild.                */
/* -------------------------------------------------------------------- */
    CPLXMLNode *psAttrSeq =
        CPLGetXMLNode( psComplexType,
                        "complexContent.extension.sequence" );

    if( psAttrSeq == NULL )
    {
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      We are pretty sure this going to be a valid Feature class       */
/*      now, so create it.                                              */
/* -------------------------------------------------------------------- */
    GMLFeatureClass *poClass = new GMLFeatureClass( pszName );

/* -------------------------------------------------------------------- */
/*      Loop over each of the attribute elements being defined for      */
/*      this feature class.                                             */
/* -------------------------------------------------------------------- */
    CPLXMLNode *psAttrDef;
    int nAttributeIndex = 0;

    int bGotUnrecognizedType = FALSE;

    for( psAttrDef = psAttrSeq->psChild;
            psAttrDef != NULL;
            psAttrDef = psAttrDef->psNext )
    {
        if( strcmp(psAttrDef->pszValue,"group") == 0 )
        {
            /* Too complex schema for us. Aborts parsing */
            delete poClass;
            return NULL;
        }

        if( !EQUAL(psAttrDef->pszValue,"element") )
            continue;

        /* MapServer WFS writes element type as an attribute of element */
        /* not as a simpleType definition */
        const char* pszType = CPLGetXMLValue( psAttrDef, "type", NULL );
        const char* pszElementName = CPLGetXMLValue( psAttrDef, "name", NULL );
        if (pszType != NULL)
        {
            const char* pszStrippedNSType = StripNS(pszType);
            int nWidth = 0, nPrecision = 0;

            GMLPropertyType gmlType = GMLPT_Untyped;
            if (EQUAL(pszStrippedNSType, "string") ||
                EQUAL(pszStrippedNSType, "Character"))
                gmlType = GMLPT_String;
            /* TODO: Would be nice to have a proper date type */
            else if (EQUAL(pszStrippedNSType, "date") ||
                     EQUAL(pszStrippedNSType, "dateTime"))
                gmlType = GMLPT_String;
            else if (EQUAL(pszStrippedNSType, "real") ||
                     EQUAL(pszStrippedNSType, "double") ||
                     EQUAL(pszStrippedNSType, "float") ||
                     EQUAL(pszStrippedNSType, "decimal"))
                gmlType = GMLPT_Real;
            else if (EQUAL(pszStrippedNSType, "short") ||
                     EQUAL(pszStrippedNSType, "int") ||
                     EQUAL(pszStrippedNSType, "integer") ||
                     EQUAL(pszStrippedNSType, "long"))
                gmlType = GMLPT_Integer;
            else if (strncmp(pszType, "gml:", 4) == 0)
            {
                const AssocNameType* psIter = apsPropertyTypes;
                while(psIter->pszName)
                {
                    if (strncmp(pszType + 4, psIter->pszName, strlen(psIter->pszName)) == 0)
                    {
                        if (poClass->GetGeometryAttributeIndex() != -1)
                        {
                            CPLDebug("GML", "Geometry field already found ! Ignoring the following ones");
                        }
                        else
                        {
                            poClass->SetGeometryElement(pszElementName);
                            poClass->SetGeometryType(psIter->eType);
                            poClass->SetGeometryAttributeIndex( nAttributeIndex );

                            nAttributeIndex ++;
                        }
                        
                        break;
                    }

                    psIter ++;
                }

                if (psIter->pszName == NULL)
                {
                    /* Can be a non geometry gml type */
                    /* Too complex schema for us. Aborts parsing */
                    delete poClass;
                    return NULL;
                }

                if (poClass->GetGeometryAttributeIndex() == -1)
                    bGotUnrecognizedType = TRUE;

                continue;
            }

            /* Integraph stuff */
            else if (strcmp(pszType, "G:Point_MultiPointPropertyType") == 0 ||
                     strcmp(pszType, "gmgml:Point_MultiPointPropertyType") == 0)
            {
                poClass->SetGeometryElement(pszElementName);
                poClass->SetGeometryType(wkbMultiPoint);
                poClass->SetGeometryAttributeIndex( nAttributeIndex );

                nAttributeIndex ++;
                continue;
            }
            else if (strcmp(pszType, "G:LineString_MultiLineStringPropertyType") == 0 ||
                     strcmp(pszType, "gmgml:LineString_MultiLineStringPropertyType") == 0)
            {
                poClass->SetGeometryElement(pszElementName);
                poClass->SetGeometryType(wkbMultiLineString);
                poClass->SetGeometryAttributeIndex( nAttributeIndex );

                nAttributeIndex ++;
                continue;
            }
            else if (strcmp(pszType, "G:Polygon_MultiPolygonPropertyType") == 0 ||
                     strcmp(pszType, "gmgml:Polygon_MultiPolygonPropertyType") == 0 ||
                     strcmp(pszType, "gmgml:Polygon_Surface_MultiSurface_CompositeSurfacePropertyType") == 0)
            {
                poClass->SetGeometryElement(pszElementName);
                poClass->SetGeometryType(wkbMultiPolygon);
                poClass->SetGeometryAttributeIndex( nAttributeIndex );

                nAttributeIndex ++;
                continue;
            }

            /* ERDAS Apollo stuff (like in http://apollo.erdas.com/erdas-apollo/vector/WORLDWIDE?SERVICE=WFS&VERSION=1.0.0&REQUEST=DescribeFeatureType&TYPENAME=wfs:cntry98) */
            else if (strcmp(pszType, "wfs:MixedPolygonPropertyType") == 0)
            {
                poClass->SetGeometryElement(pszElementName);
                poClass->SetGeometryType(wkbMultiPolygon);
                poClass->SetGeometryAttributeIndex( nAttributeIndex );

                nAttributeIndex ++;
                continue;
            }

            else
            {
                gmlType = GMLPT_Untyped;
                if ( ! LookForSimpleType(psSchemaNode, pszStrippedNSType,
                                         &gmlType, &nWidth, &nPrecision) )
                {
                    /* Too complex schema for us. Aborts parsing */
                    delete poClass;
                    return NULL;
                }
            }

            if (pszElementName == NULL)
                pszElementName = "unnamed";
            GMLPropertyDefn *poProp = new GMLPropertyDefn(
                pszElementName, pszElementName );

            poProp->SetType( gmlType );
            poProp->SetAttributeIndex( nAttributeIndex );
            poProp->SetWidth( nWidth );
            poProp->SetPrecision( nPrecision );

            if (poClass->AddProperty( poProp ) < 0)
                delete poProp;
            else
                nAttributeIndex ++;

            continue;
        }

        // For now we skip geometries .. fixup later.
        CPLXMLNode* psSimpleType = CPLGetXMLNode( psAttrDef, "simpleType" );
        if( psSimpleType == NULL )
        {
            const char* pszRef = CPLGetXMLValue( psAttrDef, "ref", NULL );

            /* FME .xsd */
            if (pszRef != NULL && strncmp(pszRef, "gml:", 4) == 0)
            {
                const AssocNameType* psIter = apsRefTypes;
                while(psIter->pszName)
                {
                    if (strncmp(pszRef + 4, psIter->pszName, strlen(psIter->pszName)) == 0)
                    {
                        if (poClass->GetGeometryAttributeIndex() != -1)
                        {
                            OGRwkbGeometryType eNewType = psIter->eType;
                            OGRwkbGeometryType eOldType = (OGRwkbGeometryType)poClass->GetGeometryType();
                            if ((eNewType == wkbMultiPoint && eOldType == wkbPoint) ||
                                (eNewType == wkbMultiLineString && eOldType == wkbLineString) ||
                                (eNewType == wkbMultiPolygon && eOldType == wkbPolygon))
                            {
                                poClass->SetGeometryType(eNewType);
                            }
                            else
                            {
                                CPLDebug("GML", "Geometry field already found ! Ignoring the following ones");
                            }
                        }
                        else
                        {
                            poClass->SetGeometryElement(pszElementName);
                            poClass->SetGeometryType(psIter->eType);
                            poClass->SetGeometryAttributeIndex( nAttributeIndex );

                            nAttributeIndex ++;
                        }

                        break;
                    }

                    psIter ++;
                }

                if (psIter->pszName == NULL)
                {
                    /* Can be a non geometry gml type */
                    /* Too complex schema for us. Aborts parsing */
                    delete poClass;
                    return NULL;
                }

                if (poClass->GetGeometryAttributeIndex() == -1)
                    bGotUnrecognizedType = TRUE;

                continue;
            }

            /* 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 :
            <xs:element name="Obj" minOccurs="0" maxOccurs="1">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element ref="gml:_Geometry"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
            */
            CPLXMLNode* psComplexType = GetSingleChildElement( psAttrDef, "complexType" );
            CPLXMLNode* psComplexTypeSequence = GetSingleChildElement( psComplexType, "sequence" );
            CPLXMLNode* psComplexTypeSequenceElement = GetSingleChildElement( psComplexTypeSequence, "element" );

            if( pszElementName != NULL &&
                CheckMinMaxOccursCardinality(psAttrDef) &&
                psComplexTypeSequenceElement != NULL &&
                CheckMinMaxOccursCardinality(psComplexTypeSequence) &&
                strcmp(CPLGetXMLValue( psComplexTypeSequenceElement, "ref", "" ), "gml:_Geometry") == 0 )
            {
                poClass->SetGeometryElement(pszElementName);
                poClass->SetGeometryType(wkbUnknown);
                poClass->SetGeometryAttributeIndex( nAttributeIndex );

                nAttributeIndex ++;

                continue;
            }
            else
            {
                /* Too complex schema for us. Aborts parsing */
                delete poClass;
                return NULL;
            }
        }

        if (pszElementName == NULL)
            pszElementName = "unnamed";
        GMLPropertyDefn *poProp = new GMLPropertyDefn(
            pszElementName, pszElementName );

        GMLPropertyType eType = GMLPT_Untyped;
        int nWidth = 0, nPrecision = 0;
        GetSimpleTypeProperties(psSimpleType, &eType, &nWidth, &nPrecision);
        poProp->SetType( eType );
        poProp->SetWidth( nWidth );
        poProp->SetPrecision( nPrecision );
        poProp->SetAttributeIndex( nAttributeIndex );

        if (poClass->AddProperty( poProp ) < 0)
            delete poProp;
        else
            nAttributeIndex ++;
    }

    /* Only report wkbNone if we didn't find a known geometry type */
    /* and there were not any unknown types (in case this unknown type */
    /* would be a geometry type) */
    if (poClass->GetGeometryAttributeIndex() == -1 &&
        !bGotUnrecognizedType)
    {
        poClass->SetGeometryType(wkbNone);
    }

/* -------------------------------------------------------------------- */
/*      Class complete, add to reader class list.                       */
/* -------------------------------------------------------------------- */
    poClass->SetSchemaLocked( TRUE );

    return poClass;
}
Esempio n. 4
0
int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )

{
/* -------------------------------------------------------------------- */
/*      Do some rudimentary checking that this is a well formed         */
/*      node.                                                           */
/* -------------------------------------------------------------------- */
    if( psRoot == NULL 
        || psRoot->eType != CXT_Element 
        || !EQUAL(psRoot->pszValue,"GMLFeatureClass") )
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "GMLFeatureClass::InitializeFromXML() called on %s node!",
                  psRoot->pszValue );
        return FALSE;
    }

    if( CPLGetXMLValue( psRoot, "Name", NULL ) == NULL )
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "GMLFeatureClass has no <Name> element." );
        return FALSE;
    }

/* -------------------------------------------------------------------- */
/*      Collect base info.                                              */
/* -------------------------------------------------------------------- */
    CPLFree( m_pszName );
    m_pszName = CPLStrdup( CPLGetXMLValue( psRoot, "Name", NULL ) );
    
    SetElementName( CPLGetXMLValue( psRoot, "ElementPath", m_pszName ) );

    const char *pszGPath = CPLGetXMLValue( psRoot, "GeometryElementPath", "" );
    
    if( strlen( pszGPath ) > 0 )
        SetGeometryElement( pszGPath );

    if( CPLGetXMLValue( psRoot, "GeometryType", NULL ) != NULL )
    {
        SetGeometryType( atoi(CPLGetXMLValue( psRoot, "GeometryType", NULL )) );
    }

/* -------------------------------------------------------------------- */
/*      Collect dataset specific info.                                  */
/* -------------------------------------------------------------------- */
    CPLXMLNode *psDSI = CPLGetXMLNode( psRoot, "DatasetSpecificInfo" );
    if( psDSI != NULL )
    {
        const char *pszValue;

        pszValue = CPLGetXMLValue( psDSI, "FeatureCount", NULL );
        if( pszValue != NULL )
            SetFeatureCount( atoi(pszValue) );

        // Eventually we should support XML subtrees.
        pszValue = CPLGetXMLValue( psDSI, "ExtraInfo", NULL );
        if( pszValue != NULL )
            SetExtraInfo( pszValue );

        if( CPLGetXMLValue( psDSI, "ExtentXMin", NULL ) != NULL 
            && CPLGetXMLValue( psDSI, "ExtentXMax", NULL ) != NULL
            && CPLGetXMLValue( psDSI, "ExtentYMin", NULL ) != NULL
            && CPLGetXMLValue( psDSI, "ExtentYMax", NULL ) != NULL )
        {
            SetExtents( atof(CPLGetXMLValue( psDSI, "ExtentXMin", "0.0" )),
                        atof(CPLGetXMLValue( psDSI, "ExtentXMax", "0.0" )),
                        atof(CPLGetXMLValue( psDSI, "ExtentYMin", "0.0" )),
                        atof(CPLGetXMLValue( psDSI, "ExtentYMax", "0.0" )) );
        }
    }
    
/* -------------------------------------------------------------------- */
/*      Collect property definitions.                                   */
/* -------------------------------------------------------------------- */
    for( CPLXMLNode *psThis = psRoot->psChild;
         psThis != NULL; psThis = psThis->psNext )
    {
        if( EQUAL(psThis->pszValue, "PropertyDefn") )
        {
            const char *pszName = CPLGetXMLValue( psThis, "Name", NULL );
            const char *pszType = CPLGetXMLValue( psThis, "Type", "Untyped" );
            GMLPropertyDefn *poPDefn;

            if( pszName == NULL )
            {
                CPLError( CE_Failure, CPLE_AppDefined, 
                          "GMLFeatureClass %s has a PropertyDefn without a <Name>..",
                          m_pszName );
                return FALSE;
            }

            poPDefn = new GMLPropertyDefn( 
                pszName, CPLGetXMLValue( psThis, "ElementPath", NULL ) );
            
            if( EQUAL(pszType,"Untyped") )
                poPDefn->SetType( GMLPT_Untyped );
            else if( EQUAL(pszType,"String") ) 
            {
                poPDefn->SetType( GMLPT_String );
                poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
            }
            else if( EQUAL(pszType,"Integer") )
            {
                poPDefn->SetType( GMLPT_Integer );
                poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
            }
            else if( EQUAL(pszType,"Real") )
            {
                poPDefn->SetType( GMLPT_Real );
                poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
                poPDefn->SetPrecision( atoi( CPLGetXMLValue( psThis, "Precision", "0" ) ) );
            }
            else if( EQUAL(pszType,"StringList") ) 
                poPDefn->SetType( GMLPT_StringList );
            else if( EQUAL(pszType,"IntegerList") )
                poPDefn->SetType( GMLPT_IntegerList );
            else if( EQUAL(pszType,"RealList") )
                poPDefn->SetType( GMLPT_RealList );
            else if( EQUAL(pszType,"Complex") )
                poPDefn->SetType( GMLPT_Complex );
            else
            {
                CPLError( CE_Failure, CPLE_AppDefined, 
                          "Unrecognised property type %s.", 
                          pszType );
                return FALSE;
            }

            AddProperty( poPDefn );
        }
    }

    return TRUE;
}
Esempio n. 5
0
CPLXMLNode *GMLFeatureClass::SerializeToXML()

{
    CPLXMLNode  *psRoot;
    int         iProperty;

/* -------------------------------------------------------------------- */
/*      Set feature class and core information.                         */
/* -------------------------------------------------------------------- */
    psRoot = CPLCreateXMLNode( NULL, CXT_Element, "GMLFeatureClass" );

    CPLCreateXMLElementAndValue( psRoot, "Name", GetName() );
    CPLCreateXMLElementAndValue( psRoot, "ElementPath", GetElementName() );
    if( GetGeometryElement() != NULL && strlen(GetGeometryElement()) > 0 )
        CPLCreateXMLElementAndValue( psRoot, "GeometryElementPath", 
                                     GetGeometryElement() );
    
    if( GetGeometryType() != 0 /* wkbUnknown */ )
    {
        char szValue[128];

        sprintf( szValue, "%d", GetGeometryType() );
        CPLCreateXMLElementAndValue( psRoot, "GeometryType", szValue );
    }

/* -------------------------------------------------------------------- */
/*      Write out dataset specific information.                         */
/* -------------------------------------------------------------------- */
    CPLXMLNode *psDSI;

    if( m_bHaveExtents || m_nFeatureCount != -1 || m_pszExtraInfo != NULL )
    {
        psDSI = CPLCreateXMLNode( psRoot, CXT_Element, "DatasetSpecificInfo" );

        if( m_nFeatureCount != -1 )
        {
            char szValue[128];

            sprintf( szValue, "%d", m_nFeatureCount );
            CPLCreateXMLElementAndValue( psDSI, "FeatureCount", szValue );
        }

        if( m_bHaveExtents )
        {
            char szValue[128];

            sprintf( szValue, "%.5f", m_dfXMin );
            CPLCreateXMLElementAndValue( psDSI, "ExtentXMin", szValue );

            sprintf( szValue, "%.5f", m_dfXMax );
            CPLCreateXMLElementAndValue( psDSI, "ExtentXMax", szValue );

            sprintf( szValue, "%.5f", m_dfYMin );
            CPLCreateXMLElementAndValue( psDSI, "ExtentYMin", szValue );

            sprintf( szValue, "%.5f", m_dfYMax );
            CPLCreateXMLElementAndValue( psDSI, "ExtentYMax", szValue );
        }

        if( m_pszExtraInfo )
            CPLCreateXMLElementAndValue( psDSI, "ExtraInfo", m_pszExtraInfo );
    }
    
/* -------------------------------------------------------------------- */
/*      emit property information.                                      */
/* -------------------------------------------------------------------- */
    for( iProperty = 0; iProperty < GetPropertyCount(); iProperty++ )
    {
        GMLPropertyDefn *poPDefn = GetProperty( iProperty );
        CPLXMLNode *psPDefnNode;
        const char *pszTypeName = "Unknown";

        psPDefnNode = CPLCreateXMLNode( psRoot, CXT_Element, "PropertyDefn" );
        CPLCreateXMLElementAndValue( psPDefnNode, "Name", 
                                     poPDefn->GetName() );
        CPLCreateXMLElementAndValue( psPDefnNode, "ElementPath", 
                                     poPDefn->GetSrcElement() );
        switch( poPDefn->GetType() )
        {
          case GMLPT_Untyped:
            pszTypeName = "Untyped";
            break;
            
          case GMLPT_String:
            pszTypeName = "String";
            break;
            
          case GMLPT_Integer:
            pszTypeName = "Integer";
            break;
            
          case GMLPT_Real:
            pszTypeName = "Real";
            break;
            
          case GMLPT_Complex:
            pszTypeName = "Complex";
            break;

          case GMLPT_IntegerList:
            pszTypeName = "IntegerList";
            break;

          case GMLPT_RealList:
            pszTypeName = "RealList";
            break;

          case GMLPT_StringList:
            pszTypeName = "StringList";
            break;
        }
        CPLCreateXMLElementAndValue( psPDefnNode, "Type", pszTypeName );

        if( EQUAL(pszTypeName,"String") )
        {
            char szMaxLength[48];
            sprintf(szMaxLength, "%d", poPDefn->GetWidth());
            CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szMaxLength );
        }
        if( poPDefn->GetWidth() > 0 && EQUAL(pszTypeName,"Integer") )
        {
            char szLength[48];
            sprintf(szLength, "%d", poPDefn->GetWidth());
            CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szLength );
        }
        if( poPDefn->GetWidth() > 0 && EQUAL(pszTypeName,"Real") )
        {
            char szLength[48];
            sprintf(szLength, "%d", poPDefn->GetWidth());
            CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szLength );
            char szPrecision[48];
            sprintf(szPrecision, "%d", poPDefn->GetPrecision());
            CPLCreateXMLElementAndValue ( psPDefnNode, "Precision", szPrecision );
        }
    }

    return psRoot;
}
Esempio n. 6
0
void NASReader::SetFeatureProperty( const char *pszElement, 
                                    const char *pszValue )

{
    GMLFeature *poFeature = GetState()->m_poFeature;

    CPLAssert( poFeature  != NULL );

/* -------------------------------------------------------------------- */
/*      Does this property exist in the feature class?  If not, add     */
/*      it.                                                             */
/* -------------------------------------------------------------------- */
    GMLFeatureClass *poClass = poFeature->GetClass();
    int      iProperty;

    for( iProperty=0; iProperty < poClass->GetPropertyCount(); iProperty++ )
    {
        if( EQUAL(poClass->GetProperty( iProperty )->GetSrcElement(),
                  pszElement ) )
            break;
    }
    
    if( iProperty == poClass->GetPropertyCount() )
    {
        if( poClass->IsSchemaLocked() )
        {
            CPLDebug("GML","Encountered property missing from class schema.");
            return;
        }

        CPLString osFieldName;
        
        if( strchr(pszElement,'|') == NULL )
            osFieldName = pszElement;
        else
        {
            osFieldName = strrchr(pszElement,'|') + 1;
            if( poClass->GetPropertyIndex(osFieldName) != -1 )
                osFieldName = pszElement;
        }

        // Does this conflict with an existing property name? 
        while( poClass->GetProperty(osFieldName) != NULL )
        {
            osFieldName += "_";
        }

        GMLPropertyDefn *poPDefn = new GMLPropertyDefn(osFieldName,pszElement);

        if( EQUAL(CPLGetConfigOption( "GML_FIELDTYPES", ""), "ALWAYS_STRING") )
            poPDefn->SetType( GMLPT_String );

        poClass->AddProperty( poPDefn );
    }

/* -------------------------------------------------------------------- */
/*      Set the property                                                */
/* -------------------------------------------------------------------- */
    poFeature->SetProperty( iProperty, pszValue );

/* -------------------------------------------------------------------- */
/*      Do we need to update the property type?                         */
/* -------------------------------------------------------------------- */
    if( !poClass->IsSchemaLocked() )
    {
        poClass->GetProperty(iProperty)->AnalysePropertyValue(
                             poFeature->GetProperty(iProperty));
    }
}
Esempio n. 7
0
int GMLReader::ParseXSD( const char *pszFile )

{
    if( pszFile == NULL )
        return FALSE;

/* -------------------------------------------------------------------- */
/*      Load the raw XML file.                                          */
/* -------------------------------------------------------------------- */
    CPLXMLNode *psXSDTree = CPLParseXMLFile( pszFile );
    
    if( psXSDTree == NULL )
        return FALSE;

/* -------------------------------------------------------------------- */
/*      Strip off any namespace qualifiers.                             */
/* -------------------------------------------------------------------- */
    CPLStripXMLNamespace( psXSDTree, NULL, TRUE );

/* -------------------------------------------------------------------- */
/*      Find <schema> root element.                                     */
/* -------------------------------------------------------------------- */
    CPLXMLNode *psSchemaNode = CPLGetXMLNode( psXSDTree, "=schema" );
    if( psSchemaNode == NULL )
    {
        CPLDestroyXMLNode( psXSDTree );
        return FALSE;
    }

/* ==================================================================== */
/*      Process each feature class definition.                          */
/* ==================================================================== */
    CPLXMLNode *psThis;
    int         bIsLevel0 = TRUE;

    for( psThis = psSchemaNode->psChild; 
         psThis != NULL; psThis = psThis->psNext )
    {
/* -------------------------------------------------------------------- */
/*      Check for <xs:element> node.                                    */
/* -------------------------------------------------------------------- */
        if( psThis->eType != CXT_Element 
            || !EQUAL(psThis->pszValue,"element") )
            continue;

/* -------------------------------------------------------------------- */
/*      Check the substitution group.                                   */
/* -------------------------------------------------------------------- */
        const char *pszSubGroup = 
            StripNS(CPLGetXMLValue(psThis,"substitutionGroup",""));

        // Old OGR produced elements for the feature collection.
        if( EQUAL(pszSubGroup, "_FeatureCollection") )
            continue;

        if( !EQUAL(pszSubGroup, "_Feature") )
        {
            bIsLevel0 = FALSE;
            break;
        }
        
/* -------------------------------------------------------------------- */
/*      Get name                                                        */
/* -------------------------------------------------------------------- */
        const char *pszName;

        pszName = CPLGetXMLValue( psThis, "name", NULL );
        if( pszName == NULL )
        {
            bIsLevel0 = FALSE;
            break;
        }

/* -------------------------------------------------------------------- */
/*      Get type and verify relationship with name.                     */
/* -------------------------------------------------------------------- */
        const char *pszType;

        pszType = CPLGetXMLValue( psThis, "type", NULL );
        if( strstr( pszType, ":" ) != NULL )
            pszType = strstr( pszType, ":" ) + 1; 
        if( pszType == NULL || !EQUALN(pszType,pszName,strlen(pszName)) 
            || !(EQUAL(pszType+strlen(pszName),"_Type") ||
                    EQUAL(pszType+strlen(pszName),"Type")) )
        {
            bIsLevel0 = FALSE;
            break;
        }

/* -------------------------------------------------------------------- */
/*      The very next element should be the corresponding               */
/*      complexType declaration for the element.                        */
/* -------------------------------------------------------------------- */
        psThis = psThis->psNext;
        while( psThis != NULL && psThis->eType == CXT_Comment )
            psThis = psThis->psNext;

        if( psThis == NULL 
            || psThis->eType != CXT_Element
            || !EQUAL(psThis->pszValue,"complexType") 
            || !EQUAL(CPLGetXMLValue(psThis,"name",""),pszType) )
        {
            bIsLevel0 = FALSE;
            break;
        }

/* -------------------------------------------------------------------- */
/*      Grab the sequence of extensions greatgrandchild.                */
/* -------------------------------------------------------------------- */
        CPLXMLNode *psAttrSeq = 
            CPLGetXMLNode( psThis, 
                           "complexContent.extension.sequence" );

        if( psAttrSeq == NULL )
        {
            bIsLevel0 = FALSE;
            break;
        }

/* -------------------------------------------------------------------- */
/*      We are pretty sure this going to be a valid Feature class       */
/*      now, so create it.                                              */
/* -------------------------------------------------------------------- */
        GMLFeatureClass *poClass = new GMLFeatureClass( pszName );

/* -------------------------------------------------------------------- */
/*      Loop over each of the attribute elements being defined for      */
/*      this feature class.                                             */
/* -------------------------------------------------------------------- */
        CPLXMLNode *psAttrDef;

        for( psAttrDef = psAttrSeq->psChild; 
             psAttrDef != NULL; 
             psAttrDef = psAttrDef->psNext )
        {
            if( !EQUAL(psAttrDef->pszValue,"element") )
                continue;

            // For now we skip geometries .. fixup later.
            if( CPLGetXMLNode( psAttrDef, "simpleType" ) == NULL )
                continue;

            GMLPropertyDefn *poProp = new GMLPropertyDefn( 
                CPLGetXMLValue( psAttrDef, "name", "unnamed" ),
                CPLGetXMLValue( psAttrDef, "name", "unnamed" ) );

            const char *pszBase = 
                StripNS( CPLGetXMLValue( psAttrDef, 
                                         "simpleType.restriction.base", "" ));

            if( EQUAL(pszBase,"decimal") )
            {
                poProp->SetType( GMLPT_Real );
                const char *pszWidth = 
                    CPLGetXMLValue( psAttrDef, 
                              "simpleType.restriction.totalDigits.value", "0" );
                const char *pszPrecision = 
                    CPLGetXMLValue( psAttrDef, 
                              "simpleType.restriction.fractionDigits.value", "0" );
                poProp->SetWidth( atoi(pszWidth) );
                poProp->SetPrecision( atoi(pszPrecision) );
            }
            
            else if( EQUAL(pszBase,"float") 
                     || EQUAL(pszBase,"double") )
                poProp->SetType( GMLPT_Real );

            else if( EQUAL(pszBase,"integer") )
            {
                poProp->SetType( GMLPT_Integer );
                const char *pszWidth = 
                    CPLGetXMLValue( psAttrDef, 
                              "simpleType.restriction.totalDigits.value", "0" );
                poProp->SetWidth( atoi(pszWidth) );
            }

            else if( EQUAL(pszBase,"string") )
            {
                poProp->SetType( GMLPT_String );
                const char *pszWidth = 
                    CPLGetXMLValue( psAttrDef, 
                              "simpleType.restriction.maxLength.value", "0" );
                poProp->SetWidth( atoi(pszWidth) );
            }

            else
                poProp->SetType( GMLPT_Untyped );

            poClass->AddProperty( poProp );
        }

/* -------------------------------------------------------------------- */
/*      Class complete, add to reader class list.                       */
/* -------------------------------------------------------------------- */
        poClass->SetSchemaLocked( TRUE );

        AddClass( poClass );
    }

    CPLDestroyXMLNode( psXSDTree );

    if( m_nClassCount > 0 )
    {
        SetClassListLocked( TRUE );
        return TRUE;
    }
    else
        return FALSE;
}
Esempio n. 8
0
void NASReader::SetFeaturePropertyDirectly( const char *pszElement,
                                            char *pszValue )

{
    GMLFeature *poFeature = GetState()->m_poFeature;

    CPLAssert( poFeature  != NULL );

/* -------------------------------------------------------------------- */
/*      Does this property exist in the feature class?  If not, add     */
/*      it.                                                             */
/* -------------------------------------------------------------------- */
    GMLFeatureClass *poClass = poFeature->GetClass();
    int      iProperty;

    for( iProperty=0; iProperty < poClass->GetPropertyCount(); iProperty++ )
    {
        if( EQUAL(poClass->GetProperty( iProperty )->GetSrcElement(),
                  pszElement ) )
            break;
    }
    
    if( iProperty == poClass->GetPropertyCount() )
    {
        if( poClass->IsSchemaLocked() )
        {
            CPLDebug("NAS","Encountered property missing from class schema.");
            CPLFree(pszValue);
            return;
        }

        CPLString osFieldName;
        
        if( strchr(pszElement,'|') == NULL )
            osFieldName = pszElement;
        else
        {
            osFieldName = strrchr(pszElement,'|') + 1;
            if( poClass->GetPropertyIndex(osFieldName) != -1 )
                osFieldName = pszElement;
        }

        // Does this conflict with an existing property name? 
        while( poClass->GetProperty(osFieldName) != NULL )
        {
            osFieldName += "_";
        }

        GMLPropertyDefn *poPDefn = new GMLPropertyDefn(osFieldName,pszElement);

        if( EQUAL(CPLGetConfigOption( "GML_FIELDTYPES", ""), "ALWAYS_STRING") )
            poPDefn->SetType( GMLPT_String );

        poClass->AddProperty( poPDefn );
    }

/* -------------------------------------------------------------------- */
/*      We want to handle <lage> specially to ensure it is zero         */
/*      filled, and treated as a string depspite the numeric            */
/*      content. https://trac.wheregroup.com/PostNAS/ticket/9           */
/* -------------------------------------------------------------------- */
    if( strcmp(poClass->GetProperty(iProperty)->GetName(),"lage") == 0 )
    {
        if( strlen(pszValue) < 5 )
        {
            CPLString osValue = "00000";
            osValue += pszValue;
            poFeature->SetPropertyDirectly( iProperty, CPLStrdup(osValue + osValue.size() - 5) );
            CPLFree(pszValue);
        }
        else
            poFeature->SetPropertyDirectly( iProperty, pszValue );

        
        if( !poClass->IsSchemaLocked() )
        {
            poClass->GetProperty(iProperty)->SetWidth( 5 );
            poClass->GetProperty(iProperty)->SetType( GMLPT_String );
        }
        return;
    }

/* -------------------------------------------------------------------- */
/*      Set the property                                                */
/* -------------------------------------------------------------------- */
    poFeature->SetPropertyDirectly( iProperty, pszValue );

/* -------------------------------------------------------------------- */
/*      Do we need to update the property type?                         */
/* -------------------------------------------------------------------- */
    if( !poClass->IsSchemaLocked() )
    {
        // Special handling for punktkennung per NAS #12
        if( strcmp(poClass->GetProperty(iProperty)->GetName(),
                   "punktkennung") == 0)
        {
            poClass->GetProperty(iProperty)->SetWidth( 15 );
            poClass->GetProperty(iProperty)->SetType( GMLPT_String );
        }
        // Special handling for artDerFlurstuecksgrenze per http://trac.osgeo.org/gdal/ticket/4255
        else if( strcmp(poClass->GetProperty(iProperty)->GetName(),
                   "artDerFlurstuecksgrenze") == 0)
        {
            poClass->GetProperty(iProperty)->SetType( GMLPT_IntegerList );
        }
        else
            poClass->GetProperty(iProperty)->AnalysePropertyValue(
                poFeature->GetProperty(iProperty));
    }
}
OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )

{
    OGRGMLLayer *poLayer;

/* -------------------------------------------------------------------- */
/*      Create an empty layer.                                          */
/* -------------------------------------------------------------------- */
    poLayer = new OGRGMLLayer( poClass->GetName(), NULL, FALSE, 
                               wkbUnknown, this );

/* -------------------------------------------------------------------- */
/*      Added attributes (properties).                                  */
/* -------------------------------------------------------------------- */
    for( int iField = 0; iField < poClass->GetPropertyCount(); iField++ )
    {
        GMLPropertyDefn *poProperty = poClass->GetProperty( iField );
        OGRFieldType eFType;

        if( poProperty->GetType() == GMLPT_Untyped )
            eFType = OFTString;
        else if( poProperty->GetType() == GMLPT_String )
            eFType = OFTString;
        else if( poProperty->GetType() == GMLPT_Integer )
            eFType = OFTInteger;
        else if( poProperty->GetType() == GMLPT_Real )
            eFType = OFTReal;
        else
            eFType = OFTString;
        
        OGRFieldDefn oField( poProperty->GetName(), eFType );
        if ( EQUALN(oField.GetNameRef(), "ogr:", 4) )
          oField.SetName(poProperty->GetName()+4);
        if( poProperty->GetWidth() > 0 )
            oField.SetWidth( poProperty->GetWidth() );
        if( poProperty->GetPrecision() > 0 )
            oField.SetPrecision( poProperty->GetPrecision() );

        poLayer->GetLayerDefn()->AddFieldDefn( &oField );
    }

    return poLayer;
}
Esempio n. 10
0
static
GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                                     const char* pszName,
                                     CPLXMLNode *psComplexType)
{

/* -------------------------------------------------------------------- */
/*      Grab the sequence of extensions greatgrandchild.                */
/* -------------------------------------------------------------------- */
    CPLXMLNode *psAttrSeq =
        CPLGetXMLNode( psComplexType,
                        "complexContent.extension.sequence" );

    if( psAttrSeq == NULL )
    {
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      We are pretty sure this going to be a valid Feature class       */
/*      now, so create it.                                              */
/* -------------------------------------------------------------------- */
    GMLFeatureClass *poClass = new GMLFeatureClass( pszName );

/* -------------------------------------------------------------------- */
/*      Loop over each of the attribute elements being defined for      */
/*      this feature class.                                             */
/* -------------------------------------------------------------------- */
    int nAttributeIndex = 0;

    bool bGotUnrecognizedType = false;

    CPLXMLNode *psAttrDef = psAttrSeq->psChild;
    for( ; psAttrDef != NULL; psAttrDef = psAttrDef->psNext )
    {
        if( strcmp(psAttrDef->pszValue,"group") == 0 )
        {
            /* Too complex schema for us. Aborts parsing */
            delete poClass;
            return NULL;
        }

        /* Parse stuff like :
        <xs:choice>
            <xs:element ref="gml:polygonProperty"/>
            <xs:element ref="gml:multiPolygonProperty"/>
        </xs:choice>
        as found in https://downloadagiv.blob.core.windows.net/overstromingsgebieden-en-oeverzones/2014_01/Overstromingsgebieden_en_oeverzones_2014_01_GML.zip
        */
        if( strcmp(psAttrDef->pszValue,"choice") == 0 )
        {
            CPLXMLNode* psChild = psAttrDef->psChild;
            bool bPolygon = false;
            bool bMultiPolygon = false;
            for( ; psChild; psChild = psChild->psNext )
            {
                if( psChild->eType != CXT_Element )
                    continue;
                if( strcmp(psChild->pszValue,"element") == 0 )
                {
                    const char* pszRef = CPLGetXMLValue( psChild, "ref", NULL );
                    if( pszRef != NULL )
                    {
                        if( strcmp(pszRef, "gml:polygonProperty") == 0 )
                            bPolygon = true;
                        else if( strcmp(pszRef, "gml:multiPolygonProperty") == 0 )
                            bMultiPolygon = true;
                        else
                        {
                            delete poClass;
                            return NULL;
                        }
                    }
                    else
                    {
                        delete poClass;
                        return NULL;
                    }
                }
            }
            if( bPolygon && bMultiPolygon )
            {
                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
                    "", "", wkbMultiPolygon, nAttributeIndex, true ) );

                nAttributeIndex ++;
            }
            continue;
        }

        if( !EQUAL(psAttrDef->pszValue,"element") )
            continue;

        /* MapServer WFS writes element type as an attribute of element */
        /* not as a simpleType definition */
        const char* pszType = CPLGetXMLValue( psAttrDef, "type", NULL );
        const char* pszElementName = CPLGetXMLValue( psAttrDef, "name", NULL );
        bool bNullable = EQUAL(CPLGetXMLValue( psAttrDef, "minOccurs", "1" ), "0");
        const char* pszMaxOccurs = CPLGetXMLValue( psAttrDef, "maxOccurs", NULL );
        if (pszType != NULL)
        {
            const char* pszStrippedNSType = StripNS(pszType);
            int nWidth = 0, nPrecision = 0;

            GMLPropertyType gmlType = GMLPT_Untyped;
            if (EQUAL(pszStrippedNSType, "string") ||
                EQUAL(pszStrippedNSType, "Character"))
                gmlType = GMLPT_String;
            /* TODO: Would be nice to have a proper date type */
            else if (EQUAL(pszStrippedNSType, "date") ||
                     EQUAL(pszStrippedNSType, "dateTime"))
                gmlType = GMLPT_String;
            else if (EQUAL(pszStrippedNSType, "real") ||
                     EQUAL(pszStrippedNSType, "double") ||
                     EQUAL(pszStrippedNSType, "decimal"))
                gmlType = GMLPT_Real;
            else if (EQUAL(pszStrippedNSType, "float") )
                gmlType = GMLPT_Float;
            else if (EQUAL(pszStrippedNSType, "int") ||
                     EQUAL(pszStrippedNSType, "integer"))
                gmlType = GMLPT_Integer;
            else if (EQUAL(pszStrippedNSType, "long"))
                gmlType = GMLPT_Integer64;
            else if (EQUAL(pszStrippedNSType, "short") )
                gmlType = GMLPT_Short;
            else if (EQUAL(pszStrippedNSType, "boolean") )
                gmlType = GMLPT_Boolean;
            else if (strcmp(pszType, "gml:FeaturePropertyType") == 0 )
            {
                gmlType = GMLPT_FeatureProperty;
            }
            else if (STARTS_WITH(pszType, "gml:"))
            {
                const AssocNameType* psIter = apsPropertyTypes;
                while(psIter->pszName)
                {
                    if (strncmp(pszType + 4, psIter->pszName, strlen(psIter->pszName)) == 0)
                    {
                        OGRwkbGeometryType eType = psIter->eType;

                        /* Look if there's a comment restricting to subclasses */
                        if( psAttrDef->psNext != NULL && psAttrDef->psNext->eType == CXT_Comment )
                        {
                            if( strstr(psAttrDef->psNext->pszValue, "restricted to Polygon") )
                                eType = wkbPolygon;
                            else if( strstr(psAttrDef->psNext->pszValue, "restricted to LineString") )
                                eType = wkbLineString;
                            else if( strstr(psAttrDef->psNext->pszValue, "restricted to MultiPolygon") )
                                eType = wkbMultiPolygon;
                            else if( strstr(psAttrDef->psNext->pszValue, "restricted to MultiLineString") )
                                eType = wkbMultiLineString;
                        }

                        poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
                            pszElementName, pszElementName, eType, nAttributeIndex, bNullable ) );

                        nAttributeIndex ++;

                        break;
                    }

                    psIter ++;
                }

                if (psIter->pszName == NULL)
                {
                    /* Can be a non geometry gml type */
                    /* Too complex schema for us. Aborts parsing */
                    delete poClass;
                    return NULL;
                }

                if (poClass->GetGeometryPropertyCount() == 0)
                    bGotUnrecognizedType = true;

                continue;
            }

            /* Integraph stuff */
            else if (strcmp(pszType, "G:Point_MultiPointPropertyType") == 0 ||
                     strcmp(pszType, "gmgml:Point_MultiPointPropertyType") == 0)
            {
                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
                    pszElementName, pszElementName, wkbMultiPoint, nAttributeIndex,
                    bNullable ) );

                nAttributeIndex ++;
                continue;
            }
            else if (strcmp(pszType, "G:LineString_MultiLineStringPropertyType") == 0 ||
                     strcmp(pszType, "gmgml:LineString_MultiLineStringPropertyType") == 0)
            {
                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
                    pszElementName, pszElementName, wkbMultiLineString, nAttributeIndex,
                    bNullable ) );

                nAttributeIndex ++;
                continue;
            }
            else if (strcmp(pszType, "G:Polygon_MultiPolygonPropertyType") == 0 ||
                     strcmp(pszType, "gmgml:Polygon_MultiPolygonPropertyType") == 0 ||
                     strcmp(pszType, "gmgml:Polygon_Surface_MultiSurface_CompositeSurfacePropertyType") == 0)
            {
                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
                    pszElementName, pszElementName, wkbMultiPolygon, nAttributeIndex,
                    bNullable ) );

                nAttributeIndex ++;
                continue;
            }

            /* ERDAS Apollo stuff (like in http://apollo.erdas.com/erdas-apollo/vector/WORLDWIDE?SERVICE=WFS&VERSION=1.0.0&REQUEST=DescribeFeatureType&TYPENAME=wfs:cntry98) */
            else if (strcmp(pszType, "wfs:MixedPolygonPropertyType") == 0)
            {
                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
                    pszElementName, pszElementName, wkbMultiPolygon, nAttributeIndex,
                    bNullable) );

                nAttributeIndex ++;
                continue;
            }

            else
            {
                gmlType = GMLPT_Untyped;
                if ( ! LookForSimpleType(psSchemaNode, pszStrippedNSType,
                                         &gmlType, &nWidth, &nPrecision) )
                {
                    /* Too complex schema for us. Aborts parsing */
                    delete poClass;
                    return NULL;
                }
            }

            if (pszElementName == NULL)
                pszElementName = "unnamed";
            const char* pszPropertyName = pszElementName;
            if( gmlType == GMLPT_FeatureProperty )
            {
                pszPropertyName = CPLSPrintf("%s_href", pszElementName);
            }
            GMLPropertyDefn *poProp = new GMLPropertyDefn(
                pszPropertyName, pszElementName );

            if( pszMaxOccurs != NULL && strcmp(pszMaxOccurs, "1") != 0 )
                gmlType = GetListTypeFromSingleType(gmlType);

            poProp->SetType( gmlType );
            poProp->SetWidth( nWidth );
            poProp->SetPrecision( nPrecision );
            poProp->SetNullable( bNullable );

            if (poClass->AddProperty( poProp ) < 0)
                delete poProp;
            else
                nAttributeIndex ++;

            continue;
        }

        // For now we skip geometries .. fixup later.
        CPLXMLNode* psSimpleType = CPLGetXMLNode( psAttrDef, "simpleType" );
        if( psSimpleType == NULL )
        {
            const char* pszRef = CPLGetXMLValue( psAttrDef, "ref", NULL );

            /* FME .xsd */
            if (pszRef != NULL && STARTS_WITH(pszRef, "gml:"))
            {
                const AssocNameType* psIter = apsRefTypes;
                while(psIter->pszName)
                {
                    if (strncmp(pszRef + 4, psIter->pszName, strlen(psIter->pszName)) == 0)
                    {
                        if (poClass->GetGeometryPropertyCount() > 0)
                        {
                            OGRwkbGeometryType eNewType = psIter->eType;
                            OGRwkbGeometryType eOldType = (OGRwkbGeometryType)poClass->GetGeometryProperty(0)->GetType();
                            if ((eNewType == wkbMultiPoint && eOldType == wkbPoint) ||
                                (eNewType == wkbMultiLineString && eOldType == wkbLineString) ||
                                (eNewType == wkbMultiPolygon && eOldType == wkbPolygon))
                            {
                                poClass->GetGeometryProperty(0)->SetType(eNewType);
                            }
                            else
                            {
                                CPLDebug("GML", "Geometry field already found ! Ignoring the following ones");
                            }
                        }
                        else
                        {
                            poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
                                pszElementName, pszElementName, psIter->eType, nAttributeIndex, true ) );

                            nAttributeIndex ++;
                        }

                        break;
                    }

                    psIter ++;
                }

                if (psIter->pszName == NULL)
                {
                    /* Can be a non geometry gml type */
                    /* Too complex schema for us. Aborts parsing */
                    delete poClass;
                    return NULL;
                }

                if (poClass->GetGeometryPropertyCount() == 0)
                    bGotUnrecognizedType = true;

                continue;
            }

            /* 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 :
            <xs:element name="Obj" minOccurs="0" maxOccurs="1">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element ref="gml:_Geometry"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
            */
            CPLXMLNode* l_psComplexType = GetSingleChildElement( psAttrDef, "complexType" );
            CPLXMLNode* psComplexTypeSequence = GetSingleChildElement( l_psComplexType, "sequence" );
            CPLXMLNode* psComplexTypeSequenceElement = GetSingleChildElement( psComplexTypeSequence, "element" );

            if( pszElementName != NULL &&
                CheckMinMaxOccursCardinality(psAttrDef) &&
                psComplexTypeSequenceElement != NULL &&
                CheckMinMaxOccursCardinality(psComplexTypeSequence) &&
                strcmp(CPLGetXMLValue( psComplexTypeSequenceElement, "ref", "" ), "gml:_Geometry") == 0 )
            {
                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
                    pszElementName, pszElementName, wkbUnknown, nAttributeIndex, bNullable ) );

                nAttributeIndex ++;

                continue;
            }
            else
            {
                /* Too complex schema for us. Aborts parsing */
                delete poClass;
                return NULL;
            }
        }

        if (pszElementName == NULL)
            pszElementName = "unnamed";
        GMLPropertyDefn *poProp = new GMLPropertyDefn(
            pszElementName, pszElementName );

        GMLPropertyType eType = GMLPT_Untyped;
        int nWidth = 0, nPrecision = 0;
        GetSimpleTypeProperties(psSimpleType, &eType, &nWidth, &nPrecision);

        if( pszMaxOccurs != NULL && strcmp(pszMaxOccurs, "1") != 0 )
            eType = GetListTypeFromSingleType(eType);

        poProp->SetType( eType );
        poProp->SetWidth( nWidth );
        poProp->SetPrecision( nPrecision );
        poProp->SetNullable( bNullable );

        if (poClass->AddProperty( poProp ) < 0)
            delete poProp;
        else
            nAttributeIndex ++;
    }

    /* If we have found an unknown types, let's be on the side of caution and */
    /* create a geometry field */
    if( poClass->GetGeometryPropertyCount() == 0 &&
        bGotUnrecognizedType )
    {
        poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( "", "", wkbUnknown, -1, true ) );
    }

/* -------------------------------------------------------------------- */
/*      Class complete, add to reader class list.                       */
/* -------------------------------------------------------------------- */
    poClass->SetSchemaLocked( true );

    return poClass;
}
Esempio n. 11
0
CPLXMLNode *GMLFeatureClass::SerializeToXML()

{
    CPLXMLNode  *psRoot;
    int         iProperty;

/* -------------------------------------------------------------------- */
/*      Set feature class and core information.                         */
/* -------------------------------------------------------------------- */
    psRoot = CPLCreateXMLNode( NULL, CXT_Element, "GMLFeatureClass" );

    CPLCreateXMLElementAndValue( psRoot, "Name", GetName() );
    CPLCreateXMLElementAndValue( psRoot, "ElementPath", GetElementName() );
    
    if( m_nGeometryPropertyCount > 1 )
    {
        for(int i=0; i < m_nGeometryPropertyCount; i++)
        {
            GMLGeometryPropertyDefn* poGeomFDefn = m_papoGeometryProperty[i];

            CPLXMLNode *psPDefnNode;
            psPDefnNode = CPLCreateXMLNode( psRoot, CXT_Element, "GeomPropertyDefn" );
            if( strlen(poGeomFDefn->GetName()) > 0 )
                CPLCreateXMLElementAndValue( psPDefnNode, "Name", 
                                             poGeomFDefn->GetName() );
            if( poGeomFDefn->GetSrcElement() != NULL && strlen(poGeomFDefn->GetSrcElement()) > 0 )
                CPLCreateXMLElementAndValue( psPDefnNode, "ElementPath", 
                                             poGeomFDefn->GetSrcElement() );
            
            if( poGeomFDefn->GetType() != 0 /* wkbUnknown */ )
            {
                char szValue[128];

                OGRwkbGeometryType eType = (OGRwkbGeometryType)poGeomFDefn->GetType();

                CPLString osStr(OGRToOGCGeomType(eType));
                if( wkbHasZ(eType) ) osStr += "Z";
                CPLCreateXMLNode( psPDefnNode, CXT_Comment, osStr.c_str() );

                sprintf( szValue, "%d", eType );
                CPLCreateXMLElementAndValue( psPDefnNode, "Type", szValue );
            }
        }
    }
    else if( m_nGeometryPropertyCount == 1 )
    {
        GMLGeometryPropertyDefn* poGeomFDefn = m_papoGeometryProperty[0];
        
        if( strlen(poGeomFDefn->GetName()) > 0 )
            CPLCreateXMLElementAndValue( psRoot, "GeometryName", 
                                         poGeomFDefn->GetName() );

        if( poGeomFDefn->GetSrcElement() != NULL && strlen(poGeomFDefn->GetSrcElement()) > 0 )
            CPLCreateXMLElementAndValue( psRoot, "GeometryElementPath", 
                                         poGeomFDefn->GetSrcElement() );
        
        if( poGeomFDefn->GetType() != 0 /* wkbUnknown */ )
        {
            char szValue[128];

            OGRwkbGeometryType eType = (OGRwkbGeometryType)poGeomFDefn->GetType();

            CPLString osStr(OGRToOGCGeomType(eType));
            if( wkbHasZ(eType) ) osStr += "Z";
            CPLCreateXMLNode( psRoot, CXT_Comment, osStr.c_str() );

            sprintf( szValue, "%d", eType );
            CPLCreateXMLElementAndValue( psRoot, "GeometryType", szValue );
        }
    }
    else
    {
        CPLCreateXMLElementAndValue( psRoot, "GeometryType", "100" );
    }

    const char* pszSRSName = GetSRSName();
    if( pszSRSName )
    {
        CPLCreateXMLElementAndValue( psRoot, "SRSName", pszSRSName );
    }

/* -------------------------------------------------------------------- */
/*      Write out dataset specific information.                         */
/* -------------------------------------------------------------------- */
    CPLXMLNode *psDSI;

    if( m_bHaveExtents || m_nFeatureCount != -1 || m_pszExtraInfo != NULL )
    {
        psDSI = CPLCreateXMLNode( psRoot, CXT_Element, "DatasetSpecificInfo" );

        if( m_nFeatureCount != -1 )
        {
            char szValue[128];

            sprintf( szValue, CPL_FRMT_GIB, m_nFeatureCount );
            CPLCreateXMLElementAndValue( psDSI, "FeatureCount", szValue );
        }

        if( m_bHaveExtents &&
            fabs(m_dfXMin) < 1e100 &&
            fabs(m_dfXMax) < 1e100 &&
            fabs(m_dfYMin) < 1e100 &&
            fabs(m_dfYMax) < 1e100 )
        {
            char szValue[128];

            CPLsnprintf( szValue, sizeof(szValue), "%.5f", m_dfXMin );
            CPLCreateXMLElementAndValue( psDSI, "ExtentXMin", szValue );

            CPLsnprintf( szValue, sizeof(szValue), "%.5f", m_dfXMax );
            CPLCreateXMLElementAndValue( psDSI, "ExtentXMax", szValue );

            CPLsnprintf( szValue, sizeof(szValue), "%.5f", m_dfYMin );
            CPLCreateXMLElementAndValue( psDSI, "ExtentYMin", szValue );

            CPLsnprintf( szValue, sizeof(szValue), "%.5f", m_dfYMax );
            CPLCreateXMLElementAndValue( psDSI, "ExtentYMax", szValue );
        }

        if( m_pszExtraInfo )
            CPLCreateXMLElementAndValue( psDSI, "ExtraInfo", m_pszExtraInfo );
    }
    
/* -------------------------------------------------------------------- */
/*      emit property information.                                      */
/* -------------------------------------------------------------------- */
    for( iProperty = 0; iProperty < GetPropertyCount(); iProperty++ )
    {
        GMLPropertyDefn *poPDefn = GetProperty( iProperty );
        CPLXMLNode *psPDefnNode;
        const char *pszTypeName = "Unknown";

        psPDefnNode = CPLCreateXMLNode( psRoot, CXT_Element, "PropertyDefn" );
        CPLCreateXMLElementAndValue( psPDefnNode, "Name", 
                                     poPDefn->GetName() );
        CPLCreateXMLElementAndValue( psPDefnNode, "ElementPath", 
                                     poPDefn->GetSrcElement() );
        switch( poPDefn->GetType() )
        {
          case GMLPT_Untyped:
            pszTypeName = "Untyped";
            break;
            
          case GMLPT_String:
          case GMLPT_Boolean:
            pszTypeName = "String";
            break;
            
          case GMLPT_Integer:
          case GMLPT_Short:
          case GMLPT_Integer64:
            pszTypeName = "Integer";
            break;
            
          case GMLPT_Real:
          case GMLPT_Float:
            pszTypeName = "Real";
            break;
            
          case GMLPT_Complex:
            pszTypeName = "Complex";
            break;

          case GMLPT_IntegerList:
          case GMLPT_Integer64List:
            pszTypeName = "IntegerList";
            break;

          case GMLPT_RealList:
            pszTypeName = "RealList";
            break;

          case GMLPT_StringList:
          case GMLPT_BooleanList:
            pszTypeName = "StringList";
            break;

          /* should not happen in practise for now because this is not */
          /* autodetected */
          case GMLPT_FeatureProperty:
            pszTypeName = "FeatureProperty";
            break;

          /* should not happen in practise for now because this is not */
          /* autodetected */
          case GMLPT_FeaturePropertyList:
            pszTypeName = "FeaturePropertyList";
            break;
        }
        CPLCreateXMLElementAndValue( psPDefnNode, "Type", pszTypeName );
        if( poPDefn->GetType() == GMLPT_Boolean || poPDefn->GetType() == GMLPT_BooleanList )
            CPLCreateXMLElementAndValue( psPDefnNode, "Subtype", "Boolean" );
        else if( poPDefn->GetType() == GMLPT_Short )
            CPLCreateXMLElementAndValue( psPDefnNode, "Subtype", "Short" );
        else if( poPDefn->GetType() == GMLPT_Float )
            CPLCreateXMLElementAndValue( psPDefnNode, "Subtype", "Float" );
        else if( poPDefn->GetType() == GMLPT_Integer64 ||
                 poPDefn->GetType() == GMLPT_Integer64List )
            CPLCreateXMLElementAndValue( psPDefnNode, "Subtype", "Integer64" );

        if( EQUAL(pszTypeName,"String") )
        {
            char szMaxLength[48];
            sprintf(szMaxLength, "%d", poPDefn->GetWidth());
            CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szMaxLength );
        }
        if( poPDefn->GetWidth() > 0 && EQUAL(pszTypeName,"Integer") )
        {
            char szLength[48];
            sprintf(szLength, "%d", poPDefn->GetWidth());
            CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szLength );
        }
        if( poPDefn->GetWidth() > 0 && EQUAL(pszTypeName,"Real") )
        {
            char szLength[48];
            sprintf(szLength, "%d", poPDefn->GetWidth());
            CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szLength );
            char szPrecision[48];
            sprintf(szPrecision, "%d", poPDefn->GetPrecision());
            CPLCreateXMLElementAndValue ( psPDefnNode, "Precision", szPrecision );
        }
    }

    return psRoot;
}
Esempio n. 12
0
int GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )

{
/* -------------------------------------------------------------------- */
/*      Do some rudimentary checking that this is a well formed         */
/*      node.                                                           */
/* -------------------------------------------------------------------- */
    if( psRoot == NULL 
        || psRoot->eType != CXT_Element 
        || !EQUAL(psRoot->pszValue,"GMLFeatureClass") )
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "GMLFeatureClass::InitializeFromXML() called on %s node!",
                  psRoot->pszValue );
        return FALSE;
    }

    if( CPLGetXMLValue( psRoot, "Name", NULL ) == NULL )
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "GMLFeatureClass has no <Name> element." );
        return FALSE;
    }

/* -------------------------------------------------------------------- */
/*      Collect base info.                                              */
/* -------------------------------------------------------------------- */
    CPLFree( m_pszName );
    m_pszName = CPLStrdup( CPLGetXMLValue( psRoot, "Name", NULL ) );
    n_nNameLen = strlen(m_pszName);

    SetElementName( CPLGetXMLValue( psRoot, "ElementPath", m_pszName ) );

/* -------------------------------------------------------------------- */
/*      Collect geometry properties.                                    */
/* -------------------------------------------------------------------- */
    CPLXMLNode *psThis;

    int bHasValidGeometryName = FALSE;
    int bHasValidGeometryElementPath = FALSE;
    int bHasFoundGeomType = FALSE;
    int bHasFoundGeomElements = FALSE;
    const char* pszGName = "";
    const char* pszGPath = "";
    int nGeomType = wkbUnknown;

    for( psThis = psRoot->psChild; psThis != NULL; psThis = psThis->psNext )
    {
        if( psThis->eType == CXT_Element &&
            EQUAL(psThis->pszValue, "GeomPropertyDefn") )
        {
            const char *pszName = CPLGetXMLValue( psThis, "Name", "" );
            const char *pszElementPath = CPLGetXMLValue( psThis, "ElementPath", "" );
            const char *pszType = CPLGetXMLValue( psThis, "Type", NULL );
            int bNullable = CSLTestBoolean(CPLGetXMLValue( psThis, "Nullable", "true") );
            nGeomType = wkbUnknown;
            if( pszType != NULL && !EQUAL(pszType, "0") )
            {
                nGeomType = atoi(pszType);
                OGRwkbGeometryType nFlattenGeomType = wkbFlatten(nGeomType);
                if( nGeomType != 0 && !(nFlattenGeomType >= wkbPoint && nFlattenGeomType <= wkbMultiSurface) )
                {
                    nGeomType = wkbUnknown;
                    CPLError(CE_Warning, CPLE_AppDefined, "Unrecognised geometry type : %s",
                            pszType);
                }
                else if( nGeomType == 0 )
                    nGeomType = OGRFromOGCGeomType(pszType);
            }
            bHasFoundGeomElements = TRUE;
            AddGeometryProperty( new GMLGeometryPropertyDefn( pszName, pszElementPath, nGeomType, -1, bNullable ) );
            bHasValidGeometryName = FALSE;
            bHasValidGeometryElementPath = FALSE;
            bHasFoundGeomType = FALSE;
        }
        else if( psThis->eType == CXT_Element &&
            strcmp(psThis->pszValue, "GeometryName") == 0 )
        {
            bHasFoundGeomElements = TRUE;

            if( bHasValidGeometryName )
            {
                AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, TRUE ) );
                bHasValidGeometryName = FALSE;
                bHasValidGeometryElementPath = FALSE;
                bHasFoundGeomType = FALSE;
                pszGPath = "";
                nGeomType = wkbUnknown;
            }
            pszGName = CPLGetXMLValue( psThis, NULL, "" );
            bHasValidGeometryName = TRUE;
        }
        else if( psThis->eType == CXT_Element &&
            strcmp(psThis->pszValue, "GeometryElementPath") == 0 )
        {
            bHasFoundGeomElements = TRUE;

            if( bHasValidGeometryElementPath )
            {
                AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, TRUE ) );
                bHasValidGeometryName = FALSE;
                bHasValidGeometryElementPath = FALSE;
                bHasFoundGeomType = FALSE;
                pszGName = "";
                nGeomType = wkbUnknown;
            }
            pszGPath = CPLGetXMLValue( psThis, NULL, "" );
            bHasValidGeometryElementPath = TRUE;
        }
        else if( psThis->eType == CXT_Element &&
                 strcmp(psThis->pszValue, "GeometryType") == 0 )
        {
            bHasFoundGeomElements = TRUE;

            if( bHasFoundGeomType )
            {
                AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, TRUE ) );
                bHasValidGeometryName = FALSE;
                bHasValidGeometryElementPath = FALSE;
                bHasFoundGeomType = FALSE;
                pszGName = "";
                pszGPath = "";
                nGeomType = wkbUnknown;
            }
            const char* pszGeometryType = CPLGetXMLValue( psThis, NULL, NULL );
            nGeomType = wkbUnknown;
            if( pszGeometryType != NULL && !EQUAL(pszGeometryType, "0") )
            {
                nGeomType = atoi(pszGeometryType);
                OGRwkbGeometryType nFlattenGeomType = wkbFlatten(nGeomType);
                if( nGeomType == 100 || EQUAL(pszGeometryType, "NONE") )
                {
                    bHasValidGeometryElementPath = FALSE;
                    bHasFoundGeomType = FALSE;
                    break;
                }
                else if( nGeomType != 0 && !(nFlattenGeomType >= wkbPoint && nFlattenGeomType <= wkbMultiSurface) )
                {
                    nGeomType = wkbUnknown;
                    CPLError(CE_Warning, CPLE_AppDefined, "Unrecognised geometry type : %s",
                            pszGeometryType);
                }
                else if( nGeomType == 0 )
                    nGeomType = OGRFromOGCGeomType(pszGeometryType);
            }
            bHasFoundGeomType = TRUE;
        }
    }

    /* If there was a dangling <GeometryElementPath> or <GeometryType> or */
    /* that no explicit geometry information has been found, then add */
    /* a geometry field */
    if( bHasValidGeometryElementPath || bHasFoundGeomType || !bHasFoundGeomElements )
    {
        AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, TRUE ) );
    }

    SetSRSName( CPLGetXMLValue( psRoot, "SRSName", NULL ) );

/* -------------------------------------------------------------------- */
/*      Collect dataset specific info.                                  */
/* -------------------------------------------------------------------- */
    CPLXMLNode *psDSI = CPLGetXMLNode( psRoot, "DatasetSpecificInfo" );
    if( psDSI != NULL )
    {
        const char *pszValue;

        pszValue = CPLGetXMLValue( psDSI, "FeatureCount", NULL );
        if( pszValue != NULL )
            SetFeatureCount( CPLAtoGIntBig(pszValue) );

        // Eventually we should support XML subtrees.
        pszValue = CPLGetXMLValue( psDSI, "ExtraInfo", NULL );
        if( pszValue != NULL )
            SetExtraInfo( pszValue );

        if( CPLGetXMLValue( psDSI, "ExtentXMin", NULL ) != NULL 
            && CPLGetXMLValue( psDSI, "ExtentXMax", NULL ) != NULL
            && CPLGetXMLValue( psDSI, "ExtentYMin", NULL ) != NULL
            && CPLGetXMLValue( psDSI, "ExtentYMax", NULL ) != NULL )
        {
            SetExtents( CPLAtof(CPLGetXMLValue( psDSI, "ExtentXMin", "0.0" )),
                        CPLAtof(CPLGetXMLValue( psDSI, "ExtentXMax", "0.0" )),
                        CPLAtof(CPLGetXMLValue( psDSI, "ExtentYMin", "0.0" )),
                        CPLAtof(CPLGetXMLValue( psDSI, "ExtentYMax", "0.0" )) );
        }
    }
    
/* -------------------------------------------------------------------- */
/*      Collect property definitions.                                   */
/* -------------------------------------------------------------------- */
    for( psThis = psRoot->psChild; psThis != NULL; psThis = psThis->psNext )
    {
        if( psThis->eType == CXT_Element &&
            EQUAL(psThis->pszValue, "PropertyDefn") )
        {
            const char *pszName = CPLGetXMLValue( psThis, "Name", NULL );
            const char *pszType = CPLGetXMLValue( psThis, "Type", "Untyped" );
            const char *pszSubType = CPLGetXMLValue( psThis, "Subtype", "" );
            const char *pszCondition = CPLGetXMLValue( psThis, "Condition", NULL );
            int bNullable = CSLTestBoolean(CPLGetXMLValue( psThis, "Nullable", "true") );
            GMLPropertyDefn *poPDefn;

            if( pszName == NULL )
            {
                CPLError( CE_Failure, CPLE_AppDefined, 
                          "GMLFeatureClass %s has a PropertyDefn without a <Name>..",
                          m_pszName );
                return FALSE;
            }

            poPDefn = new GMLPropertyDefn( 
                pszName, CPLGetXMLValue( psThis, "ElementPath", NULL ) );
            
            poPDefn->SetNullable(bNullable);
            if( EQUAL(pszType,"Untyped") )
                poPDefn->SetType( GMLPT_Untyped );
            else if( EQUAL(pszType,"String") ) 
            {
                if( EQUAL(pszSubType, "Boolean") )
                {
                    poPDefn->SetType( GMLPT_Boolean );
                    poPDefn->SetWidth( 1 );
                }
                else
                {
                    poPDefn->SetType( GMLPT_String );
                    poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
                }
            }
            else if( EQUAL(pszType,"Integer") )
            {
                if( EQUAL(pszSubType, "Short") )
                {
                    poPDefn->SetType( GMLPT_Short );
                }
                else if( EQUAL(pszSubType, "Integer64") )
                {
                    poPDefn->SetType( GMLPT_Integer64 );
                }
                else
                {
                    poPDefn->SetType( GMLPT_Integer );
                }
                poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
            }
            else if( EQUAL(pszType,"Real") )
            {
                if( EQUAL(pszSubType, "Float") )
                {
                    poPDefn->SetType( GMLPT_Float );
                }
                else
                {
                    poPDefn->SetType( GMLPT_Real );
                }
                poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
                poPDefn->SetPrecision( atoi( CPLGetXMLValue( psThis, "Precision", "0" ) ) );
            }
            else if( EQUAL(pszType,"StringList") ) 
            {
                if( EQUAL(pszSubType, "Boolean") )
                    poPDefn->SetType( GMLPT_BooleanList );
                else
                    poPDefn->SetType( GMLPT_StringList );
            }
            else if( EQUAL(pszType,"IntegerList") )
            {
                if( EQUAL(pszSubType, "Integer64") )
                    poPDefn->SetType( GMLPT_Integer64List );
                else
                    poPDefn->SetType( GMLPT_IntegerList );
            }
            else if( EQUAL(pszType,"RealList") )
                poPDefn->SetType( GMLPT_RealList );
            else if( EQUAL(pszType,"Complex") )
                poPDefn->SetType( GMLPT_Complex );
            else if( EQUAL(pszType,"FeatureProperty") )
                poPDefn->SetType( GMLPT_FeatureProperty );
            else if( EQUAL(pszType,"FeaturePropertyList") )
                poPDefn->SetType( GMLPT_FeaturePropertyList );
            else
            {
                CPLError( CE_Failure, CPLE_AppDefined, 
                          "Unrecognised property type %s.", 
                          pszType );
                delete poPDefn;
                return FALSE;
            }
            if( pszCondition != NULL )
                poPDefn->SetCondition(pszCondition);

            AddProperty( poPDefn );
        }
    }

    return TRUE;
}