Skip to content

Commit 1d5f897

Browse files
author
mhugent
committedJan 15, 2007
Use the expat parser for the WFS provider because of smaller memory needs and possibility to incrementally parse document
git-svn-id: http://svn.osgeo.org/qgis/trunk@6434 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 5731d6b commit 1d5f897

9 files changed

+860
-9
lines changed
 

‎src/core/qgsproviderregistry.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ QgsDataProvider* QgsProviderRegistry::getProvider( QString const & providerKey,
394394
}
395395
else
396396
{
397-
QgsLogger::warning( "Failed to load ../providers/libproviders.so" );
397+
QgsLogger::warning( "Failed to load " + lib );
398398
delete myLib;
399399
return 0;
400400
}

‎src/plugins/CMakeLists.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11

2-
SUBDIRS (copyright_label delimited_text grid_maker navigation north_arrow scale_bar wfs)
2+
SUBDIRS (copyright_label delimited_text grid_maker navigation north_arrow scale_bar)
33

44
IF (POSTGRES_FOUND)
55
SUBDIRS (geoprocessing spit)
66
ENDIF (POSTGRES_FOUND)
77

88
IF (EXPAT_FOUND)
9-
SUBDIRS (gps_importer)
9+
SUBDIRS (gps_importer wfs)
1010
ENDIF (EXPAT_FOUND)
1111

1212
IF (GSL_FOUND)

‎src/plugins/wfs/CMakeLists.txt

-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ INCLUDE_DIRECTORIES(
3535
../../core ../../core/raster ../../core/renderer ../../core/symbology
3636
../../gui
3737
..
38-
../../providers/wfs
3938
../../app # for QgsNewHttpConnection
4039
${GEOS_INCLUDE_DIR}
4140
${GEOS_INCLUDE_DIR}/geos

‎src/plugins/wfs/qgswfsplugin.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#include "qgssinglesymbolrenderer.h"
2222
#include "qgsvectorlayer.h"
2323
#include "qgswfsplugin.h"
24-
#include "qgswfsprovider.h"
2524

2625
#include "mIconAddWfsLayer.xpm"
2726

‎src/providers/CMakeLists.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11

2-
SUBDIRS (ogr wms delimitedtext wfs)
2+
SUBDIRS (ogr wms delimitedtext)
33

44
IF (POSTGRES_FOUND)
55
SUBDIRS (postgres)
66
ENDIF (POSTGRES_FOUND)
77

88
IF (EXPAT_FOUND)
9-
SUBDIRS (gpx)
9+
SUBDIRS (gpx wfs)
1010
ENDIF (EXPAT_FOUND)
1111

1212
IF (GRASS_FOUND)

‎src/providers/wfs/CMakeLists.txt

+8-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22
########################################################
33
# Files
44

5-
SET(WFS_SRCS qgswfsprovider.cpp)
5+
SET(WFS_SRCS qgswfsprovider.cpp qgswfsdata.cpp)
66

7+
SET (WFS_MOC_HDRS
8+
qgswfsdata.h
9+
)
710

811
########################################################
912
# Build
@@ -14,12 +17,15 @@ INCLUDE_DIRECTORIES (
1417
../../core
1518
${GEOS_INCLUDE_DIR}
1619
${GEOS_INCLUDE_DIR}/geos
20+
${EXPAT_INCLUDE_DIR}
1721
)
1822

19-
ADD_LIBRARY (wfsprovider MODULE ${WFS_SRCS})
23+
ADD_LIBRARY (wfsprovider MODULE ${WFS_SRCS} ${WFS_MOC_SRCS})
2024

2125
TARGET_LINK_LIBRARIES (wfsprovider
2226
${QT_LIBRARIES}
27+
${GEOS_LIBRARY}
28+
${EXPAT_LIBRARY}
2329
qgis_core
2430
)
2531

‎src/providers/wfs/qgswfsdata.cpp

+677
Large diffs are not rendered by default.

‎src/providers/wfs/qgswfsdata.h

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
#ifndef QGSWFSDATA_H
2+
#define QGSWFSDATA_H
3+
4+
#include <QHttp>
5+
#include <expat.h>
6+
#include "qgis.h"
7+
#include "qgsapplication.h"
8+
#include "qgsdataprovider.h"
9+
#include "qgsfeature.h"
10+
#include "qgspoint.h"
11+
#include <list>
12+
#include <set>
13+
#include <stack>
14+
class QgsRect;
15+
class QgsSpatialRefSys;
16+
17+
18+
/**This class reads data from a WFS server or alternatively from a GML file. It uses the expat XML parser and an event based model to keep performance high. The parsing starts when the first data arrives, it does not wait until the request is finished*/
19+
class QgsWFSData: public QObject
20+
{
21+
Q_OBJECT
22+
public:
23+
QgsWFSData(const QString& uri, QgsRect* extent, QgsSpatialRefSys* srs, std::list<QgsFeature*>* features, const QString& geometryAttribute, const std::set<QString>& thematicAttributes, QGis::WKBTYPE* wkbType);
24+
~QgsWFSData();
25+
26+
/**Does the Http GET request to the wfs server
27+
@param query string (to define the requested typename)
28+
@param extent the extent of the WFS layer
29+
@param srs the reference system of the layer
30+
@param features the features of the layer
31+
@return 0 in case of success*/
32+
int getWFSData();
33+
34+
private slots:
35+
void setFinished(bool error);
36+
37+
private:
38+
39+
enum parseMode
40+
{
41+
boundingBox,
42+
featureMember,
43+
attribute,
44+
geometry,
45+
coordinate,
46+
point,
47+
line,
48+
polygon,
49+
multiPoint,
50+
multiLine,
51+
multiPolygon
52+
};
53+
54+
QgsWFSData();
55+
56+
/**XML handler methods*/
57+
void startElement(const XML_Char* el, const XML_Char** attr);
58+
void endElement(const XML_Char* el);
59+
void characters(const XML_Char* chars, int len);
60+
static void start(void* data, const XML_Char* el, const XML_Char** attr)
61+
{
62+
static_cast<QgsWFSData*>(data)->startElement(el, attr);
63+
}
64+
static void end(void* data, const XML_Char* el)
65+
{
66+
static_cast<QgsWFSData*>(data)->endElement(el);
67+
}
68+
static void chars(void* data, const XML_Char* chars, int len)
69+
{
70+
static_cast<QgsWFSData*>(data)->characters(chars, len);
71+
}
72+
73+
//helper routines
74+
/**Reads attribute srsName="EPSG:..."
75+
@param epsgNr result
76+
@param attr attribute strings
77+
@return 0 in case of success*/
78+
int readEpsgFromAttribute(int& epsgNr, const XML_Char** attr) const;
79+
/**Creates a rectangle from a coordinate string.
80+
@return 0 in case of success*/
81+
int createBBoxFromCoordinateString(QgsRect* bb, const QString& coordString) const;
82+
/**Creates a set of points from a coordinate string.
83+
@return 0 in case of success*/
84+
int pointsFromCoordinateString(std::list<QgsPoint>& points, const QString& coordString) const;
85+
int getPointWKB(unsigned char** wkb, int* size, const QgsPoint&) const;
86+
int getLineWKB(unsigned char** wkb, int* size, const std::list<QgsPoint>& lineCoordinates) const;
87+
int getRingWKB(unsigned char** wkb, int* size, const std::list<QgsPoint>& ringCoordinates) const;
88+
/**Creates a multiline from the information in mCurrentWKBFragments and mCurrentWKBFragmentSizes. Assign the result. The multiline is in mCurrentWKB and mCurrentWKBSize. The function deletes the memory in mCurrentWKBFragments. Returns 0 in case of success.*/
89+
int createMultiLineFromFragments();
90+
int createMultiPointFromFragments();
91+
int createPolygonFromFragments();
92+
int createMultiPolygonFromFragments();
93+
/**Adds all the integers contained in mCurrentWKBFragmentSizes*/
94+
int totalWKBFragmentSize() const;
95+
96+
QString mUri;
97+
//results are members such that handler routines are able to manipulate them
98+
/**Bounding box of the layer*/
99+
QgsRect* mExtent;
100+
/**Source srs of the layer*/
101+
QgsSpatialRefSys* mSrs;
102+
/**The features of the layer*/
103+
std::list<QgsFeature*>* mFeatures;
104+
/**Name of geometry attribute*/
105+
QString mGeometryAttribute;
106+
std::set<QString> mThematicAttributes;
107+
QGis::WKBTYPE* mWkbType;
108+
/**True if the request is finished*/
109+
bool mFinished;
110+
/**The HTTP client object*/
111+
QHttp mHttp;
112+
/**Keep track about the most important nested elements*/
113+
std::stack<parseMode> mParseModeStack;
114+
/**This contains the character data if an important element has been encountered*/
115+
QString mStringCash;
116+
QgsFeature* mCurrentFeature;
117+
int mFeatureCount;
118+
/**The total WKB for a feature*/
119+
unsigned char* mCurrentWKB;
120+
/**The total WKB size for a feature*/
121+
int mCurrentWKBSize;
122+
/**WKB intermediate storage during parsing. For points and lines, no intermediate WKB is stored at all. For multipoins and multilines and polygons, only one nested list is used. For multipolygons, both nested lists are used*/
123+
std::list< std::list<unsigned char*> > mCurrentWKBFragments;
124+
/**Similar to mCurrentWKB, but only the size*/
125+
std::list< std::list<int> > mCurrentWKBFragmentSizes;
126+
QString mAttributeName;
127+
/**Index where the current attribute should be inserted*/
128+
int mAttributeIndex;
129+
QString mTypeName;
130+
QgsApplication::endian_t mEndian;
131+
};
132+
133+
#endif

‎src/providers/wfs/qgswfsprovider.cpp

+37
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "qgsgeometry.h"
2323
#include "qgshttptransaction.h"
2424
#include "qgsspatialrefsys.h"
25+
#include "qgswfsdata.h"
2526
#include "qgswfsprovider.h"
2627
#include "qgslogger.h"
2728
#include <QDomDocument>
@@ -306,6 +307,7 @@ int QgsWFSProvider::describeFeatureType(const QString& uri, QString& geometryAtt
306307

307308
int QgsWFSProvider::getFeatureGET(const QString& uri, const QString& geometryAttribute)
308309
{
310+
#if 0
309311
//assemble request string
310312
QString request = uri /*+ "&OUTPUTFORMAT=gml3"*/; //use gml2 as it is supported by most wfs servers
311313
QByteArray result;
@@ -334,6 +336,41 @@ int QgsWFSProvider::getFeatureGET(const QString& uri, const QString& geometryAtt
334336
}
335337

336338
return 0;
339+
#endif
340+
341+
//try the new and faster method with the expat parser
342+
std::list<QgsFeature*> dataFeatures;
343+
std::set<QString> thematicAttributes;
344+
for(QgsFieldMap::const_iterator it = mFields.begin(); it != mFields.end(); ++it)
345+
{
346+
thematicAttributes.insert(it->name());
347+
}
348+
349+
QgsWFSData dataReader(uri, &mExtent, mSourceSRS, &dataFeatures, geometryAttribute, thematicAttributes, &mWKBType);
350+
if(dataReader.getWFSData() != 0)
351+
{
352+
qWarning("getWFSData returned with error");
353+
return 1;
354+
}
355+
356+
qWarning("feature count after request is:");
357+
qWarning(QString::number(dataFeatures.size()).toLocal8Bit().data());
358+
qWarning("mExtent after request is:");
359+
qWarning(mExtent.stringRep().toLocal8Bit().data());
360+
361+
mFeatureCount = 0;
362+
363+
QgsRect featureBBox;
364+
GEOS_GEOM::Envelope* geosBBox;
365+
for(std::list<QgsFeature*>::const_iterator it = dataFeatures.begin(); it != dataFeatures.end(); ++it)
366+
{
367+
featureBBox = (*it)->boundingBox();
368+
geosBBox = new GEOS_GEOM::Envelope(featureBBox.xMin(), featureBBox.xMax(), featureBBox.yMin(), featureBBox.yMax());
369+
mSpatialIndex.insert(geosBBox, (void*)(*it));
370+
mEnvelopesAndFeatures.push_back(std::make_pair(geosBBox, (*it)));
371+
++mFeatureCount;
372+
}
373+
return 0;
337374
}
338375

339376
int QgsWFSProvider::getFeaturePOST(const QString& uri, const QString& geometryAttribute)

0 commit comments

Comments
 (0)
Please sign in to comment.