Skip to content

Commit 7dcf723

Browse files

File tree

2 files changed

+892
-185
lines changed

2 files changed

+892
-185
lines changed
 

‎src/providers/wfs/qgswfsprovider.cpp‎

Lines changed: 850 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ int QgsWFSProvider::getCapabilitiesSOAP(const QString& uri, std::list<QString>&
383383
int QgsWFSProvider::getFeatureGET(const QString& uri, const QString& geometryAttribute)
384384
{
385385
//assemble request string
386-
QString request = uri + "&OUTPUTFORMAT=gml3"; //version 1.1.1 would be correct
386+
QString request = uri /*+ "&OUTPUTFORMAT=gml3"*/; //use gml2 as it is supported by most wfs servers
387387
QByteArray result;
388388
QgsHttpTransaction http(request);
389389
http.getSynchronously(result);
@@ -397,14 +397,14 @@ int QgsWFSProvider::getFeatureGET(const QString& uri, const QString& geometryAtt
397397
QDomElement featureCollectionElement = getFeatureDocument.documentElement();
398398

399399
//get and set Extent
400-
if(getExtentFromGML(&mExtent, featureCollectionElement) != 0)
400+
if(getExtentFromGML2(&mExtent, featureCollectionElement) != 0)
401401
{
402402
return 3;
403403
}
404404

405-
setSRSFromGML(featureCollectionElement);
405+
setSRSFromGML2(featureCollectionElement);
406406

407-
if(getFeaturesFromGML(featureCollectionElement, geometryAttribute, mFeatures) != 0)
407+
if(getFeaturesFromGML2(featureCollectionElement, geometryAttribute, mFeatures) != 0)
408408
{
409409
return 4;
410410
}
@@ -440,88 +440,873 @@ int QgsWFSProvider::describeFeatureTypeGET(const QString& uri, std::vector<QgsFi
440440
}
441441
}
442442

443+
//remove the namespace from tname
444+
if(tname.contains(":"))
445+
{
446+
tname = tname.section(":", 1, 1);
447+
}
448+
443449
QDomDocument describeFeatureDocument;
444450
if(!describeFeatureDocument.setContent(result, true))
445451
{
446452
return 1; //error
447453
}
448454

449-
qWarning(describeFeatureDocument.toString());
455+
qWarning(describeFeatureDocument.toString());
456+
457+
//get the <schema> root element
458+
QDomNodeList schemaNodeList = describeFeatureDocument.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "schema");
459+
if(schemaNodeList.length() < 1)
460+
{
461+
return 2;
462+
}
463+
QDomElement schemaElement = schemaNodeList.at(0).toElement();
464+
465+
//find <element name="tname" type = ...>
466+
QString complexTypeType;
467+
QDomNodeList typeElementNodeList = schemaElement.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "element");
468+
for(int i = 0; i < typeElementNodeList.length(); ++i)
469+
{
470+
QDomElement typeElement = typeElementNodeList.at(i).toElement();
471+
if(typeElement.attribute("name") == tname)
472+
{
473+
complexTypeType = typeElement.attribute("type");
474+
}
475+
}
476+
477+
if(complexTypeType.isEmpty())
478+
{
479+
return 3;
480+
}
481+
482+
//remove the namespace on complexTypeType
483+
if(complexTypeType.contains(":"))
484+
{
485+
complexTypeType = complexTypeType.section(":", 1, 1);
486+
}
487+
488+
//find <complexType name=complexTypeType
489+
QDomElement complexTypeElement;
490+
QDomNodeList complexTypeNodeList = schemaElement.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "complexType");
491+
for(int i = 0; i < complexTypeNodeList.length(); ++i)
492+
{
493+
if(complexTypeNodeList.at(i).toElement().attribute("name") == complexTypeType)
494+
{
495+
complexTypeElement = complexTypeNodeList.at(i).toElement();
496+
}
497+
}
498+
499+
if(complexTypeElement.isNull())
500+
{
501+
return 4;
502+
}
503+
504+
//now create the attributes
505+
QDomNodeList attributeNodeList = complexTypeElement.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "element");
506+
for(int i = 0; i < attributeNodeList.length(); ++i)
507+
{
508+
QDomElement attributeElement = attributeNodeList.at(i).toElement();
509+
//attribute name
510+
QString name = attributeElement.attribute("name");
511+
//attribute type
512+
QString type = attributeElement.attribute("type");
513+
if(type.isEmpty())
514+
{
515+
//todo: is the type name inside a <simpleType> element?
516+
}
517+
//todo: distinguish between numerical and non-numerical types
518+
fields.push_back(QgsField(name, type));
519+
}
520+
return 0;
521+
}
522+
523+
int QgsWFSProvider::describeFeatureTypePOST(const QString& uri, std::vector<QgsField>& fields)
524+
{
525+
return 1; //soon...
526+
}
527+
528+
int QgsWFSProvider::describeFeatureTypeSOAP(const QString& uri, std::vector<QgsField>& fields)
529+
{
530+
return 1; //soon...
531+
}
532+
533+
int QgsWFSProvider::getExtentFromGML2(QgsRect* extent, const QDomElement& wfsCollectionElement) const
534+
{
535+
QDomNodeList boundedByList = wfsCollectionElement.elementsByTagNameNS(GML_NAMESPACE, "boundedBy");
536+
if(boundedByList.length() < 1)
537+
{
538+
return 1;
539+
}
540+
QDomElement boundedByElement = boundedByList.at(0).toElement();
541+
QDomNode childNode = boundedByElement.firstChild();
542+
if(childNode.isNull())
543+
{
544+
return 2;
545+
}
546+
547+
//support <gml:Box>, <gml:coordinates> and <gml:Envelope>,<gml::lowerCorner>,<gml::upperCorner>. What
548+
//about <gml:Envelope>, <gml:pos>?
549+
QString bboxName = childNode.localName();
550+
if(bboxName != "Box")
551+
{
552+
return 3;
553+
}
554+
555+
QDomNode coordinatesNode = childNode.firstChild();
556+
if(coordinatesNode.localName() != "coordinates")
557+
{
558+
return 4;
559+
}
560+
561+
std::list<QgsPoint> boundingPoints;
562+
if(readGML2Coordinates(boundingPoints, coordinatesNode.toElement()) != 0)
563+
{
564+
return 5;
565+
}
566+
567+
if(boundingPoints.size() != 2)
568+
{
569+
return 6;
570+
}
571+
572+
std::list<QgsPoint>::const_iterator it = boundingPoints.begin();
573+
extent->setXmin(it->x());
574+
extent->setYmin(it->y());
575+
++it;
576+
extent->setXmax(it->x());
577+
extent->setYmax(it->y());
578+
return 0;
579+
}
580+
581+
int QgsWFSProvider::setSRSFromGML2(const QDomElement& wfsCollectionElement)
582+
{
583+
QgsDebugMsg("entering QgsWFSProvider::setSRSFromGML");
584+
//search <gml:boundedBy>
585+
QDomNodeList boundedByList = wfsCollectionElement.elementsByTagNameNS(GML_NAMESPACE, "boundedBy");
586+
if(boundedByList.size() < 1)
587+
{
588+
QgsDebugMsg("Error, could not find boundedBy element");
589+
return 1;
590+
}
591+
//search <gml:Envelope>
592+
QDomElement boundedByElem = boundedByList.at(0).toElement();
593+
QDomNodeList boxList = boundedByElem.elementsByTagNameNS(GML_NAMESPACE, "Box");
594+
if(boxList.size() < 1)
595+
{
596+
QgsDebugMsg("Error, could not find Envelope element");
597+
return 2;
598+
}
599+
QDomElement boxElem = boxList.at(0).toElement();
600+
//getAttribute 'srsName'
601+
QString srsName = boxElem.attribute("srsName");
602+
if(srsName.isEmpty())
603+
{
604+
QgsDebugMsg("Error, srsName is empty");
605+
return 3;
606+
}
607+
QgsDebugMsg("srsName is: " +srsName);
608+
609+
610+
//extract the EPSG id
611+
int epsgId;
612+
bool conversionSuccess;
613+
if(srsName.contains("#"))//geoserver has "http://www.opengis.net/gml/srs/epsg.xml#4326"
614+
{
615+
epsgId = srsName.section("#", 1, 1).toInt(&conversionSuccess);
616+
if(!conversionSuccess)
617+
{
618+
return 4;
619+
}
620+
}
621+
else if(srsName.contains(":"))//mapserver has "EPSG:4326"
622+
{
623+
epsgId = srsName.section(":", 1, 1).toInt(&conversionSuccess);
624+
if(!conversionSuccess)
625+
{
626+
return 5;
627+
}
628+
}
629+
630+
mSourceSRS = new QgsSpatialRefSys();
631+
if(!mSourceSRS->createFromEpsg(epsgId))
632+
{
633+
QgsDebugMsg("Error, creation of QgsSpatialRefSys failed");
634+
delete mSourceSRS;
635+
mSourceSRS = 0;
636+
return 6;
637+
}
638+
return 0;
639+
}
640+
641+
int QgsWFSProvider::getFeaturesFromGML2(const QDomElement& wfsCollectionElement, const QString& geometryAttribute, std::vector<QgsFeature*>& features) const
642+
{
643+
QDomNodeList featureTypeNodeList = wfsCollectionElement.elementsByTagNameNS(GML_NAMESPACE, "featureMember");
644+
QDomElement currentFeatureMemberElem;
645+
QDomElement layerNameElem;
646+
QDomNode currentAttributeChild;
647+
QDomElement currentAttributeElement;
648+
int counter = 0;
649+
QgsFeature* f = 0;
650+
unsigned char* wkb = 0;
651+
int wkbSize = 0;
652+
QGis::WKBTYPE currentType;
653+
654+
for(int i = 0; i < featureTypeNodeList.size(); ++i)
655+
{
656+
f = new QgsFeature(counter);
657+
currentFeatureMemberElem = featureTypeNodeList.at(i).toElement();
658+
//the first child element is always <namespace:layer>
659+
layerNameElem = currentFeatureMemberElem.firstChild().toElement();
660+
//the children are the attributes
661+
currentAttributeChild = layerNameElem.firstChild();
662+
while(!currentAttributeChild.isNull())
663+
{
664+
currentAttributeElement = currentAttributeChild.toElement();
665+
if(currentAttributeElement.localName() != "boundedBy")
666+
{
667+
if((currentAttributeElement.localName()) != geometryAttribute) //a normal attribute
668+
{
669+
f->addAttribute(currentAttributeElement.localName(), currentAttributeElement.text(), false);
670+
}
671+
else //a geometry attribute
672+
{
673+
getWkbFromGML2(currentAttributeElement, &wkb, &wkbSize, &currentType);
674+
mWKBType = currentType; //a more sophisticated method is necessary
675+
f->setGeometryAndOwnership(wkb, wkbSize);
676+
}
677+
}
678+
currentAttributeChild = currentAttributeChild.nextSibling();
679+
}
680+
if(wkb && wkbSize > 0)
681+
{
682+
features.push_back(f);
683+
}
684+
++counter;
685+
}
686+
return 0;
687+
}
688+
689+
int QgsWFSProvider::getWkbFromGML2(const QDomNode& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
690+
{
691+
QDomNode geometryChild = geometryElement.firstChild();
692+
if(geometryChild.isNull())
693+
{
694+
return 1;
695+
}
696+
QDomElement geometryTypeElement = geometryChild.toElement();
697+
QString geomType = geometryTypeElement.localName();
698+
if(geomType == "Point")
699+
{
700+
return getWkbFromGML2Point(geometryTypeElement, wkb, wkbSize, type);
701+
}
702+
else if(geomType == "LineString")
703+
{
704+
return getWkbFromGML2LineString(geometryTypeElement, wkb, wkbSize, type);
705+
}
706+
else if(geomType == "Polygon")
707+
{
708+
return getWkbFromGML2Polygon(geometryTypeElement, wkb, wkbSize, type);
709+
}
710+
else if(geomType == "MultiPoint")
711+
{
712+
return getWkbFromGML2MultiPoint(geometryTypeElement, wkb, wkbSize, type);
713+
}
714+
else if(geomType == "MultiLineString")
715+
{
716+
return getWkbFromGML2MultiLineString(geometryTypeElement, wkb, wkbSize, type);
717+
}
718+
else if(geomType == "MultiPolygon")
719+
{
720+
return getWkbFromGML2MultiPolygon(geometryTypeElement, wkb, wkbSize, type);
721+
}
722+
else //unknown type
723+
{
724+
*wkb = 0;
725+
*wkbSize = 0;
726+
}
727+
return 0;
728+
}
729+
730+
int QgsWFSProvider::getWkbFromGML2Point(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
731+
{
732+
QDomNodeList coordList = geometryElement.elementsByTagNameNS(GML_NAMESPACE, "coordinates");
733+
if(coordList.size() < 1)
734+
{
735+
return 1;
736+
}
737+
QDomElement coordElement = coordList.at(0).toElement();
738+
std::list<QgsPoint> pointCoordinate;
739+
if(readGML2Coordinates(pointCoordinate, coordElement) != 0)
740+
{
741+
return 2;
742+
}
743+
744+
if(pointCoordinate.size() < 1)
745+
{
746+
return 3;
747+
}
748+
749+
std::list<QgsPoint>::const_iterator point_it = pointCoordinate.begin();
750+
char e = endian();
751+
double x = point_it->x();
752+
double y = point_it->y();
753+
int size = 1 + sizeof(int) + 2 * sizeof(double);
754+
*wkb = new unsigned char[size];
755+
*wkbSize = size;
756+
*type = QGis::WKBPoint;
757+
int wkbPosition = 0; //current offset from wkb beginning (in bytes)
758+
memcpy(&(*wkb)[wkbPosition], &e, 1);
759+
wkbPosition += 1;
760+
memcpy(&(*wkb)[wkbPosition], type, sizeof(int));
761+
wkbPosition += sizeof(int);
762+
memcpy(&(*wkb)[wkbPosition], &x, sizeof(double));
763+
wkbPosition += sizeof(double);
764+
memcpy(&(*wkb)[wkbPosition], &y, sizeof(double));
765+
return 0;
766+
}
767+
768+
int QgsWFSProvider::getWkbFromGML2Polygon(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
769+
{
770+
//read all the coordinates (as QgsPoint) into memory. Each linear ring has an entry in the vector
771+
std::vector<std::list<QgsPoint> > ringCoordinates;
772+
773+
//read coordinates for outer boundary
774+
QDomNodeList outerBoundaryList = geometryElement.elementsByTagNameNS(GML_NAMESPACE, "outerBoundaryIs");
775+
if(outerBoundaryList.size() < 1) //outer ring is necessary
776+
{
777+
return 1;
778+
}
779+
QDomElement coordinatesElement = outerBoundaryList.at(0).firstChild().firstChild().toElement();
780+
if(coordinatesElement.isNull())
781+
{
782+
return 2;
783+
}
784+
std::list<QgsPoint> exteriorPointList;
785+
if(readGML2Coordinates(exteriorPointList, coordinatesElement) != 0)
786+
{
787+
return 3;
788+
}
789+
ringCoordinates.push_back(exteriorPointList);
790+
791+
//read coordinates for inner boundary
792+
QDomNodeList innerBoundaryList = geometryElement.elementsByTagNameNS(GML_NAMESPACE, "innerBoundaryIs");
793+
for(int i = 0; i < innerBoundaryList.size(); ++i)
794+
{
795+
std::list<QgsPoint> interiorPointList;
796+
QDomElement coordinatesElement = innerBoundaryList.at(i).firstChild().firstChild().toElement();
797+
if(coordinatesElement.isNull())
798+
{
799+
return 4;
800+
}
801+
if(readGML2Coordinates(interiorPointList, coordinatesElement) != 0)
802+
{
803+
return 5;
804+
}
805+
ringCoordinates.push_back(interiorPointList);
806+
}
807+
808+
//calculate number of bytes to allocate
809+
int nrings = 1 + innerBoundaryList.size();
810+
int npoints = 0;//total number of points
811+
for(std::vector<std::list<QgsPoint> >::const_iterator it = ringCoordinates.begin(); it != ringCoordinates.end(); ++it)
812+
{
813+
npoints += it->size();
814+
}
815+
int size = 1 + 2 * sizeof(int) + nrings * sizeof(int) + 2 * npoints * sizeof(double);
816+
*wkb = new unsigned char[size];
817+
*wkbSize = size;
818+
*type = QGis::WKBPolygon;
819+
char e = endian();
820+
int wkbPosition = 0; //current offset from wkb beginning (in bytes)
821+
int nPointsInRing = 0;
822+
double x, y;
823+
824+
//fill the contents into *wkb
825+
memcpy(&(*wkb)[wkbPosition], &e, 1);
826+
wkbPosition += 1;
827+
memcpy(&(*wkb)[wkbPosition], type, sizeof(int));
828+
wkbPosition += sizeof(int);
829+
memcpy(&(*wkb)[wkbPosition], &nrings, sizeof(int));
830+
wkbPosition += sizeof(int);
831+
for(std::vector<std::list<QgsPoint> >::const_iterator it = ringCoordinates.begin(); it != ringCoordinates.end(); ++it)
832+
{
833+
nPointsInRing = it->size();
834+
memcpy(&(*wkb)[wkbPosition], &nPointsInRing, sizeof(int));
835+
wkbPosition += sizeof(int);
836+
//iterate through the string list converting the strings to x-/y- doubles
837+
std::list<QgsPoint>::const_iterator iter;
838+
for(iter = it->begin(); iter != it->end(); ++iter)
839+
{
840+
x = iter->x();
841+
y = iter->y();
842+
//qWarning("currentCoordinate: " + QString::number(x) + " // " + QString::number(y));
843+
memcpy(&(*wkb)[wkbPosition], &x, sizeof(double));
844+
wkbPosition += sizeof(double);
845+
memcpy(&(*wkb)[wkbPosition], &y, sizeof(double));
846+
wkbPosition += sizeof(double);
847+
}
848+
}
849+
return 0;
850+
}
851+
852+
int QgsWFSProvider::getWkbFromGML2LineString(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
853+
{
854+
QDomNodeList coordinatesList = geometryElement.elementsByTagNameNS(GML_NAMESPACE, "coordinates");
855+
if(coordinatesList.size() < 1)
856+
{
857+
return 1;
858+
}
859+
QDomElement coordinatesElement = coordinatesList.at(0).toElement();
860+
std::list<QgsPoint> lineCoordinates;
861+
if(readGML2Coordinates(lineCoordinates, coordinatesElement) != 0)
862+
{
863+
return 2;
864+
}
865+
866+
char e = endian();
867+
int size = 1 + 2 * sizeof(int) + lineCoordinates.size() * 2* sizeof(double);
868+
*wkb = new unsigned char[size];
869+
*wkbSize = size;
870+
*type = QGis::WKBLineString;
871+
int wkbPosition = 0; //current offset from wkb beginning (in bytes)
872+
double x, y;
873+
int nPoints = lineCoordinates.size();
874+
875+
//fill the contents into *wkb
876+
memcpy(&(*wkb)[wkbPosition], &e, 1);
877+
wkbPosition += 1;
878+
memcpy(&(*wkb)[wkbPosition], type, sizeof(int));
879+
wkbPosition += sizeof(int);
880+
memcpy(&(*wkb)[wkbPosition], &nPoints, sizeof(int));
881+
wkbPosition += sizeof(int);
882+
883+
std::list<QgsPoint>::const_iterator iter;
884+
for(iter = lineCoordinates.begin(); iter != lineCoordinates.end(); ++iter)
885+
{
886+
x = iter->x();
887+
y = iter->y();
888+
memcpy(&(*wkb)[wkbPosition], &x, sizeof(double));
889+
wkbPosition += sizeof(double);
890+
memcpy(&(*wkb)[wkbPosition], &y, sizeof(double));
891+
wkbPosition += sizeof(double);
892+
}
893+
return 0;
894+
}
895+
896+
int QgsWFSProvider::getWkbFromGML2MultiPoint(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
897+
{
898+
std::list<QgsPoint> pointList;
899+
std::list<QgsPoint> currentPoint;
900+
QDomNodeList pointMemberList = geometryElement.elementsByTagNameNS(GML_NAMESPACE, "pointMember");
901+
if(pointMemberList.size() < 1)
902+
{
903+
return 1;
904+
}
905+
QDomNodeList pointNodeList;
906+
QDomNodeList coordinatesList;
907+
for(int i = 0; i < pointMemberList.size(); ++i)
908+
{
909+
//<Point> element
910+
pointNodeList = pointMemberList.at(i).toElement().elementsByTagNameNS(GML_NAMESPACE, "Point");
911+
if(pointNodeList.size() < 1)
912+
{
913+
continue;
914+
}
915+
//<coordinates> element
916+
coordinatesList = pointNodeList.at(0).toElement().elementsByTagNameNS(GML_NAMESPACE, "coordinates");
917+
if(coordinatesList.size() < 1)
918+
{
919+
continue;
920+
}
921+
currentPoint.clear();
922+
if(readGML2Coordinates(currentPoint, coordinatesList.at(0).toElement()) != 0)
923+
{
924+
continue;
925+
}
926+
if(currentPoint.size() < 1)
927+
{
928+
continue;
929+
}
930+
pointList.push_back((*currentPoint.begin()));
931+
}
932+
933+
//calculate the required wkb size
934+
int size = 1 + 2 * sizeof(int) + pointList.size() * (2 * sizeof(double) + 1 + sizeof(int));
935+
*wkb = new unsigned char[size];
936+
*wkbSize = size;
937+
*type = QGis::WKBMultiPoint;
938+
939+
//fill the wkb content
940+
char e = endian();
941+
int wkbPosition = 0; //current offset from wkb beginning (in bytes)
942+
int nPoints = pointList.size(); //number of points
943+
double x, y;
944+
memcpy(&(*wkb)[wkbPosition], &e, 1);
945+
wkbPosition += 1;
946+
memcpy(&(*wkb)[wkbPosition], type, sizeof(int));
947+
wkbPosition += sizeof(int);
948+
memcpy(&(*wkb)[wkbPosition], &nPoints, sizeof(int));
949+
wkbPosition += sizeof(int);
950+
for(std::list<QgsPoint>::const_iterator it = pointList.begin(); it != pointList.end(); ++it)
951+
{
952+
memcpy(&(*wkb)[wkbPosition], &e, 1);
953+
wkbPosition += 1;
954+
memcpy(&(*wkb)[wkbPosition], type, sizeof(int));
955+
wkbPosition += sizeof(int);
956+
x = it->x();
957+
memcpy(&(*wkb)[wkbPosition], &x, sizeof(double));
958+
wkbPosition += sizeof(double);
959+
y = it->y();
960+
memcpy(&(*wkb)[wkbPosition], &y, sizeof(double));
961+
wkbPosition += sizeof(double);
962+
}
963+
return 0;
964+
}
965+
966+
int QgsWFSProvider::getWkbFromGML2MultiLineString(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
967+
{
968+
//geoserver has
969+
//<gml:MultiLineString>
970+
//<gml:lineStringMember>
971+
//<gml:LineString>
972+
973+
//mapserver has directly
974+
//<gml:MultiLineString
975+
//<gml:LineString
976+
977+
std::list<std::list<QgsPoint> > lineCoordinates; //first list: lines, second list: points of one line
978+
QDomElement currentLineStringElement;
979+
QDomNodeList currentCoordList;
980+
981+
QDomNodeList lineStringMemberList = geometryElement.elementsByTagNameNS(GML_NAMESPACE, "lineStringMember");
982+
if(lineStringMemberList.size() > 0) //geoserver
983+
{
984+
for(int i = 0; i < lineStringMemberList.size(); ++i)
985+
{
986+
QDomNodeList lineStringNodeList = geometryElement.elementsByTagNameNS(GML_NAMESPACE, "LineString");
987+
if(lineStringNodeList.size() < 1)
988+
{
989+
return 1;
990+
}
991+
currentLineStringElement = lineStringNodeList.at(0).toElement();
992+
currentCoordList = currentLineStringElement.elementsByTagNameNS(GML_NAMESPACE, "coordinates");
993+
if(currentCoordList.size() < 1)
994+
{
995+
return 2;
996+
}
997+
std::list<QgsPoint> currentPointList;
998+
if(readGML2Coordinates(currentPointList, currentCoordList.at(0).toElement()) != 0)
999+
{
1000+
return 3;
1001+
}
1002+
lineCoordinates.push_back(currentPointList);
1003+
}
1004+
}
1005+
else
1006+
{
1007+
QDomNodeList lineStringList = geometryElement.elementsByTagNameNS(GML_NAMESPACE, "LineString");
1008+
if(lineStringList.size() > 0) //mapserver
1009+
{
1010+
for(int i = 0; i < lineStringList.size(); ++i)
1011+
{
1012+
currentLineStringElement = lineStringList.at(i).toElement();
1013+
currentCoordList = currentLineStringElement.elementsByTagNameNS(GML_NAMESPACE, "coordinates");
1014+
if(currentCoordList.size() < 1)
1015+
{
1016+
return 4;
1017+
}
1018+
std::list<QgsPoint> currentPointList;
1019+
if(readGML2Coordinates(currentPointList, currentCoordList.at(0).toElement()) != 0)
1020+
{
1021+
return 5;
1022+
}
1023+
lineCoordinates.push_back(currentPointList);
1024+
}
1025+
}
1026+
else
1027+
{
1028+
return 6;
1029+
}
1030+
}
1031+
1032+
1033+
//calculate the required wkb size
1034+
int size = (lineCoordinates.size() + 1) * (1 + 2 * sizeof(int));
1035+
for(std::list<std::list<QgsPoint> >::const_iterator it = lineCoordinates.begin(); it != lineCoordinates.end(); ++it)
1036+
{
1037+
size += it->size() * 2 * sizeof(double);
1038+
}
1039+
*wkb = new unsigned char[size];
1040+
*wkbSize = size;
1041+
*type = QGis::WKBMultiLineString;
1042+
1043+
//fill the wkb content
1044+
char e = endian();
1045+
int wkbPosition = 0; //current offset from wkb beginning (in bytes)
1046+
int nLines = lineCoordinates.size();
1047+
int nPoints; //number of points in a line
1048+
double x, y;
1049+
memcpy(&(*wkb)[wkbPosition], &e, 1);
1050+
wkbPosition += 1;
1051+
memcpy(&(*wkb)[wkbPosition], type, sizeof(int));
1052+
wkbPosition += sizeof(int);
1053+
memcpy(&(*wkb)[wkbPosition], &nLines, sizeof(int));
1054+
wkbPosition += sizeof(int);
1055+
for(std::list<std::list<QgsPoint> >::const_iterator it = lineCoordinates.begin(); it != lineCoordinates.end(); ++it)
1056+
{
1057+
memcpy(&(*wkb)[wkbPosition], &e, 1);
1058+
wkbPosition += 1;
1059+
memcpy(&(*wkb)[wkbPosition], type, sizeof(int));
1060+
wkbPosition += sizeof(int);
1061+
nPoints = it->size();
1062+
memcpy(&(*wkb)[wkbPosition], &nPoints, sizeof(int));
1063+
wkbPosition += sizeof(int);
1064+
for(std::list<QgsPoint>::const_iterator iter = it->begin(); iter != it->end(); ++iter)
1065+
{
1066+
x = iter->x();
1067+
//qWarning("x is: " + QString::number(x));
1068+
y = iter->y();
1069+
//qWarning("y is: " + QString::number(y));
1070+
memcpy(&(*wkb)[wkbPosition], &x, sizeof(double));
1071+
wkbPosition += sizeof(double);
1072+
memcpy(&(*wkb)[wkbPosition], &y, sizeof(double));
1073+
wkbPosition += sizeof(double);
1074+
}
1075+
}
1076+
return 0;
1077+
}
1078+
1079+
int QgsWFSProvider::getWkbFromGML2MultiPolygon(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
1080+
{
1081+
//first list: different polygons, second list: different rings, third list: different points
1082+
std::list<std::list<std::list<QgsPoint> > > multiPolygonPoints;
1083+
QDomElement currentPolygonMemberElement;
1084+
QDomNodeList polygonList;
1085+
QDomElement currentPolygonElement;
1086+
QDomNodeList outerBoundaryList;
1087+
QDomElement currentOuterBoundaryElement;
1088+
QDomElement currentInnerBoundaryElement;
1089+
QDomNodeList innerBoundaryList;
1090+
QDomNodeList linearRingNodeList;
1091+
QDomElement currentLinearRingElement;
1092+
QDomNodeList currentCoordinateList;
1093+
1094+
QDomNodeList polygonMemberList = geometryElement.elementsByTagNameNS(GML_NAMESPACE, "polygonMember");
1095+
for(int i = 0; i < polygonMemberList.size(); ++i)
1096+
{
1097+
std::list<std::list<QgsPoint> > currentPolygonList;
1098+
currentPolygonMemberElement = polygonMemberList.at(i).toElement();
1099+
polygonList = currentPolygonMemberElement.elementsByTagNameNS(GML_NAMESPACE, "Polygon");
1100+
if(polygonList.size() < 1)
1101+
{
1102+
continue;
1103+
}
1104+
currentPolygonElement = polygonList.at(0).toElement();
1105+
1106+
//find exterior ring
1107+
outerBoundaryList = currentPolygonElement.elementsByTagNameNS(GML_NAMESPACE, "outerBoundaryIs");
1108+
if(outerBoundaryList.size() < 1)
1109+
{
1110+
continue;
1111+
}
1112+
1113+
currentOuterBoundaryElement = outerBoundaryList.at(0).toElement();
1114+
std::list<QgsPoint> ringCoordinates;
1115+
1116+
linearRingNodeList = currentOuterBoundaryElement.elementsByTagNameNS(GML_NAMESPACE, "LinearRing");
1117+
if(linearRingNodeList.size() < 1)
1118+
{
1119+
continue;
1120+
}
1121+
currentLinearRingElement = linearRingNodeList.at(i).toElement();
1122+
currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(GML_NAMESPACE, "coordinates");
1123+
if(currentCoordinateList.size() < 1)
1124+
{
1125+
continue;
1126+
}
1127+
if(readGML2Coordinates(ringCoordinates, currentCoordinateList.at(0).toElement()) != 0)
1128+
{
1129+
continue;
1130+
}
1131+
currentPolygonList.push_back(ringCoordinates);
1132+
1133+
//find interior rings
1134+
QDomNodeList innerBoundaryList = currentPolygonElement.elementsByTagNameNS(GML_NAMESPACE, "innerBoundaryIs");
1135+
for(int i = 0; i < innerBoundaryList.size(); ++i)
1136+
{
1137+
std::list<QgsPoint> ringCoordinates;
1138+
currentInnerBoundaryElement = innerBoundaryList.at(i).toElement();
1139+
linearRingNodeList = currentOuterBoundaryElement.elementsByTagNameNS(GML_NAMESPACE, "LinearRing");
1140+
if(linearRingNodeList.size() < 1)
1141+
{
1142+
continue;
1143+
}
1144+
currentLinearRingElement = linearRingNodeList.at(i).toElement();
1145+
currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(GML_NAMESPACE, "coordinates");
1146+
if(currentCoordinateList.size() < 1)
1147+
{
1148+
continue;
1149+
}
1150+
if(readGML2Coordinates(ringCoordinates, currentCoordinateList.at(0).toElement()) != 0)
1151+
{
1152+
continue;
1153+
}
1154+
currentPolygonList.push_back(ringCoordinates);
1155+
}
1156+
multiPolygonPoints.push_back(currentPolygonList);
1157+
}
4501158

451-
//get the <schema> root element
452-
QDomNodeList schemaNodeList = describeFeatureDocument.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "schema");
453-
if(schemaNodeList.length() < 1)
1159+
int size = 1 + 2 * sizeof(int);
1160+
//calculate the wkb size
1161+
for(std::list<std::list<std::list<QgsPoint> > >::const_iterator it = multiPolygonPoints.begin(); it != multiPolygonPoints.end(); ++it)
4541162
{
455-
return 2;
1163+
size += 1 + 2 * sizeof(int);
1164+
for(std::list<std::list<QgsPoint> >::const_iterator iter = it->begin(); iter != it->end(); ++iter)
1165+
{
1166+
size += sizeof(int) + 2 * iter->size() * sizeof(double);
1167+
}
4561168
}
457-
QDomElement schemaElement = schemaNodeList.at(0).toElement();
1169+
*wkb = new unsigned char[size];
1170+
*wkbSize = size;
1171+
*type = QGis::WKBMultiPolygon;
1172+
int polygonType = QGis::WKBPolygon;
1173+
char e = endian();
1174+
int wkbPosition = 0; //current offset from wkb beginning (in bytes)
1175+
double x, y;
1176+
int nPolygons = multiPolygonPoints.size();
1177+
int nRings;
1178+
int nPointsInRing;
4581179

459-
//find <element name="tname" type = ...>
460-
QString complexTypeType;
461-
QDomNodeList typeElementNodeList = schemaElement.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "element");
462-
for(int i = 0; i < typeElementNodeList.length(); ++i)
1180+
//fill the contents into *wkb
1181+
memcpy(&(*wkb)[wkbPosition], &e, 1);
1182+
wkbPosition += 1;
1183+
memcpy(&(*wkb)[wkbPosition], type, sizeof(int));
1184+
wkbPosition += sizeof(int);
1185+
memcpy(&(*wkb)[wkbPosition], &nPolygons, sizeof(int));
1186+
wkbPosition += sizeof(int);
1187+
1188+
for(std::list<std::list<std::list<QgsPoint> > >::const_iterator it = multiPolygonPoints.begin(); it != multiPolygonPoints.end(); ++it)
4631189
{
464-
QDomElement typeElement = typeElementNodeList.at(i).toElement();
465-
if(typeElement.attribute("name") == tname)
1190+
memcpy(&(*wkb)[wkbPosition], &e, 1);
1191+
wkbPosition += 1;
1192+
memcpy(&(*wkb)[wkbPosition], &polygonType, sizeof(int));
1193+
wkbPosition += sizeof(int);
1194+
nRings = it->size();
1195+
memcpy(&(*wkb)[wkbPosition], &nRings, sizeof(int));
1196+
wkbPosition += sizeof(int);
1197+
for(std::list<std::list<QgsPoint> >::const_iterator iter = it->begin(); iter != it->end(); ++iter)
4661198
{
467-
complexTypeType = typeElement.attribute("type");
1199+
nPointsInRing = iter->size();
1200+
memcpy(&(*wkb)[wkbPosition], &nPointsInRing, sizeof(int));
1201+
wkbPosition += sizeof(int);
1202+
for(std::list<QgsPoint>::const_iterator iterator = iter->begin(); iterator != iter->end(); ++iterator)
1203+
{
1204+
x = iterator->x();
1205+
y = iterator->y();
1206+
memcpy(&(*wkb)[wkbPosition], &x, sizeof(double));
1207+
wkbPosition += sizeof(double);
1208+
memcpy(&(*wkb)[wkbPosition], &y, sizeof(double));
1209+
wkbPosition += sizeof(double);
1210+
}
4681211
}
4691212
}
1213+
return 0;
1214+
}
4701215

471-
if(complexTypeType.isEmpty())
1216+
int QgsWFSProvider::readGML2Coordinates(std::list<QgsPoint>& coords, const QDomElement elem) const
1217+
{
1218+
QString coordSeparator = ",";
1219+
QString tupelSeparator = " ";
1220+
//"decimal" has to be "."
1221+
1222+
coords.clear();
1223+
1224+
if(elem.hasAttribute("cs"))
4721225
{
473-
return 3;
1226+
coordSeparator = elem.attribute("cs");
1227+
}
1228+
if(elem.hasAttribute("ts"))
1229+
{
1230+
tupelSeparator = elem.attribute("ts");
4741231
}
4751232

476-
//remove the namespace on complexTypeType
477-
complexTypeType = complexTypeType.section(':', 1, 1);
1233+
QStringList tupels = elem.text().split(tupelSeparator, QString::SkipEmptyParts);
1234+
QStringList tupel_coords;
1235+
double x, y;
1236+
bool conversionSuccess;
4781237

479-
//find <complexType name=complexTypeType
480-
QDomElement complexTypeElement;
481-
QDomNodeList complexTypeNodeList = schemaElement.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "complexType");
482-
for(int i = 0; i < complexTypeNodeList.length(); ++i)
1238+
QStringList::const_iterator it;
1239+
for(it = tupels.constBegin(); it != tupels.constEnd(); ++it)
4831240
{
484-
if(complexTypeNodeList.at(i).toElement().attribute("name") == complexTypeType)
1241+
tupel_coords = (*it).split(coordSeparator, QString::SkipEmptyParts);
1242+
if(tupel_coords.size() < 2)
4851243
{
486-
complexTypeElement = complexTypeNodeList.at(i).toElement();
1244+
continue;
1245+
}
1246+
x = tupel_coords.at(0).toDouble(&conversionSuccess);
1247+
if(!conversionSuccess)
1248+
{
1249+
return 1;
1250+
}
1251+
y = tupel_coords.at(1).toDouble(&conversionSuccess);
1252+
if(!conversionSuccess)
1253+
{
1254+
return 1;
4871255
}
1256+
coords.push_back(QgsPoint(x, y));
4881257
}
1258+
return 0;
1259+
}
4891260

490-
if(complexTypeElement.isNull())
1261+
int QgsWFSProvider::getSrid()
1262+
{
1263+
if(mSourceSRS)
4911264
{
492-
return 4;
1265+
return mSourceSRS->srid();
4931266
}
494-
495-
//now create the attributes
496-
QDomNodeList attributeNodeList = complexTypeElement.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "element");
497-
for(int i = 0; i < attributeNodeList.length(); ++i)
1267+
else
4981268
{
499-
QDomElement attributeElement = attributeNodeList.at(i).toElement();
500-
//attribute name
501-
QString name = attributeElement.attribute("name");
502-
//attribute type
503-
QString type = attributeElement.attribute("type");
504-
if(type.isEmpty())
505-
{
506-
//todo: is the type name inside a <simpleType> element?
507-
}
508-
//todo: distinguish between numerical and non-numerical types
509-
fields.push_back(QgsField(name, type));
1269+
return 0;
5101270
}
511-
return 0;
5121271
}
5131272

514-
int QgsWFSProvider::describeFeatureTypePOST(const QString& uri, std::vector<QgsField>& fields)
1273+
QString QgsWFSProvider::name() const
5151274
{
516-
return 1; //soon...
1275+
return TEXT_PROVIDER_KEY;
5171276
}
5181277

519-
int QgsWFSProvider::describeFeatureTypeSOAP(const QString& uri, std::vector<QgsField>& fields)
1278+
QString QgsWFSProvider::description() const
5201279
{
521-
return 1; //soon...
1280+
return TEXT_PROVIDER_DESCRIPTION;
1281+
}
1282+
1283+
1284+
QGISEXTERN QgsWFSProvider* classFactory(const QString *uri)
1285+
{
1286+
return new QgsWFSProvider(*uri);
1287+
}
1288+
1289+
QGISEXTERN QString providerKey()
1290+
{
1291+
return TEXT_PROVIDER_KEY;
1292+
}
1293+
1294+
QGISEXTERN QString description()
1295+
{
1296+
return TEXT_PROVIDER_DESCRIPTION;
1297+
}
1298+
1299+
QGISEXTERN bool isProvider()
1300+
{
1301+
return true;
5221302
}
5231303

524-
int QgsWFSProvider::getExtentFromGML(QgsRect* extent, const QDomElement& wfsCollectionElement) const
1304+
1305+
1306+
//methods for reading GML3. Not needed at the moment as most servers support GML2
1307+
1308+
#if 0
1309+
int QgsWFSProvider::getExtentFromGML3(QgsRect* extent, const QDomElement& wfsCollectionElement) const
5251310
{
5261311
QDomNodeList boundedByList = wfsCollectionElement.elementsByTagNameNS(GML_NAMESPACE, "boundedBy");
5271312
if(boundedByList.length() < 1)
@@ -570,72 +1355,6 @@ int QgsWFSProvider::getExtentFromGML(QgsRect* extent, const QDomElement& wfsColl
5701355
extent->setYmin(yLow);
5711356
extent->setXmax(xRight);
5721357
extent->setYmax(yUp);
573-
574-
#if 0
575-
//lowerCorner
576-
QDomNodeList lowerCornerList = envelopeElement.elementsByTagNameNS(GML_NAMESPACE, "lowerCorner");
577-
if(lowerCornerList.length() < 1)
578-
{
579-
return 3;
580-
}
581-
QDomElement lowerCornerElement = lowerCornerList.at(0).toElement();
582-
QStringList lowerCornerStringList = lowerCornerElement.text().split(" ", QString::SkipEmptyParts);
583-
if(lowerCornerStringList.size() < 2)
584-
{
585-
return 4;
586-
}
587-
588-
bool conversionOk;
589-
double xLow = lowerCornerStringList.at(0).toDouble(&conversionOk);
590-
if(conversionOk)
591-
{
592-
extent->setXmin(xLow);
593-
}
594-
else
595-
{
596-
return 5;
597-
}
598-
double yLow = lowerCornerStringList.at(1).toDouble(&conversionOk);
599-
if(conversionOk)
600-
{
601-
extent->setYmin(yLow);
602-
}
603-
else
604-
{
605-
return 6;
606-
}
607-
608-
//upperCorner
609-
QDomNodeList upperCornerList = envelopeElement.elementsByTagNameNS(GML_NAMESPACE, "upperCorner");
610-
if(upperCornerList.length() < 1)
611-
{
612-
return 7;
613-
}
614-
QDomElement upperCornerElement = upperCornerList.at(0).toElement();
615-
QStringList upperCornerStringList = upperCornerElement.text().split(" ", QString::SkipEmptyParts);
616-
if(upperCornerStringList.size() < 2)
617-
{
618-
return 8;
619-
}
620-
double xUp = upperCornerStringList.at(0).toDouble(&conversionOk);
621-
if(conversionOk)
622-
{
623-
extent->setXmax(xUp);
624-
}
625-
else
626-
{
627-
return 9;
628-
}
629-
double yUp = upperCornerStringList.at(1).toDouble();
630-
if(conversionOk)
631-
{
632-
extent->setYmax(yUp);
633-
}
634-
else
635-
{
636-
return 10;
637-
}
638-
#endif
6391358
}
6401359
else if(bboxName == "Box")
6411360
{
@@ -702,7 +1421,7 @@ int QgsWFSProvider::getExtentFromGML(QgsRect* extent, const QDomElement& wfsColl
7021421
return 0;
7031422
}
7041423

705-
int QgsWFSProvider::getFeaturesFromGML(const QDomElement& wfsCollectionElement, const QString& geometryAttribute, std::vector<QgsFeature*>& features) const
1424+
int QgsWFSProvider::getFeaturesFromGML3(const QDomElement& wfsCollectionElement, const QString& geometryAttribute, std::vector<QgsFeature*>& features) const
7061425
{
7071426
QDomNodeList featureTypeNodeList = wfsCollectionElement.elementsByTagNameNS(GML_NAMESPACE, "featureMember");
7081427
QDomElement currentFeatureMemberElem;
@@ -734,7 +1453,7 @@ int QgsWFSProvider::getFeaturesFromGML(const QDomElement& wfsCollectionElement,
7341453
}
7351454
else //a geometry attribute
7361455
{
737-
getWkbFromGML(currentAttributeElement, &wkb, &wkbSize, &currentType);
1456+
getWkbFromGML3(currentAttributeElement, &wkb, &wkbSize, &currentType);
7381457
mWKBType = currentType; //a more sophisticated method is necessary
7391458
f->setGeometryAndOwnership(wkb, wkbSize);
7401459
}
@@ -750,7 +1469,7 @@ int QgsWFSProvider::getFeaturesFromGML(const QDomElement& wfsCollectionElement,
7501469
return 1;
7511470
}
7521471

753-
int QgsWFSProvider::getWkbFromGML(const QDomNode& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
1472+
int QgsWFSProvider::getWkbFromGML3(const QDomNode& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
7541473
{
7551474
QDomNode geometryChild = geometryElement.firstChild();
7561475
if(geometryChild.isNull())
@@ -761,23 +1480,23 @@ int QgsWFSProvider::getWkbFromGML(const QDomNode& geometryElement, unsigned char
7611480
QString geomType = geometryTypeElement.localName();
7621481
if(geomType == "Point")
7631482
{
764-
return getWkbFromGMLPoint(geometryTypeElement, wkb, wkbSize, type);
1483+
return getWkbFromGML3Point(geometryTypeElement, wkb, wkbSize, type);
7651484
}
7661485
else if(geomType == "Polygon")
7671486
{
768-
return getWkbFromGMLPolygon(geometryTypeElement, wkb, wkbSize, type);
1487+
return getWkbFromGML3Polygon(geometryTypeElement, wkb, wkbSize, type);
7691488
}
7701489
else if(geomType == "LineString")
7711490
{
772-
return getWkbFromGMLLineString(geometryTypeElement, wkb, wkbSize, type);
1491+
return getWkbFromGML3LineString(geometryTypeElement, wkb, wkbSize, type);
7731492
}
7741493
else if(geomType == "MultiCurve")
7751494
{
776-
return getWkbFromMultiCurve(geometryTypeElement, wkb, wkbSize, type);
1495+
return getWkbFromGML3MultiCurve(geometryTypeElement, wkb, wkbSize, type);
7771496
}
7781497
else if(geomType == "MultiSurface")
7791498
{
780-
return getWkbFromGMLMultiSurface(geometryTypeElement, wkb, wkbSize, type);
1499+
return getWkbFromGML3MultiSurface(geometryTypeElement, wkb, wkbSize, type);
7811500
}
7821501
else //unknown type
7831502
{
@@ -787,7 +1506,7 @@ int QgsWFSProvider::getWkbFromGML(const QDomNode& geometryElement, unsigned char
7871506
return 0;
7881507
}
7891508

790-
int QgsWFSProvider::getWkbFromGMLPoint(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
1509+
int QgsWFSProvider::getWkbFromGML3Point(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
7911510
{
7921511
QDomNodeList posList = geometryElement.elementsByTagNameNS(GML_NAMESPACE, "pos");
7931512
if(posList.size() < 1)
@@ -825,7 +1544,7 @@ int QgsWFSProvider::getWkbFromGMLPoint(const QDomElement& geometryElement, unsig
8251544
return 0;
8261545
}
8271546

828-
int QgsWFSProvider::getWkbFromGMLLineString(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
1547+
int QgsWFSProvider::getWkbFromGML3LineString(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
8291548
{
8301549
QDomNodeList posList = geometryElement.elementsByTagNameNS(GML_NAMESPACE, "posList");
8311550
if(posList.size() < 1)
@@ -868,7 +1587,7 @@ int QgsWFSProvider::getWkbFromGMLLineString(const QDomElement& geometryElement,
8681587
return 0;
8691588
}
8701589

871-
int QgsWFSProvider::getWkbFromGMLPolygon(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
1590+
int QgsWFSProvider::getWkbFromGML3Polygon(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
8721591
{
8731592
QDomNodeList exteriorList = geometryElement.elementsByTagNameNS(GML_NAMESPACE, "exterior");
8741593
if(exteriorList.size() < 1) //exterior ring is necessary
@@ -946,7 +1665,7 @@ int QgsWFSProvider::getWkbFromGMLPolygon(const QDomElement& geometryElement, uns
9461665
return 0;
9471666
}
9481667

949-
int QgsWFSProvider::getWkbFromGMLMultiSurface(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
1668+
int QgsWFSProvider::getWkbFromGML3MultiSurface(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
9501669
{
9511670
//get <surfaceMembers> tag
9521671
QDomNodeList surfaceMembersList = geometryElement.elementsByTagNameNS(GML_NAMESPACE, "surfaceMembers");
@@ -1083,7 +1802,7 @@ int QgsWFSProvider::getWkbFromGMLMultiSurface(const QDomElement& geometryElement
10831802
return 0;
10841803
}
10851804

1086-
int QgsWFSProvider::getWkbFromMultiCurve(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
1805+
int QgsWFSProvider::getWkbFromGML3MultiCurve(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const
10871806
{
10881807
QDomNodeList curveMembersList = geometryElement.elementsByTagNameNS(GML_NAMESPACE, "curveMembers");
10891808
if(curveMembersList.size() < 1)
@@ -1224,7 +1943,7 @@ int QgsWFSProvider::readCoordinatesFromPosList(std::list<QgsPoint>& coords, cons
12241943
return 0;
12251944
}
12261945

1227-
int QgsWFSProvider::setSRSFromGML(const QDomElement& wfsCollectionElement)
1946+
int QgsWFSProvider::setSRSFromGML3(const QDomElement& wfsCollectionElement)
12281947
{
12291948
QgsDebugMsg("entering QgsWFSProvider::setSRSFromGML");
12301949
//search <gml:boundedBy>
@@ -1261,46 +1980,4 @@ int QgsWFSProvider::setSRSFromGML(const QDomElement& wfsCollectionElement)
12611980
}
12621981
return 0;
12631982
}
1264-
1265-
int QgsWFSProvider::getSrid()
1266-
{
1267-
if(mSourceSRS)
1268-
{
1269-
return mSourceSRS->srid();
1270-
}
1271-
else
1272-
{
1273-
return 0;
1274-
}
1275-
}
1276-
1277-
QString QgsWFSProvider::name() const
1278-
{
1279-
return TEXT_PROVIDER_KEY;
1280-
}
1281-
1282-
QString QgsWFSProvider::description() const
1283-
{
1284-
return TEXT_PROVIDER_DESCRIPTION;
1285-
}
1286-
1287-
1288-
QGISEXTERN QgsWFSProvider* classFactory(const QString *uri)
1289-
{
1290-
return new QgsWFSProvider(*uri);
1291-
}
1292-
1293-
QGISEXTERN QString providerKey()
1294-
{
1295-
return TEXT_PROVIDER_KEY;
1296-
}
1297-
1298-
QGISEXTERN QString description()
1299-
{
1300-
return TEXT_PROVIDER_DESCRIPTION;
1301-
}
1302-
1303-
QGISEXTERN bool isProvider()
1304-
{
1305-
return true;
1306-
}
1983+
#endif //0 //methods for reading GML3

‎src/providers/wfs/qgswfsprovider.h‎

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ class QgsWFSProvider: public QgsVectorDataProvider
100100
/**Stores the minimum/maximum values for each attribute
101101
The position in the vector is equal to the position of an attribute in the layers attribute vector*/
102102
std::vector< std::pair<QString, QString> > mMinMaxCash;
103+
104+
/**Goes through all the features and their attributes and populates mMinMaxCash with entries*/
105+
void fillMinMaxCash();
103106

104107
/**Collects information about the field types. Is called internally from QgsWFSProvider::getFeature*/
105108
int describeFeatureType(const QString& uri, std::vector<QgsField>& fields);
@@ -116,37 +119,64 @@ class QgsWFSProvider: public QgsVectorDataProvider
116119
int describeFeatureTypeGET(const QString& uri, std::vector<QgsField>& fields);
117120
int describeFeatureTypePOST(const QString& uri, std::vector<QgsField>& fields);
118121
int describeFeatureTypeSOAP(const QString& uri, std::vector<QgsField>& fields);
122+
123+
//GML2 specific methods
124+
int getExtentFromGML2(QgsRect* extent, const QDomElement& wfsCollectionElement) const;
125+
126+
int getFeaturesFromGML2(const QDomElement& wfsCollectionElement, const QString& geometryAttribute, std::vector<QgsFeature*>& features) const;
127+
128+
int getWkbFromGML2(const QDomNode& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
129+
/**Creates WKB from a <Point> element*/
130+
int getWkbFromGML2Point(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
131+
/**Creates WKB from a <Polygon> element*/
132+
int getWkbFromGML2Polygon(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
133+
/**Creates WKB from a <LineString> element*/
134+
int getWkbFromGML2LineString(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
135+
/**Creates WKB from a <MultiPoint> element*/
136+
int getWkbFromGML2MultiPoint(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
137+
/**Creates WKB from a <MultiLineString> element*/
138+
int getWkbFromGML2MultiLineString(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
139+
/**Creates WKB from a <MultiPolygon> element*/
140+
int getWkbFromGML2MultiPolygon(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
141+
/**Reads the <gml:coordinates> element and extracts the coordinates as points
142+
@param coords list where the found coordinates are appended
143+
@param elem the <gml:coordinates> element
144+
@return 0 in case of success*/
145+
int readGML2Coordinates(std::list<QgsPoint>& coords, const QDomElement elem) const;
146+
/**Tries to create a QgsSpatialRefSys object and assign it to mSourceSRS. Returns 0 in case of success*/
147+
int setSRSFromGML2(const QDomElement& wfsCollectionElement);
148+
149+
//GML3 specific methods. Not needed at the moment as most servers support GML2
150+
#if 0
119151
/**Evaluates the <gml:boundedBy> element
120152
@return 0 in case of success*/
121-
int getExtentFromGML(QgsRect* extent, const QDomElement& wfsCollectionElement) const;
153+
int getExtentFromGML3(QgsRect* extent, const QDomElement& wfsCollectionElement) const;
122154
/**Turns GML into QGIS features
123155
@param wfsCollectionElement reference to the GML parent element
124156
@param geometryAttribute the name of the attribute containing the geometry
125157
@param features the vector where pointers to the features are filled (the features have to be deleted after usage)
126158
@return 0 in case of success*/
127-
int getFeaturesFromGML(const QDomElement& wfsCollectionElement, const QString& geometryAttribute, std::vector<QgsFeature*>& features) const;
159+
int getFeaturesFromGML3(const QDomElement& wfsCollectionElement, const QString& geometryAttribute, std::vector<QgsFeature*>& features) const;
128160
/**Turns a GML geometry attribute element (and its contents) into wkb. This function delegates the work to the geometry type specific functions below.
129161
@param wkb allocated geometry data
130162
@param wkbSize size of the allocated data
131163
@param type wkb type (point/multipoint/line/multiline/polygon/multipolygon)
132164
@return 0 in case of success*/
133-
int getWkbFromGML(const QDomNode& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
134-
int getWkbFromGMLPoint(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
135-
int getWkbFromGMLLineString(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
136-
int getWkbFromGMLPolygon(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
137-
int getWkbFromGMLMultiSurface(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
138-
int getWkbFromMultiCurve(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
165+
int getWkbFromGML3(const QDomNode& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
166+
int getWkbFromGML3Point(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
167+
int getWkbFromGML3LineString(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
168+
int getWkbFromGML3Polygon(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
169+
int getWkbFromGML3MultiSurface(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
170+
int getWkbFromGML3MultiCurve(const QDomElement& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
139171
/**Takes a <gml:pos> or <gml:posList> element and fills the coordinates into the passed list
140172
@param coords the list where the coordinates are filled into
141173
@param elem the <gml:pos> or <gml:posList> element
142174
@return 0 in case of success*/
143175
int readCoordinatesFromPosList(std::list<QgsPoint>& coords, const QDomElement elem) const;
144176

145177
/**Tries to create a QgsSpatialRefSys object and assign it to mSourceSRS. Returns 0 in case of success*/
146-
int setSRSFromGML(const QDomElement& wfsCollectionElement);
147-
148-
/***/
149-
void fillMinMaxCash();
178+
int setSRSFromGML3(const QDomElement& wfsCollectionElement);
179+
#endif //0 methods for GML3
150180
};
151181

152182
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.