[gdal-dev] GML / NAS code redundancy

Martin Landa landa.martin at gmail.com
Sat Apr 5 03:36:21 PDT 2014


Dear Even,

2014-03-19 11:17 GMT+01:00 Even Rouault <even.rouault at mines-paris.org>:

> Just for Martin's enlightment, the GML driver manages to recognize several
> layers in that case since the RekisteriyksikonTietoja is the top feature
> present in the first bytes of the file, and the other feature types are sub
> feature types, also defined in RekisteriyksikonTietoja.xsd. In the case, the
> schema were simple enough so that the XSD parser could understand them.
>
> For Martin's case, I think that a .gfs will be necessary to extract properties
> in nested XML elements.

thanks a lot for your notes, it helped a lot. When working on support
for this format in OGR I found two problems.

First is related to GML registry. The input file contains different
layers based on its internal type (TypSouboru). For each of these
types are prepared separated GFS file.

    <!-- Czech VFR schame-->
    <namespace prefix="vf"
               uri="urn:cz:isvs:ruian:schemas:VymennyFormatTypy:v1
../ruian/xsd/vymenny_format/VymennyFormatTypy.xsd"
               useGlobalSRSName="true">
        <featureType elementName="TypSouboru"
                     elementValue="OB_UKSH"
                     gfsSchemaLocation="vfr_ob_uksh_v1.gfs"/>
        <featureType elementName="TypSouboru"
                     elementValue="ST_UKSH"
                     gfsSchemaLocation="vfr_st_uksh_v1.gfs"/>
        <featureType elementName="TypSouboru"
                     elementValue="ST_UKSG"
                     gfsSchemaLocation="vfr_st_uksg_v1.gfs"/>
    </namespace>

I have added a new attribute to 'osElementValue' to
'GMLRegistryFeatureType' class (see attached 'gmlregistry.diff' file).
Then the library also checks value of 'elementName' and if it's
defined and than uses related GFS.

The second problem is related to class and tag names. The layer names
are in plural form, features in singular form, eg.

<data>
  <cities>
   <city>
   ...
   </city>
  </cities>
</data>

To allow GML driver to create layer 'cities' I need to modify
'GMLHandler::startElementDefault()' method, see 'gmlhandler.diff'.

Thanks for any comments in advance, Martin

-- 
Martin Landa * http://geo.fsv.cvut.cz/gwiki/Landa
-------------- next part --------------
Index: ogr/ogrsf_frmts/gml/gmlregistry.cpp
===================================================================
--- ogr/ogrsf_frmts/gml/gmlregistry.cpp	(revision 27127)
+++ ogr/ogrsf_frmts/gml/gmlregistry.cpp	(working copy)
@@ -110,6 +110,7 @@
 int GMLRegistryFeatureType::Parse(const char* pszRegistryFilename, CPLXMLNode* psNode)
 {
     const char* pszElementName = CPLGetXMLValue(psNode, "elementName", NULL);
+    const char* pszElementValue = CPLGetXMLValue(psNode, "elementValue", NULL);
     const char* pszSchemaLocation = CPLGetXMLValue(psNode, "schemaLocation", NULL);
     const char* pszGFSSchemaLocation = CPLGetXMLValue(psNode, "gfsSchemaLocation", NULL);
     if( pszElementName == NULL || (pszSchemaLocation == NULL && pszGFSSchemaLocation == NULL) )
@@ -139,5 +140,10 @@
         osGFSSchemaLocation = pszGFSSchemaLocation;
     }
 
+    if ( pszElementValue != NULL )
+    {
+        osElementValue = pszElementValue; 
+    }
+
     return TRUE;
 }
Index: ogr/ogrsf_frmts/gml/gmlregistry.h
===================================================================
--- ogr/ogrsf_frmts/gml/gmlregistry.h	(revision 27127)
+++ ogr/ogrsf_frmts/gml/gmlregistry.h	(working copy)
@@ -39,6 +39,7 @@
 {
     public:
         CPLString                           osElementName;
+        CPLString                           osElementValue;
         CPLString                           osSchemaLocation;
         CPLString                           osGFSSchemaLocation;
 
Index: ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
===================================================================
--- ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp	(revision 27127)
+++ ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp	(working copy)
@@ -758,16 +758,26 @@
                     {
                         if( oNamespace.bUseGlobalSRSName )
                             bUseGlobalSRSName = TRUE;
-
+                        
                         for( size_t iTypename = 0;
                                     iTypename < oNamespace.aoFeatureTypes.size();
                                     iTypename ++ )
                         {
+                            const char* pszElementToFind = NULL;
+                            
                             GMLRegistryFeatureType& oFeatureType =
                                         oNamespace.aoFeatureTypes[iTypename];
-                            const char* pszElementToFind =
-                                CPLSPrintf("%s:%s", oNamespace.osPrefix.c_str(),
-                                           oFeatureType.osElementName.c_str());
+                            
+                            if ( oFeatureType.osElementValue.size() ) 
+                                pszElementToFind = CPLSPrintf("%s:%s>%s",
+                                                              oNamespace.osPrefix.c_str(),
+                                                              oFeatureType.osElementName.c_str(),
+                                                              oFeatureType.osElementValue.c_str());
+                            else
+                                pszElementToFind = CPLSPrintf("%s:%s",
+                                                              oNamespace.osPrefix.c_str(),
+                                                              oFeatureType.osElementName.c_str());
+                            
                             if( osHeader.ifind(pszElementToFind) != std::string::npos )
                             {
                                 if( oFeatureType.osSchemaLocation.size() )
-------------- next part --------------
Index: ogr/ogrsf_frmts/gml/gmlhandler.cpp
===================================================================
--- ogr/ogrsf_frmts/gml/gmlhandler.cpp	(revision 27127)
+++ ogr/ogrsf_frmts/gml/gmlhandler.cpp	(working copy)
@@ -1262,12 +1262,28 @@
                 strcmp(pszName, "FeatureCollection") == 0)) &&
              (nClassIndex = m_poReader->GetFeatureElementIndex( pszName, nLenName, eAppSchemaType )) != -1 )
     {
+        const char *pszElementName = NULL;
+        CPLString pszFilteredElementName;
+        
         m_bAlreadyFoundGeometry = FALSE;
 
-        pszFilteredClassName = m_poReader->GetFilteredClassName();
-        if ( pszFilteredClassName != NULL &&
-             strcmp(pszName, pszFilteredClassName) != 0 )
+        if ( nClassIndex < m_poReader->GetClassCount() )
+            pszElementName = m_poReader->GetClass( nClassIndex )->GetElementName();
+        pszFilteredClassName = (char *)m_poReader->GetFilteredClassName();
+        
+        if ( pszElementName != NULL )
         {
+            if ( pszElementName[m_poReader->GetState()->osPath.size()] == '|' )
+                pszFilteredElementName = pszElementName + 1 + m_poReader->GetState()->osPath.size();
+            else
+                pszFilteredElementName = (char *) pszElementName;
+        }
+        
+
+        if ( pszFilteredClassName != NULL && pszFilteredElementName != NULL &&
+             strcmp(pszName, !pszFilteredElementName.empty() ?
+                    pszFilteredElementName.c_str() : pszFilteredClassName) != 0 )
+        {
             m_nDepthFeature = m_nDepth;
 
             PUSH_STATE(STATE_IGNORED_FEATURE);
@@ -1285,7 +1301,8 @@
                     m_poReader->SetFeaturePropertyDirectly( "gid", pszGID, -1, GMLPT_String );
             }
             else
-                m_poReader->PushFeature( pszName, GetFID(attr), nClassIndex );
+                m_poReader->PushFeature( pszFilteredClassName ? pszFilteredClassName : pszName,
+                                         GetFID(attr), nClassIndex );
 
             m_nDepthFeature = m_nDepth;
 


More information about the gdal-dev mailing list