Skip to content

Instantly share code, notes, and snippets.

@jef-n
Last active August 17, 2017 11:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jef-n/2b3f988d8d051cf6beda2fbe072e4901 to your computer and use it in GitHub Desktop.
Save jef-n/2b3f988d8d051cf6beda2fbe072e4901 to your computer and use it in GitHub Desktop.
diff --git a/gdal/ogr/file.lst b/gdal/ogr/file.lst
index 684660ff47..abd6875ce9 100644
--- a/gdal/ogr/file.lst
+++ b/gdal/ogr/file.lst
@@ -14,12 +14,12 @@ OBJ = ogrgeometryfactory.o \
ogrtriangulatedsurface.o \
ogrmultipoint.o \
ogrmultilinestring.o \
- ogrcircularstring.o \
- ogrcompoundcurve.o \
- ogrcurvepolygon.o \
- ogrcurvecollection.o \
- ogrmulticurve.o \
- ogrmultisurface.o \
+ ogrcircularstring.o \
+ ogrcompoundcurve.o \
+ ogrcurvepolygon.o \
+ ogrcurvecollection.o \
+ ogrmulticurve.o \
+ ogrmultisurface.o \
ogr_api.o \
ogrfeature.o \
ogrfeaturedefn.o \
@@ -54,9 +54,9 @@ OBJ = ogrgeometryfactory.o \
ogrpgeogeometry.o \
ogrgeomediageometry.o \
ogr_geocoding.o \
- osr_cs_wkt.o \
+ osr_cs_wkt.o \
osr_cs_wkt_parser.o \
- ogrgeomfielddefn.o \
- ograpispy.o \
- ogr_xerces.o \
- ogr_geo_utils.o
+ ogrgeomfielddefn.o \
+ ograpispy.o \
+ ogr_xerces.o \
+ ogr_geo_utils.o
diff --git a/gdal/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp b/gdal/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp
index 638471cd77..214d1be4f1 100644
--- a/gdal/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp
+++ b/gdal/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp
@@ -175,9 +175,9 @@ int GMLFeatureClass::AddProperty( GMLPropertyDefn *poDefn )
if( GetProperty(poDefn->GetName()) != NULL )
{
CPLError(CE_Warning, CPLE_AppDefined,
- "Field with same name (%s) already exists. "
+ "Field with same name (%s) already exists in (%s). "
"Skipping newer ones",
- poDefn->GetName());
+ poDefn->GetName(), m_pszName);
return -1;
}
@@ -212,7 +212,7 @@ int GMLFeatureClass::GetGeometryPropertyIndexBySrcElement(
{
for( int i = 0; i < m_nGeometryPropertyCount; i++ )
- if( strcmp(pszElement, m_papoGeometryProperty[i]->GetSrcElement()) == 0)
+ if( EQUAL(pszElement, m_papoGeometryProperty[i]->GetSrcElement()) )
return i;
return -1;
@@ -225,12 +225,28 @@ int GMLFeatureClass::GetGeometryPropertyIndexBySrcElement(
int GMLFeatureClass::AddGeometryProperty( GMLGeometryPropertyDefn *poDefn )
{
- if( GetGeometryPropertyIndexBySrcElement(poDefn->GetSrcElement()) >= 0 )
+ if( EQUAL( poDefn->GetSrcElement(), "" ) && !EQUAL( poDefn->GetName(), "") )
+ {
+ for( int i = 0; i < m_nGeometryPropertyCount; i++ )
+ {
+ if( EQUAL(poDefn->GetName(), m_papoGeometryProperty[i]->GetName() ) )
+ {
+ CPLError(CE_Warning, CPLE_AppDefined,
+ "Geometry field with same name (%s) already exists in (%s). "
+ "Skipping newer ones",
+ poDefn->GetName(),
+ m_pszName);
+ return -1;
+ }
+ }
+ }
+ else if( GetGeometryPropertyIndexBySrcElement(poDefn->GetSrcElement()) >= 0 )
{
CPLError(CE_Warning, CPLE_AppDefined,
- "Field with same name (%s) already exists. "
+ "Geometry field with same name (%s) already exists in (%s). "
"Skipping newer ones",
- poDefn->GetSrcElement());
+ poDefn->GetSrcElement(),
+ m_pszName);
return -1;
}
@@ -724,8 +740,8 @@ bool GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
else
{
CPLError(CE_Failure, CPLE_AppDefined,
- "Unrecognized property type %s.",
- pszType);
+ "Unrecognized property type %s in %s.",
+ pszType, pszName);
delete poPDefn;
return false;
}
diff --git a/gdal/ogr/ogrsf_frmts/gml/gmlreader.cpp b/gdal/ogr/ogrsf_frmts/gml/gmlreader.cpp
index 848bf91705..ba46907f72 100644
--- a/gdal/ogr/ogrsf_frmts/gml/gmlreader.cpp
+++ b/gdal/ogr/ogrsf_frmts/gml/gmlreader.cpp
@@ -1276,8 +1276,8 @@ bool GMLReader::SaveClasses( const char *pszFile )
/************************************************************************/
bool GMLReader::PrescanForSchema( bool bGetExtents,
- bool bAnalyzeSRSPerFeature,
- bool bOnlyDetectSRS )
+ bool bAnalyzeSRSPerFeature,
+ bool bOnlyDetectSRS )
{
if( m_pszFilename == NULL )
diff --git a/gdal/ogr/ogrsf_frmts/gml/gmlreader.h b/gdal/ogr/ogrsf_frmts/gml/gmlreader.h
index 97dfdfbff6..242fd5a9c3 100644
--- a/gdal/ogr/ogrsf_frmts/gml/gmlreader.h
+++ b/gdal/ogr/ogrsf_frmts/gml/gmlreader.h
@@ -251,6 +251,7 @@ public:
void SetGeometryDirectly( CPLXMLNode* psGeom );
void SetGeometryDirectly( int nIdx, CPLXMLNode* psGeom );
void AddGeometry( CPLXMLNode* psGeom );
+ int GetGeometryCount() const { return m_nGeometryCount; }
const CPLXMLNode* const * GetGeometryList() const { return m_papsGeometry; }
const CPLXMLNode* GetGeometryRef( int nIdx ) const;
diff --git a/gdal/ogr/ogrsf_frmts/nas/drv_nas.html b/gdal/ogr/ogrsf_frmts/nas/drv_nas.html
index 2898627577..0ac9d09725 100644
--- a/gdal/ogr/ogrsf_frmts/nas/drv_nas.html
+++ b/gdal/ogr/ogrsf_frmts/nas/drv_nas.html
@@ -7,27 +7,43 @@
<h1>NAS - ALKIS</h1>
-The NAS reader reads the NAS/ALKIS format used for cadastral data in Germany.
+<p>The NAS driver reads the NAS/ALKIS format used for cadastral data in Germany.
The format is a GML profile with fairly complex GML3 objects not easily read
-with the general OGR GML driver. <p>
-
-This driver depends on GDAL/OGR being built with the Xerces XML parsing
-library.<p>
-
-This driver was implemented within the context of the PostNAS project
-which has more information on it's use.<p>
-
-The driver looks for "opengis.net/gml" and one of the strings semicolon
-separated strings listed in the option NAS_INDICATOR (which defaults to
-"NAS-Operationen.xsd;NAS-Operationen_optional.xsd;AAA-Fachschema.xsd") to
-determine if a input is a NAS file and ignores all files without any matches.
-
-<h2>See Also</h2>
-
-<ul>
-<li> <a href="http://trac.wheregroup.com/PostNAS">PostNAS</a>
-<li> <a href="http://www.norbit.de/68/">norGIS ALKIS-Import</a>
-</ul>
+with the general OGR GML driver.</p>
+
+<p>This driver depends on GDAL/OGR being built with the Xerces XML parsing
+library.</p>
+
+<p>The driver looks for "opengis.net/gml" and one of the strings semicolon
+separated strings listed in the option <b>NAS_INDICATOR</b> (which defaults to
+"NAS-Operationen;AAA-Fachschema;aaa.xsd;aaa-suite") to
+determine if a input is a NAS file and ignores all files without any matches.</p>
+
+<p>In GDAL 2.3 a bunch of workarounds were removed, that caused the driver to
+remap or ignore some elements and attributes internally to avoid attribute
+conflicts (e.g. <i>zeigtAufExternes</i>). Instead it now takes the
+<b>NAS_GFS_TEMPLATE</b> option, that makes it possible to cleanly map element
+paths to feature attributes using a GFS file like in the GML driver. Multiple
+geometries per layer are also possible (eg. ax_flurstueck.objektkoordinaten
+next to the regular wkb_geometry).
+
+<p>A <a href="https://github.com/norBIT/alkisimport/blob/master/alkis-schema.gfs">GFS template</a> and
+a corresponding <a href="https://github.com/norBIT/alkisimport/blob/master/alkis-schema.sql">PostgreSQL schema</a>
+of the full NAS schema are part of <a href="http://www.norbit.de/68/">norGIS ALKIS-Import</a>
+(also featuring a shell script and PyQt frontend which ease the import). The
+two files were generated using <a href="https://github.com/norBIT/xmi2db/">xmi2db</a>
+(fork of <a href="https://github.com/pkorduan/xmi2db">xmi2db</a>) from the
+official application schema.</p>
+
+<p>New in 2.3 is also the option <b>NAS_NO_RELATION_LAYER</b> that allows to
+disable populating the table <i>alkis_beziehungen</i>. The information found
+there is redundant to the relation fields also contained in original
+elements/tables. Enabling the option also makes progress reporting
+available.</p>
+
+<p>This driver was implemented within the context of the
+<a href="http://trac.wheregroup.com/PostNAS">PostNAS project</a>,
+which has more information on it's use and other related projects.</p>
</body>
</html>
diff --git a/gdal/ogr/ogrsf_frmts/nas/nashandler.cpp b/gdal/ogr/ogrsf_frmts/nas/nashandler.cpp
index 99c386c49a..901d36b90c 100644
--- a/gdal/ogr/ogrsf_frmts/nas/nashandler.cpp
+++ b/gdal/ogr/ogrsf_frmts/nas/nashandler.cpp
@@ -85,6 +85,7 @@ NASHandler::NASHandler( NASReader *poReader ) :
m_nGeomAlloc(0),
m_nGeomLen(0),
m_nGeometryDepth(0),
+ m_nGeometryPropertyIndex(-1),
m_nDepth(0),
m_nDepthFeature(0),
m_bIgnoreFeature(false),
@@ -140,25 +141,12 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
transcode( localname, m_osElementName );
- if ( ( m_bIgnoreFeature && m_nDepth >= m_nDepthFeature ) ||
- ( m_osIgnoredElement != "" && m_nDepth >= m_nDepthElement ) )
+ if ( m_bIgnoreFeature && m_nDepth >= m_nDepthFeature )
{
m_nDepth ++;
return;
}
- // ignore attributes of external references and "objektkoordinaten"
- // (see PostNAS #3 and #15)
- if (m_osElementName == "zeigtAufExternes" ||
- m_osElementName== "objektkoordinaten" )
- {
- m_osIgnoredElement = m_osElementName;
- m_nDepthElement = m_nDepth;
- m_nDepth ++;
-
- return;
- }
-
#ifdef DEBUG_VERBOSE
CPLDebug( "NAS",
"%*sstartElement %s m_bIgnoreFeature:%d depth:%d "
@@ -191,6 +179,12 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
if( m_pszGeometry != NULL
|| IsGeometryElement( m_osElementName ) )
{
+ if( m_nGeometryPropertyIndex == -1 )
+ {
+ GMLFeatureClass* poClass = poState->m_poFeature->GetClass();
+ m_nGeometryPropertyIndex = poClass->GetGeometryPropertyIndexBySrcElement( poState->osPath.c_str() );
+ }
+
const int nLNLen = static_cast<int>(m_osElementName.size());
CPLString osAttributes = GetAttributes( &attrs );
@@ -290,8 +284,8 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
if( EQUAL( pszLast, "Replace" ) )
{
- //CPLAssert( m_osLastReplacingFID != "" );
- //CPLAssert( m_osLastSafeToIgnore != "" );
+ // CPLAssert( m_osLastReplacingFID != "" );
+ // CPLAssert( m_osLastSafeToIgnore != "" );
m_poReader->SetFeaturePropertyDirectly(
"replacedBy", CPLStrdup(m_osLastReplacingFID) );
m_poReader->SetFeaturePropertyDirectly(
@@ -495,16 +489,6 @@ void NASHandler::endElement( const XMLCh* const /* uri */ ,
return;
}
- if ( m_osIgnoredElement != "" && m_nDepth >= m_nDepthElement )
- {
- if ( m_nDepth == m_nDepthElement )
- {
- m_osIgnoredElement = "";
- m_nDepthElement = 0;
- }
- return;
- }
-
#ifdef DEBUG_VERBOSE
CPLDebug("NAS",
"%*sendElement %s m_bIgnoreFeature:%d depth:%d depthFeature:%d featureClass:%s",
@@ -628,13 +612,14 @@ void NASHandler::endElement( const XMLCh* const /* uri */ ,
CPLSetXMLValue( psNode, "pos", CPLSPrintf("0 0 %s", pszPos) );
}
- if ( poState->m_poFeature->GetGeometryList() &&
- poState->m_poFeature->GetGeometryList()[0] )
+ if ( m_nGeometryPropertyIndex >= 0 &&
+ m_nGeometryPropertyIndex < poState->m_poFeature->GetGeometryCount() &&
+ poState->m_poFeature->GetGeometryList()[m_nGeometryPropertyIndex] )
{
int iId = poState->m_poFeature->GetClass()->GetPropertyIndex( "gml_id" );
const GMLProperty *poIdProp = poState->m_poFeature->GetProperty(iId);
#ifdef DEBUG_VERBOSE
- char *pszOldGeom = CPLSerializeXMLTree( poState->m_poFeature->GetGeometryList()[0] );
+ char *pszOldGeom = CPLSerializeXMLTree( poState->m_poFeature->GetGeometryList()[m_nGeometryPropertyIndex] );
CPLDebug("NAS", "Overwriting other geometry (%s; replace:%s; with:%s)",
poIdProp && poIdProp->nSubProperties>0 && poIdProp->papszSubProperties[0] ? poIdProp->papszSubProperties[0] : "(null)",
@@ -649,7 +634,21 @@ void NASHandler::endElement( const XMLCh* const /* uri */ ,
#endif
}
- poState->m_poFeature->SetGeometryDirectly( psNode );
+ if( m_nGeometryPropertyIndex >= 0 )
+ poState->m_poFeature->SetGeometryDirectly( m_nGeometryPropertyIndex, psNode );
+
+ // no geometry property or property without element path
+ else if( poState->m_poFeature->GetClass()->GetGeometryPropertyCount() == 0 ||
+ ( poState->m_poFeature->GetClass()->GetGeometryPropertyCount() == 1 &&
+ poState->m_poFeature->GetClass()->GetGeometryProperty(0)->GetSrcElement() &&
+ *poState->m_poFeature->GetClass()->GetGeometryProperty(0)->GetSrcElement() == 0 ) )
+ poState->m_poFeature->SetGeometryDirectly( psNode );
+
+ else
+ CPLError( CE_Warning, CPLE_AppDefined, "NAS: Unexpected geometry skipped (class:%s path:%s geom:%s)",
+ poState->m_poFeature->GetClass()->GetName(),
+ poState->osPath.c_str(),
+ m_pszGeometry );
}
else
CPLError( CE_Warning, CPLE_AppDefined, "NAS: Invalid geometry skipped" );
@@ -660,6 +659,7 @@ void NASHandler::endElement( const XMLCh* const /* uri */ ,
CPLFree( m_pszGeometry );
m_pszGeometry = NULL;
m_nGeomAlloc = m_nGeomLen = 0;
+ m_nGeometryPropertyIndex = -1;
}
}
diff --git a/gdal/ogr/ogrsf_frmts/nas/nasreader.cpp b/gdal/ogr/ogrsf_frmts/nas/nasreader.cpp
index 626845bc30..3ed15227a8 100644
--- a/gdal/ogr/ogrsf_frmts/nas/nasreader.cpp
+++ b/gdal/ogr/ogrsf_frmts/nas/nasreader.cpp
@@ -29,16 +29,16 @@
#include "gmlreaderp.h"
#include "gmlreader.h"
+
+#include <algorithm>
+
+#include "cpl_conv.h"
#include "cpl_error.h"
+#include "cpl_multiproc.h"
#include "cpl_string.h"
#include "gmlutils.h"
-#include "cpl_multiproc.h"
-
#include "ogr_geometry.h"
-#include <algorithm>
-
-CPL_CVSID("$Id$")
/************************************************************************/
/* ==================================================================== */
@@ -47,7 +47,6 @@ CPL_CVSID("$Id$")
/************************************************************************/
#include "nasreaderp.h"
-#include "cpl_conv.h"
/************************************************************************/
/* CreateNASReader() */
@@ -88,7 +87,7 @@ NASReader::~NASReader()
{
ClearClasses();
- CPLFree( m_pszFilename );
+ CPLFree(m_pszFilename);
CleanupParser();
@@ -98,7 +97,7 @@ NASReader::~NASReader()
if( m_bXercesInitialized )
OGRDeinitializeXerces();
- CPLFree( m_pszFilteredClassName );
+ CPLFree(m_pszFilteredClassName);
}
/************************************************************************/
@@ -108,16 +107,15 @@ NASReader::~NASReader()
void NASReader::SetSourceFile( const char *pszFilename )
{
- CPLFree( m_pszFilename );
- m_pszFilename = CPLStrdup( pszFilename );
+ CPLFree(m_pszFilename);
+ m_pszFilename = CPLStrdup(pszFilename);
}
/************************************************************************/
/* GetSourceFileName() */
/************************************************************************/
-const char* NASReader::GetSourceFileName()
-
+const char *NASReader::GetSourceFileName()
{
return m_pszFilename;
}
@@ -147,19 +145,20 @@ bool NASReader::SetupParser()
CleanupParser();
// Create and initialize parser.
- XMLCh* xmlUriValid = NULL;
- XMLCh* xmlUriNS = NULL;
+ XMLCh *xmlUriValid = NULL;
+ XMLCh *xmlUriNS = NULL;
- try{
+ try
+ {
m_poSAXReader = XMLReaderFactory::createXMLReader();
- m_poNASHandler = new NASHandler( this );
+ m_poNASHandler = new NASHandler(this);
- m_poSAXReader->setContentHandler( m_poNASHandler );
- m_poSAXReader->setErrorHandler( m_poNASHandler );
- m_poSAXReader->setLexicalHandler( m_poNASHandler );
- m_poSAXReader->setEntityResolver( m_poNASHandler );
- m_poSAXReader->setDTDHandler( m_poNASHandler );
+ m_poSAXReader->setContentHandler(m_poNASHandler);
+ m_poSAXReader->setErrorHandler(m_poNASHandler);
+ m_poSAXReader->setLexicalHandler(m_poNASHandler);
+ m_poSAXReader->setEntityResolver(m_poNASHandler);
+ m_poSAXReader->setDTDHandler(m_poNASHandler);
xmlUriValid =
XMLString::transcode("http://xml.org/sax/features/validation");
@@ -167,37 +166,37 @@ bool NASReader::SetupParser()
XMLString::transcode("http://xml.org/sax/features/namespaces");
#if (OGR_GML_VALIDATION)
- m_poSAXReader->setFeature( xmlUriValid, true);
- m_poSAXReader->setFeature( xmlUriNS, true);
+ m_poSAXReader->setFeature(xmlUriValid, true);
+ m_poSAXReader->setFeature(xmlUriNS, true);
- m_poSAXReader->setFeature( XMLUni::fgSAX2CoreNameSpaces, true );
- m_poSAXReader->setFeature( XMLUni::fgXercesSchema, true );
+ m_poSAXReader->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
+ m_poSAXReader->setFeature(XMLUni::fgXercesSchema, true);
-// m_poSAXReader->setDoSchema(true);
-// m_poSAXReader->setValidationSchemaFullChecking(true);
+ // m_poSAXReader->setDoSchema(true);
+ // m_poSAXReader->setValidationSchemaFullChecking(true);
#else
- m_poSAXReader->setFeature( XMLUni::fgSAX2CoreValidation, false);
+ m_poSAXReader->setFeature(XMLUni::fgSAX2CoreValidation, false);
- m_poSAXReader->setFeature( XMLUni::fgXercesSchema, false);
+ m_poSAXReader->setFeature(XMLUni::fgXercesSchema, false);
#endif
- XMLString::release( &xmlUriValid );
- XMLString::release( &xmlUriNS );
+ XMLString::release(&xmlUriValid);
+ XMLString::release(&xmlUriNS);
}
catch (...)
{
- XMLString::release( &xmlUriValid );
- XMLString::release( &xmlUriNS );
+ XMLString::release(&xmlUriValid);
+ XMLString::release(&xmlUriNS);
- CPLError( CE_Warning, CPLE_AppDefined,
- "Exception initializing Xerces based GML reader.\n" );
+ CPLError(CE_Warning, CPLE_AppDefined,
+ "Exception initializing Xerces based GML reader.\n");
return false;
}
m_bReadStarted = false;
// Push an empty state.
- PushState( new GMLReadState() );
+ PushState(new GMLReadState());
if (m_GMLInputSource == NULL )
{
@@ -250,6 +249,7 @@ GMLFeature *NASReader::NextFeature()
{
if( m_poSAXReader == NULL )
SetupParser();
+
if( m_poSAXReader == NULL )
return NULL;
@@ -264,7 +264,7 @@ GMLFeature *NASReader::NextFeature()
poReturn = m_poCompleteFeature;
m_poCompleteFeature = NULL;
}
- catch (const XMLException& toCatch)
+ catch (const XMLException &toCatch)
{
CPLDebug( "NAS",
"Error during NextFeature()! Message:\n%s",
@@ -308,6 +308,35 @@ void NASReader::PushFeature( const char *pszElement,
GMLFeatureClass *poNewClass = new GMLFeatureClass( pszElement );
+ if( EQUAL( pszElement, "Delete" ) )
+ {
+ struct {
+ const char *pszName;
+ GMLPropertyType eType;
+ int width;
+ } types[] = {
+ { "typeName", GMLPT_String, -1 },
+ { "FeatureId", GMLPT_String, -1 },
+ { "context", GMLPT_String, -1 },
+ { "safeToIgnore", GMLPT_String, -1 },
+ { "replacedBy", GMLPT_String, -1 },
+ { "anlass", GMLPT_StringList, -1 },
+ { "endet", GMLPT_String, 20 },
+ { "ignored", GMLPT_String, -1 },
+ };
+
+ for( unsigned int i = 0; i < sizeof(types)/sizeof(*types); i++ )
+ {
+ GMLPropertyDefn *poPDefn = new GMLPropertyDefn(types[i].pszName, types[i].pszName);
+
+ poPDefn->SetType(types[i].eType);
+ if( types[i].width > 0 )
+ poPDefn->SetWidth(types[i].width);
+
+ poNewClass->AddProperty(poPDefn);
+ }
+ }
+
iClass = AddClass( poNewClass );
}
@@ -485,11 +514,11 @@ GMLFeatureClass *NASReader::GetClass( const char *pszName ) const
int NASReader::AddClass( GMLFeatureClass *poNewClass )
{
- CPLAssert( GetClass( poNewClass->GetName() ) == NULL );
+ CPLAssert( poNewClass != NULL && GetClass( poNewClass->GetName() ) == NULL );
m_nClassCount++;
- m_papoClass = (GMLFeatureClass **)
- CPLRealloc( m_papoClass, sizeof(void*) * m_nClassCount );
+ m_papoClass = static_cast<GMLFeatureClass **>(
+ CPLRealloc(m_papoClass, sizeof(void*) * m_nClassCount));
// keep delete the last entry
if( m_nClassCount > 1 &&
@@ -513,16 +542,18 @@ int NASReader::AddClass( GMLFeatureClass *poNewClass )
void NASReader::ClearClasses()
{
+ CPLDebug("NAS", "Clearing classes.");
+
for( int i = 0; i < m_nClassCount; i++ )
delete m_papoClass[i];
- CPLFree( m_papoClass );
+ CPLFree(m_papoClass);
m_nClassCount = 0;
m_papoClass = NULL;
}
/************************************************************************/
-/* SetFeatureProperty() */
+/* SetFeaturePropertyDirectly() */
/* */
/* Set the property value on the current feature, adding the */
/* property name to the GMLFeatureClass if required. */
@@ -535,7 +566,7 @@ void NASReader::SetFeaturePropertyDirectly( const char *pszElement,
{
GMLFeature *poFeature = GetState()->m_poFeature;
- CPLAssert( poFeature != NULL );
+ CPLAssert(poFeature != NULL);
/* -------------------------------------------------------------------- */
/* Does this property exist in the feature class? If not, add */
@@ -577,7 +608,7 @@ void NASReader::SetFeaturePropertyDirectly( const char *pszElement,
osFieldName += "_";
}
- GMLPropertyDefn *poPDefn = new GMLPropertyDefn(osFieldName,pszElement);
+ GMLPropertyDefn *poPDefn = new GMLPropertyDefn(osFieldName, pszElement);
if( EQUAL(CPLGetConfigOption( "GML_FIELDTYPES", ""), "ALWAYS_STRING") )
poPDefn->SetType( GMLPT_String );
@@ -594,57 +625,17 @@ void NASReader::SetFeaturePropertyDirectly( const char *pszElement,
int iId = poClass->GetPropertyIndex( "gml_id" );
const GMLProperty *poIdProp = poFeature->GetProperty(iId);
- CPLDebug( "NAS",
- "Overwriting existing property %s.%s of value '%s' "
- "with '%s' (gml_id: %s).",
- poClass->GetName(), pszElement,
- poProp->papszSubProperties[0], pszValue,
- poIdProp && poIdProp->nSubProperties>0 &&
- poIdProp->papszSubProperties &&
- poIdProp->papszSubProperties[0] ?
- poIdProp->papszSubProperties[0] : "(null)" );
- }
- }
-
-/* -------------------------------------------------------------------- */
-/* We want to handle <lage> specially to ensure it is zero */
-/* filled, and treated as a string despite 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 );
+ CPLError(CE_Warning, CPLE_AppDefined,
+ "Overwriting existing property %s.%s of value '%s' "
+ "with '%s' (gml_id: %s; type:%d).",
+ poClass->GetName(), pszElement,
+ poProp->papszSubProperties[0], pszValue,
+ poIdProp && poIdProp->nSubProperties>0 &&
+ poIdProp->papszSubProperties &&
+ poIdProp->papszSubProperties[0] ?
+ poIdProp->papszSubProperties[0] : "(null)",
+ poClass->GetProperty( iProperty )->GetType() );
}
- return;
- }
- else if( strcmp( poClass->GetProperty(iProperty)->GetName(),
- "kartendarstellung") == 0 ||
- strcmp( poClass->GetProperty(iProperty)->GetName(),
- "rechtsbehelfsverfahren") == 0 )
- {
- poFeature->SetPropertyDirectly(
- iProperty, CPLStrdup( EQUAL( pszValue, "true" ) ? "1" : "0" ) );
- CPLFree(pszValue);
-
- if( !poClass->IsSchemaLocked() )
- {
- poClass->GetProperty(iProperty)->SetType( GMLPT_Integer );
- }
- return;
}
/* -------------------------------------------------------------------- */
@@ -657,23 +648,8 @@ void NASReader::SetFeaturePropertyDirectly( const char *pszElement,
/* -------------------------------------------------------------------- */
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));
+ poClass->GetProperty(iProperty)->AnalysePropertyValue(
+ poFeature->GetProperty(iProperty));
}
}
@@ -688,71 +664,72 @@ bool NASReader::LoadClasses( const char *pszFile )
if( pszFile == NULL )
return false;
+ CPLDebug( "NAS", "Loading classes from %s", pszFile);
+
/* -------------------------------------------------------------------- */
/* Load the raw XML file. */
/* -------------------------------------------------------------------- */
- VSILFILE *fp = VSIFOpenL( pszFile, "rb" );
+ VSILFILE *fp = VSIFOpenL(pszFile, "rb");
if( fp == NULL )
{
- CPLError( CE_Failure, CPLE_OpenFailed,
- "Failed to open file %s.", pszFile );
+ CPLError(CE_Failure, CPLE_OpenFailed,
+ "Failed to open file %s.", pszFile);
return false;
}
- VSIFSeekL( fp, 0, SEEK_END );
- const int nLength = static_cast<int>(VSIFTellL( fp ));
- VSIFSeekL( fp, 0, SEEK_SET );
+ VSIFSeekL(fp, 0, SEEK_END);
+ int nLength = static_cast<int>(VSIFTellL(fp));
+ VSIFSeekL(fp, 0, SEEK_SET);
- char *pszWholeText = static_cast<char *>( VSIMalloc(nLength+1) );
+ char *pszWholeText = static_cast<char *>(VSIMalloc(nLength + 1));
if( pszWholeText == NULL )
{
- CPLError( CE_Failure, CPLE_AppDefined,
- "Failed to allocate %d byte buffer for %s,\n"
- "is this really a GMLFeatureClassList file?",
- nLength, pszFile );
- VSIFCloseL( fp );
+ CPLError(CE_Failure, CPLE_AppDefined,
+ "Failed to allocate %d byte buffer for %s,\n"
+ "is this really a GMLFeatureClassList file?",
+ nLength, pszFile);
+ VSIFCloseL(fp);
return false;
}
if( VSIFReadL( pszWholeText, nLength, 1, fp ) != 1 )
{
- VSIFree( pszWholeText );
- VSIFCloseL( fp );
- CPLError( CE_Failure, CPLE_AppDefined,
- "Read failed on %s.", pszFile );
+ VSIFree(pszWholeText);
+ VSIFCloseL(fp);
+ CPLError(CE_Failure, CPLE_AppDefined,
+ "Read failed on %s.", pszFile);
return false;
}
pszWholeText[nLength] = '\0';
- VSIFCloseL( fp );
+ VSIFCloseL(fp);
- if( strstr( pszWholeText, "<GMLFeatureClassList>" ) == NULL )
+ if( strstr(pszWholeText, "<GMLFeatureClassList" ) == NULL )
{
- VSIFree( pszWholeText );
- CPLError( CE_Failure, CPLE_AppDefined,
- "File %s does not contain a GMLFeatureClassList tree.",
- pszFile );
+ VSIFree(pszWholeText);
+ CPLError(CE_Failure, CPLE_AppDefined,
+ "File %s does not contain a GMLFeatureClassList tree.",
+ pszFile);
return false;
}
/* -------------------------------------------------------------------- */
/* Convert to XML parse tree. */
/* -------------------------------------------------------------------- */
- CPLXMLNode *psRoot = CPLParseXMLString( pszWholeText );
- VSIFree( pszWholeText );
+ CPLXMLTreeCloser psRoot(CPLParseXMLString(pszWholeText));
+ VSIFree(pszWholeText);
// We assume parser will report errors via CPL.
- if( psRoot == NULL )
+ if( psRoot.get() == NULL )
return false;
if( psRoot->eType != CXT_Element
- || !EQUAL(psRoot->pszValue,"GMLFeatureClassList") )
+ || !EQUAL(psRoot->pszValue, "GMLFeatureClassList") )
{
- CPLDestroyXMLNode(psRoot);
- CPLError( CE_Failure, CPLE_AppDefined,
- "File %s is not a GMLFeatureClassList document.",
- pszFile );
+ CPLError(CE_Failure, CPLE_AppDefined,
+ "File %s is not a GMLFeatureClassList document.",
+ pszFile);
return false;
}
@@ -764,26 +741,23 @@ bool NASReader::LoadClasses( const char *pszFile )
psThis = psThis->psNext )
{
if( psThis->eType == CXT_Element
- && EQUAL(psThis->pszValue,"GMLFeatureClass") )
+ && EQUAL(psThis->pszValue, "GMLFeatureClass") )
{
GMLFeatureClass *poClass = new GMLFeatureClass();
- if( !poClass->InitializeFromXML( psThis ) )
+ if( !poClass->InitializeFromXML(psThis) )
{
delete poClass;
- CPLDestroyXMLNode( psRoot );
return false;
}
- poClass->SetSchemaLocked( true );
+ poClass->SetSchemaLocked(true);
- AddClass( poClass );
+ AddClass(poClass);
}
}
- CPLDestroyXMLNode( psRoot );
-
- SetClassListLocked( true );
+ SetClassListLocked(true);
return true;
}
@@ -803,7 +777,7 @@ bool NASReader::SaveClasses( const char *pszFile )
/* Create in memory schema tree. */
/* -------------------------------------------------------------------- */
CPLXMLNode *psRoot =
- CPLCreateXMLNode( NULL, CXT_Element, "GMLFeatureClassList" );
+ CPLCreateXMLNode(NULL, CXT_Element, "GMLFeatureClassList");
for( int iClass = 0; iClass < GetClassCount(); iClass++ )
{
@@ -815,15 +789,17 @@ bool NASReader::SaveClasses( const char *pszFile )
/* -------------------------------------------------------------------- */
/* Serialize to disk. */
/* -------------------------------------------------------------------- */
- bool bSuccess = true;
- char *pszWholeText = CPLSerializeXMLTree( psRoot );
+ char *pszWholeText = CPLSerializeXMLTree(psRoot);
- CPLDestroyXMLNode( psRoot );
+ CPLDestroyXMLNode(psRoot);
- VSILFILE *fp = VSIFOpenL( pszFile, "wb" );
+ VSILFILE *fp = VSIFOpenL(pszFile, "wb");
+ bool bSuccess = true;
if( fp == NULL )
bSuccess = false;
+ else if( VSIFWriteL(pszWholeText, strlen(pszWholeText), 1, fp) != 1 )
+ bSuccess = false;
else
{
if( VSIFWriteL( pszWholeText, strlen(pszWholeText), 1, fp ) != 1 )
@@ -831,7 +807,7 @@ bool NASReader::SaveClasses( const char *pszFile )
VSIFCloseL( fp );
}
- CPLFree( pszWholeText );
+ CPLFree(pszWholeText);
return bSuccess;
}
@@ -852,23 +828,24 @@ bool NASReader::PrescanForSchema( bool bGetExtents,
if( m_pszFilename == NULL )
return false;
- SetClassListLocked( false );
+ CPLDebug("NAS", "Prescanning %s.", m_pszFilename );
+
+ SetClassListLocked(false);
- ClearClasses();
if( !SetupParser() )
return false;
std::string osWork;
- GMLFeature *poFeature = NULL;
+ GMLFeature *poFeature = NULL;
while( (poFeature = NextFeature()) != NULL )
{
GMLFeatureClass *poClass = poFeature->GetClass();
if( poClass->GetFeatureCount() == -1 )
- poClass->SetFeatureCount( 1 );
+ poClass->SetFeatureCount(1);
else
- poClass->SetFeatureCount( poClass->GetFeatureCount() + 1 );
+ poClass->SetFeatureCount(poClass->GetFeatureCount() + 1);
if( bGetExtents )
{
@@ -894,8 +871,8 @@ bool NASReader::PrescanForSchema( bool bGetExtents,
// Merge SRSName into layer.
const char* pszSRSName = GML_ExtractSrsNameFromGeometry(papsGeometry, osWork, false);
-// if (pszSRSName != NULL)
-// m_bCanUseGlobalSRSName = FALSE;
+ // if (pszSRSName != NULL)
+ // m_bCanUseGlobalSRSName = FALSE;
poClass->MergeSRSName(pszSRSName);
// Merge geometry type into layer.
@@ -946,6 +923,35 @@ bool NASReader::PrescanForSchema( bool bGetExtents,
CleanupParser();
+ // Skip empty classes
+ int j = 0;
+ for( int i = 0, n = m_nClassCount; i < n; i++ )
+ {
+ if( m_papoClass[i]->GetFeatureCount() > 0 )
+ {
+ m_papoClass[j++] = m_papoClass[i];
+ continue;
+ }
+
+ CPLDebug("NAS",
+ "Skipping empty layer %s.", m_papoClass[i]->GetName() );
+ }
+
+ m_nClassCount = j;
+
+ CPLDebug("NAS",
+ "%d remaining classes after prescan.\n",
+ m_nClassCount );
+
+ for( int i = 0; i < m_nClassCount; i++ )
+ {
+ CPLDebug("NAS",
+ "%s: %lld features.\n",
+ m_papoClass[i]->GetName(),
+ m_papoClass[i]->GetFeatureCount() );
+ }
+
+
return GetClassCount() > 0;
}
@@ -1060,7 +1066,7 @@ bool NASReader::ResolveXlinks( const char * /*pszFile */,
bool NASReader::SetFilteredClassName(const char* pszClassName)
{
CPLFree(m_pszFilteredClassName);
- m_pszFilteredClassName = (pszClassName) ? CPLStrdup(pszClassName) : NULL;
+ m_pszFilteredClassName = pszClassName ? CPLStrdup(pszClassName) : NULL;
return true;
}
diff --git a/gdal/ogr/ogrsf_frmts/nas/nasreaderp.h b/gdal/ogr/ogrsf_frmts/nas/nasreaderp.h
index d820f9042b..0b1f2e83ac 100644
--- a/gdal/ogr/ogrsf_frmts/nas/nasreaderp.h
+++ b/gdal/ogr/ogrsf_frmts/nas/nasreaderp.h
@@ -65,6 +65,7 @@ class NASHandler : public DefaultHandler
int m_nGeomLen;
int m_nGeometryDepth;
+ int m_nGeometryPropertyIndex;
bool IsGeometryElement( const char * );
int m_nDepth;
@@ -76,7 +77,6 @@ class NASHandler : public DefaultHandler
int m_nUpdateOrDeleteDepth;
int m_nUpdatePropertyDepth;
int m_nNameOrValueDepth;
- CPLString m_osIgnoredElement;
CPLString m_osLastTypeName;
CPLString m_osLastReplacingFID;
diff --git a/gdal/ogr/ogrsf_frmts/nas/ogr_nas.h b/gdal/ogr/ogrsf_frmts/nas/ogr_nas.h
index 7d8e8caa87..ed8c009033 100644
--- a/gdal/ogr/ogrsf_frmts/nas/ogr_nas.h
+++ b/gdal/ogr/ogrsf_frmts/nas/ogr_nas.h
@@ -44,8 +44,7 @@ class OGRNASDataSource;
class OGRNASLayer : public OGRLayer
{
- OGRSpatialReference *poSRS;
- OGRFeatureDefn *poFeatureDefn;
+ OGRFeatureDefn *poFeatureDefn;
int iNextNASId;
@@ -55,8 +54,6 @@ class OGRNASLayer : public OGRLayer
public:
OGRNASLayer( const char * pszName,
- OGRSpatialReference *poSRS,
- OGRwkbGeometryType eType,
OGRNASDataSource *poDS );
virtual ~OGRNASLayer();
diff --git a/gdal/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp b/gdal/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp
index 91476e4135..7b2e7c4da2 100644
--- a/gdal/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp
+++ b/gdal/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp
@@ -82,11 +82,11 @@ int OGRNASDataSource::Open( const char * pszNewName )
poReader = CreateNASReader();
if( poReader == NULL )
{
- CPLError( CE_Failure, CPLE_AppDefined,
- "File %s appears to be NAS but the NAS reader cannot\n"
- "be instantiated, likely because Xerces support was not\n"
- "configured in.",
- pszNewName );
+ CPLError(CE_Failure, CPLE_AppDefined,
+ "File %s appears to be NAS but the NAS reader cannot\n"
+ "be instantiated, likely because Xerces support was not\n"
+ "configured in.",
+ pszNewName );
return FALSE;
}
@@ -94,34 +94,57 @@ int OGRNASDataSource::Open( const char * pszNewName )
pszName = CPLStrdup( pszNewName );
-/* -------------------------------------------------------------------- */
-/* Can we find a NAS Feature Schema (.gfs) for the input file? */
-/* -------------------------------------------------------------------- */
bool bHaveSchema = false;
-
- const char *pszGFSFilename = CPLResetExtension( pszNewName, "gfs" );
+ const char *pszGFSFilename;
VSIStatBufL sGFSStatBuf;
- if( VSIStatL( pszGFSFilename, &sGFSStatBuf ) == 0 )
+
+ // Is some NAS Feature Schema (.gfs) TEMPLATE required?
+ const char *pszNASTemplateName = CPLGetConfigOption("NAS_GFS_TEMPLATE", NULL);
+ if( pszNASTemplateName != NULL )
{
- VSIStatBufL sNASStatBuf;
- if( VSIStatL( pszNewName, &sNASStatBuf ) == 0 &&
- sNASStatBuf.st_mtime > sGFSStatBuf.st_mtime )
+ // Load the TEMPLATE.
+ if( !poReader->LoadClasses(pszNASTemplateName) )
{
- CPLDebug( "NAS",
- "Found %s but ignoring because it appears\n"
- "be older than the associated NAS file.",
- pszGFSFilename );
+ CPLError(CE_Failure, CPLE_AppDefined,
+ "NAS schema %s could not be loaded\n",
+ pszNASTemplateName );
+ return FALSE;
}
- else
+
+ CPLDebug("NAS", "Schema loaded.");
+ }
+ else
+ {
+ /* -------------------------------------------------------------------- */
+ /* Can we find a NAS Feature Schema (.gfs) for the input file? */
+ /* -------------------------------------------------------------------- */
+ pszGFSFilename = CPLResetExtension( pszNewName, "gfs" );
+ if( VSIStatL( pszGFSFilename, &sGFSStatBuf ) == 0 )
+ {
+ VSIStatBufL sNASStatBuf;
+ if( VSIStatL( pszNewName, &sNASStatBuf ) == 0 &&
+ sNASStatBuf.st_mtime > sGFSStatBuf.st_mtime )
+ {
+ CPLDebug( "NAS",
+ "Found %s but ignoring because it appears "
+ "be older than the associated NAS file.",
+ pszGFSFilename );
+ }
+ else
+ {
+ bHaveSchema = poReader->LoadClasses( pszGFSFilename );
+ }
+ }
+
+ if( !bHaveSchema )
{
- bHaveSchema = poReader->LoadClasses( pszGFSFilename );
+ CPLError(CE_Failure, CPLE_AppDefined, "No schema information loaded");
}
}
/* -------------------------------------------------------------------- */
-/* Force a first pass to establish the schema. Eventually we */
-/* will have mechanisms for remembering the schema and related */
-/* information. */
+/* Force a first pass to establish the schema. The loaded schema */
+/* if any will be cleaned from any unavailable classes. */
/* -------------------------------------------------------------------- */
CPLErrorReset();
if( !bHaveSchema
@@ -150,13 +173,13 @@ int OGRNASDataSource::Open( const char * pszNewName )
else
{
CPLDebug( "NAS",
- "Not saving %s files already exists or can't be created.",
+ "Not saving %s. File already exists or can't be created.",
pszGFSFilename );
}
}
/* -------------------------------------------------------------------- */
-/* Translate the NASFeatureClasses into layers. */
+/* Translate the GMLFeatureClasses into layers. */
/* -------------------------------------------------------------------- */
papoLayers = (OGRLayer **)
CPLCalloc( sizeof(OGRNASLayer *), poReader->GetClassCount()+1 );
@@ -168,20 +191,23 @@ int OGRNASDataSource::Open( const char * pszNewName )
nLayers++;
}
- poRelationLayer = new OGRNASRelationLayer( this );
-
- // keep delete the last layer
- if( nLayers>0 && EQUAL( papoLayers[nLayers-1]->GetName(), "Delete" ) )
+ if( EQUAL( CPLGetConfigOption("NAS_NO_RELATION_LAYER", "NO"), "NO") || poReader->GetClassCount() == 0 )
{
- papoLayers[nLayers] = papoLayers[nLayers-1];
- papoLayers[nLayers-1] = poRelationLayer;
- }
- else
- {
- papoLayers[nLayers] = poRelationLayer;
- }
+ poRelationLayer = new OGRNASRelationLayer( this );
- nLayers++;
+ // keep delete the last layer
+ if( nLayers>0 && EQUAL( papoLayers[nLayers-1]->GetName(), "Delete" ) )
+ {
+ papoLayers[nLayers] = papoLayers[nLayers-1];
+ papoLayers[nLayers-1] = poRelationLayer;
+ }
+ else
+ {
+ papoLayers[nLayers] = poRelationLayer;
+ }
+
+ nLayers++;
+ }
return TRUE;
}
@@ -250,8 +276,7 @@ OGRNASLayer *OGRNASDataSource::TranslateNASSchema( GMLFeatureClass *poClass )
/* Create an empty layer. */
/* -------------------------------------------------------------------- */
OGRNASLayer *poLayer =
- new OGRNASLayer( poClass->GetName(), poSRS, eGType, this );
- delete poSRS;
+ new OGRNASLayer( poClass->GetName(), this );
/* -------------------------------------------------------------------- */
/* Added attributes (properties). */
@@ -287,6 +312,31 @@ OGRNASLayer *OGRNASDataSource::TranslateNASSchema( GMLFeatureClass *poClass )
poLayer->GetLayerDefn()->AddFieldDefn( &oField );
}
+ if(poSRS)
+ poSRS->Reference();
+
+ for (int iField = 0;
+ iField < poClass->GetGeometryPropertyCount();
+ iField++)
+ {
+ GMLGeometryPropertyDefn *poProperty =
+ poClass->GetGeometryProperty(iField);
+ OGRGeomFieldDefn oField(poProperty->GetName(),
+ (OGRwkbGeometryType)poProperty->GetType());
+ if (poClass->GetGeometryPropertyCount() == 1 &&
+ poClass->GetFeatureCount() == 0)
+ {
+ oField.SetType(wkbUnknown);
+ }
+
+ oField.SetSpatialRef(poSRS);
+ oField.SetNullable(poProperty->IsNullable());
+ poLayer->GetLayerDefn()->AddGeomFieldDefn(&oField);
+ }
+
+ if( poSRS )
+ poSRS->Dereference();
+
return poLayer;
}
diff --git a/gdal/ogr/ogrsf_frmts/nas/ogrnasdriver.cpp b/gdal/ogr/ogrsf_frmts/nas/ogrnasdriver.cpp
index a152c0d676..9088b2937e 100644
--- a/gdal/ogr/ogrsf_frmts/nas/ogrnasdriver.cpp
+++ b/gdal/ogr/ogrsf_frmts/nas/ogrnasdriver.cpp
@@ -77,8 +77,7 @@ static int OGRNASDriverIdentify( GDALOpenInfo* poOpenInfo )
char **papszIndicators = CSLTokenizeStringComplex(
CPLGetConfigOption(
"NAS_INDICATOR",
- "NAS-Operationen.xsd;NAS-Operationen_optional.xsd;"
- "AAA-Fachschema.xsd" ),
+ "NAS-Operationen;AAA-Fachschema;aaa.xsd;aaa-suite" ),
";", 0, 0 );
bool bFound = false;
diff --git a/gdal/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp b/gdal/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp
index bc36ac9ba3..4e5b3ac32c 100644
--- a/gdal/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp
+++ b/gdal/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp
@@ -39,21 +39,17 @@ CPL_CVSID("$Id$")
/************************************************************************/
OGRNASLayer::OGRNASLayer( const char * pszName,
- OGRSpatialReference *poSRSIn,
- OGRwkbGeometryType eReqType,
OGRNASDataSource *poDSIn ) :
- poSRS((poSRSIn != NULL) ? poSRSIn->Clone() : NULL),
poFeatureDefn(new OGRFeatureDefn(
pszName + (STARTS_WITH_CI(pszName, "ogr:") ? 4 : 0))),
iNextNASId(0),
poDS(poDSIn),
- // Readers should get the corresponding NASFeatureClass and cache it.
+ // Readers should get the corresponding GMLFeatureClass and cache it.
poFClass(poDS->GetReader()->GetClass( pszName ))
{
SetDescription( poFeatureDefn->GetName() );
poFeatureDefn->Reference();
- poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
- poFeatureDefn->SetGeomType( eReqType );
+ poFeatureDefn->SetGeomType(wkbNone);
}
/************************************************************************/
@@ -65,9 +61,6 @@ OGRNASLayer::~OGRNASLayer()
{
if( poFeatureDefn )
poFeatureDefn->Release();
-
- if( poSRS != NULL )
- poSRS->Release();
}
/************************************************************************/
@@ -80,7 +73,7 @@ void OGRNASLayer::ResetReading()
iNextNASId = 0;
poDS->GetReader()->ResetReading();
if (poFClass)
- poDS->GetReader()->SetFilteredClassName(poFClass->GetName());
+ poDS->GetReader()->SetFilteredClassName(poFClass->GetElementName());
}
/************************************************************************/
@@ -91,7 +84,6 @@ OGRFeature *OGRNASLayer::GetNextFeature()
{
GMLFeature *poNASFeature = NULL;
- OGRGeometry *poGeom = NULL;
if( iNextNASId == 0 )
ResetReading();
@@ -105,9 +97,6 @@ OGRFeature *OGRNASLayer::GetNextFeature()
/* -------------------------------------------------------------------- */
/* Cleanup last feature, and get a new raw nas feature. */
/* -------------------------------------------------------------------- */
- delete poGeom;
- poGeom = NULL;
-
delete poNASFeature;
poNASFeature = poDS->GetReader()->NextFeature();
if( poNASFeature == NULL )
@@ -132,49 +121,65 @@ OGRFeature *OGRNASLayer::GetNextFeature()
/* -------------------------------------------------------------------- */
const CPLXMLNode* const * papsGeometry =
poNASFeature->GetGeometryList();
- if (papsGeometry[0] != NULL)
- {
- CPLString osLastErrorMsg;
- CPLPushErrorHandler(CPLQuietErrorHandler);
- poGeom = (OGRGeometry*) OGR_G_CreateFromGMLTree(papsGeometry[0]);
- CPLPopErrorHandler();
- if( poGeom == NULL )
- osLastErrorMsg = CPLGetLastErrorMsg();
- poGeom = NASReader::ConvertGeometry(poGeom);
- poGeom = OGRGeometryFactory::forceTo(poGeom, GetGeomType());
- // poGeom->dumpReadable( 0, "NAS: " );
-
- if( poGeom == NULL )
+
+ std::vector < OGRGeometry * > poGeom( poNASFeature->GetGeometryCount() );
+
+ for( int iGeom = 0; iGeom < poNASFeature->GetGeometryCount(); ++iGeom ) {
+ if ( papsGeometry[iGeom] == NULL )
+ {
+ poGeom[iGeom] = NULL;
+ }
+ else
{
- CPLString osGMLId;
- if( poFClass->GetPropertyIndex("gml_id") == 0 )
+ CPLString osLastErrorMsg;
+ CPLPushErrorHandler(CPLQuietErrorHandler);
+
+ poGeom[iGeom] = (OGRGeometry*) OGR_G_CreateFromGMLTree(papsGeometry[iGeom]);
+ CPLPopErrorHandler();
+ if( poGeom[iGeom] == NULL )
+ osLastErrorMsg = CPLGetLastErrorMsg();
+ poGeom[iGeom] = NASReader::ConvertGeometry(poGeom[iGeom]);
+ poGeom[iGeom] = OGRGeometryFactory::forceTo(poGeom[iGeom], GetGeomType());
+ // poGeom->dumpReadable( 0, "NAS: " );
+
+ if( poGeom[iGeom] == NULL )
{
- const GMLProperty *psGMLProperty =
- poNASFeature->GetProperty( 0 );
- if( psGMLProperty && psGMLProperty->nSubProperties == 1 )
+ CPLString osGMLId;
+ if( poFClass->GetPropertyIndex("gml_id") == 0 )
{
- osGMLId.Printf("(gml_id=%s) ",
- psGMLProperty->papszSubProperties[0]);
+ const GMLProperty *psGMLProperty =
+ poNASFeature->GetProperty( 0 );
+ if( psGMLProperty && psGMLProperty->nSubProperties == 1 )
+ {
+ osGMLId.Printf("(gml_id=%s) ",
+ psGMLProperty->papszSubProperties[0]);
+ }
}
- }
- const bool bGoOn =CPLTestBool(
- CPLGetConfigOption("NAS_SKIP_CORRUPTED_FEATURES", "NO"));
- CPLError(bGoOn ? CE_Warning : CE_Failure, CPLE_AppDefined,
- "Geometry of feature %d %scannot be parsed: %s%s",
- iNextNASId, osGMLId.c_str(), osLastErrorMsg.c_str(),
- bGoOn ? ". Skipping to next feature.":
- ". You may set the NAS_SKIP_CORRUPTED_FEATURES "
- "configuration option to YES to skip to the next "
- "feature");
- delete poNASFeature;
- poNASFeature = NULL;
- if( bGoOn )
- continue;
- return NULL;
+ const bool bGoOn = CPLTestBool(
+ CPLGetConfigOption("NAS_SKIP_CORRUPTED_FEATURES", "NO"));
+ CPLError(bGoOn ? CE_Warning : CE_Failure, CPLE_AppDefined,
+ "Geometry of feature %d %scannot be parsed: %s%s",
+ iNextNASId, osGMLId.c_str(), osLastErrorMsg.c_str(),
+ bGoOn ? ". Skipping to next feature.":
+ ". You may set the NAS_SKIP_CORRUPTED_FEATURES "
+ "configuration option to YES to skip to the next "
+ "feature");
+ delete poNASFeature;
+ poNASFeature = NULL;
+
+ while (iGeom > 0)
+ delete poGeom[--iGeom];
+ poGeom.clear();
+
+ if( bGoOn )
+ continue;
+
+ return NULL;
+ }
}
- if( m_poFilterGeom != NULL && !FilterGeometry( poGeom ) )
+ if( m_poFilterGeom != NULL && !FilterGeometry( poGeom[iGeom]) )
continue;
}
@@ -245,8 +250,11 @@ OGRFeature *OGRNASLayer::GetNextFeature()
}
}
- poOGRFeature->SetGeometryDirectly( poGeom );
- poGeom = NULL;
+ for ( int iGeom = 0; iGeom < poNASFeature->GetGeometryCount(); ++iGeom ) {
+ poOGRFeature->SetGeomFieldDirectly(iGeom, poGeom[iGeom]);
+ poGeom[iGeom] = NULL;
+ }
+ poGeom.clear();
/* -------------------------------------------------------------------- */
/* Test against the attribute query. */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment