Last active
August 17, 2017 11:26
-
-
Save jef-n/2b3f988d8d051cf6beda2fbe072e4901 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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