Skip to content
Permalink
Browse files

Changed the structure of the wfs provider such that it can now also r…

…ead gml data from file

git-svn-id: http://svn.osgeo.org/qgis/trunk@6119 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
mhugent
mhugent committed Nov 23, 2006
1 parent 9db816b commit a7b3bc4fce30354beaf00a4fb24482d7bb81e8e3
Showing with 221 additions and 74 deletions.
  1. +202 −68 src/providers/wfs/qgswfsprovider.cpp
  2. +19 −6 src/providers/wfs/qgswfsprovider.h
@@ -22,6 +22,7 @@
#include "qgslogger.h"
#include <QDomDocument>
#include <QDomNodeList>
#include <QFile>
#include <cfloat>

#ifdef WIN32
@@ -248,59 +249,57 @@ void QgsWFSProvider::select(QgsRect *mbr, bool useIntersect)

int QgsWFSProvider::getFeature(const QString& uri)
{
//GET or SOAP?
if(uri.startsWith("SOAP://"))
QString geometryAttribute;

//Local url or HTTP?
if(uri.startsWith("http://"))
{
mEncoding = QgsWFSProvider::SOAP;
mEncoding = QgsWFSProvider::GET;
}
else
{
mEncoding = QgsWFSProvider::GET;
mEncoding = QgsWFSProvider::FILE;
}

QString describeFeatureUri = uri;
describeFeatureUri.replace(QString("GetFeature"), QString("DescribeFeatureType"));
if(describeFeatureType(describeFeatureUri, mFields) != 0)
{
return 1;
}

//find out the name of the attribute containing the geometry
QString geometryAttribute;
QString currentAttribute;
for(std::vector<QgsField>::iterator iter = mFields.begin(); iter != mFields.end(); ++iter)
if(mEncoding == QgsWFSProvider::FILE)
{
currentAttribute = iter->type();
if(currentAttribute.startsWith("gml:") && currentAttribute.endsWith("PropertyType"))
{
geometryAttribute = iter->name();
//erase the geometry attribute from mFields (QGIS distinguishes between geometry and thematic attributes)
mFields.erase(iter);
break;
}
//guess geometry attribute and other attributes from schema or from .gml file
if(describeFeatureTypeFile(uri, geometryAttribute, mFields) != 0)
{
return 1;
}
}

if(mEncoding == QgsWFSProvider::SOAP)
else //take schema with describeFeatureType request
{
return getFeatureSOAP(uri, geometryAttribute);
QString describeFeatureUri = uri;
describeFeatureUri.replace(QString("GetFeature"), QString("DescribeFeatureType"));
if(describeFeatureType(describeFeatureUri, geometryAttribute, mFields) != 0)
{
return 1;
}
}
else

if(mEncoding == QgsWFSProvider::GET)
{
return getFeatureGET(uri, geometryAttribute);
}
else//local file
{
return getFeatureFILE(uri, geometryAttribute); //read the features from disk
}
return 2;
}

int QgsWFSProvider::describeFeatureType(const QString& uri, std::vector<QgsField>& fields)
int QgsWFSProvider::describeFeatureType(const QString& uri, QString& geometryAttribute, std::vector<QgsField>& fields)
{
switch(mEncoding)
{
case QgsWFSProvider::GET:
return describeFeatureTypeGET(uri, fields);
return describeFeatureTypeGET(uri, geometryAttribute, fields);
case QgsWFSProvider::POST:
return describeFeatureTypePOST(uri, fields);
return describeFeatureTypePOST(uri, geometryAttribute, fields);
case QgsWFSProvider::SOAP:
return describeFeatureTypeSOAP(uri, fields);
return describeFeatureTypeSOAP(uri, geometryAttribute, fields);
}
return 1;
}
@@ -347,57 +346,128 @@ int QgsWFSProvider::getFeatureSOAP(const QString& uri, const QString& geometryAt
return 1; //soon...
}

int QgsWFSProvider::describeFeatureTypeGET(const QString& uri, std::vector<QgsField>& fields)
int QgsWFSProvider::getFeatureFILE(const QString& uri, const QString& geometryAttribute)
{
QFile gmlFile(uri);
if(!gmlFile.open(QIODevice::ReadOnly))
{
mValid = false;
return 1;
}

QDomDocument gmlDoc;
QString errorMsg;
int errorLine, errorColumn;
if(!gmlDoc.setContent(&gmlFile, true, &errorMsg, &errorLine, &errorColumn))
{
mValid = false;
return 2;
}

QDomElement featureCollectionElement = gmlDoc.documentElement();
//get and set Extent
if(getExtentFromGML2(&mExtent, featureCollectionElement) != 0)
{
return 3;
}

setSRSFromGML2(featureCollectionElement);

if(getFeaturesFromGML2(featureCollectionElement, geometryAttribute) != 0)
{
return 4;
}

return 0;
}

int QgsWFSProvider::describeFeatureTypeGET(const QString& uri, QString& geometryAttribute, std::vector<QgsField>& fields)
{
QByteArray result;
QgsHttpTransaction http(uri);
http.getSynchronously(result);
if(!http.getSynchronously(result))
{
return 1;
}
QDomDocument describeFeatureDocument;

if(!describeFeatureDocument.setContent(result, true))
{
return 2;
}

if(readAttributesFromSchema(describeFeatureDocument, geometryAttribute, fields) != 0)
{
return 3;
}

return 0;
}

int QgsWFSProvider::describeFeatureTypePOST(const QString& uri, QString& geometryAttribute, std::vector<QgsField>& fields)
{
return 1; //soon...
}

//find out the typename
QString tname;
QStringList tnamelist = uri.split("&");
for(int i = 0; i < tnamelist.size(); ++i)
int QgsWFSProvider::describeFeatureTypeSOAP(const QString& uri, QString& geometryAttribute, std::vector<QgsField>& fields)
{
return 1; //soon...
}

int QgsWFSProvider::describeFeatureTypeFile(const QString& uri, QString& geometryAttribute, std::vector<QgsField>& fields)
{
//first look in the schema file
QString noExtension = uri;
noExtension.chop(3);
QString schemaUri = noExtension.append("xsd");
QFile schemaFile(schemaUri);

if(schemaFile.open(QIODevice::ReadOnly))
{
if(tnamelist.at(i).startsWith("typename", Qt::CaseInsensitive))
QDomDocument schemaDoc;
if(!schemaDoc.setContent(&schemaFile, true))
{
QStringList tlist = tnamelist.at(i).split("=");
tname = tlist.at(1);
return 1; //xml file not readable or not valid
}

if(readAttributesFromSchema(schemaDoc, geometryAttribute, fields) != 0)
{
return 2;
}
return 0;
}

std::list<QString> thematicAttributes;

//remove the namespace from tname
if(tname.contains(":"))
//if this fails (e.g. no schema file), try to guess the geometry attribute and the names of the thematic attributes from the .gml file
if(guessAttributesFromFile(uri, geometryAttribute, thematicAttributes) != 0)
{
tname = tname.section(":", 1, 1);
return 1;
}

QDomDocument describeFeatureDocument;
if(!describeFeatureDocument.setContent(result, true))
fields.clear();
for(std::list<QString>::const_iterator it = thematicAttributes.begin(); it != thematicAttributes.end(); ++it)
{
return 1; //error
fields.push_back(QgsField(*it, "unknown"));
}
return 0;
}

qWarning(describeFeatureDocument.toString());
int QgsWFSProvider::readAttributesFromSchema(QDomDocument& schemaDoc, QString& geometryAttribute, std::vector<QgsField>& fields) const
{
//get the <schema> root element
QDomNodeList schemaNodeList = describeFeatureDocument.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "schema");
QDomNodeList schemaNodeList = schemaDoc.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "schema");
if(schemaNodeList.length() < 1)
{
return 2;
return 1;
}
QDomElement schemaElement = schemaNodeList.at(0).toElement();

//find <element name="tname" type = ...>
QString complexTypeType;
QDomNodeList typeElementNodeList = schemaElement.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "element");
for(int i = 0; i < typeElementNodeList.length(); ++i)
{
QDomElement typeElement = typeElementNodeList.at(i).toElement();
if(typeElement.attribute("name") == tname)
{
complexTypeType = typeElement.attribute("type");
}
}
QDomElement typeElement = typeElementNodeList.at(0).toElement();
complexTypeType = typeElement.attribute("type");

if(complexTypeType.isEmpty())
{
@@ -418,6 +488,7 @@ int QgsWFSProvider::describeFeatureTypeGET(const QString& uri, std::vector<QgsFi
if(complexTypeNodeList.at(i).toElement().attribute("name") == complexTypeType)
{
complexTypeElement = complexTypeNodeList.at(i).toElement();
break;
}
}

@@ -428,31 +499,94 @@ int QgsWFSProvider::describeFeatureTypeGET(const QString& uri, std::vector<QgsFi

//now create the attributes
QDomNodeList attributeNodeList = complexTypeElement.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "element");
if(attributeNodeList.size() < 1)
{
return 5;
}

for(int i = 0; i < attributeNodeList.length(); ++i)
{
QDomElement attributeElement = attributeNodeList.at(i).toElement();
//attribute name
QString name = attributeElement.attribute("name");
//attribute type
QString type = attributeElement.attribute("type");
if(type.isEmpty())

//is it a geometry attribute?
if(type.startsWith("gml:") && type.endsWith("PropertyType"))
{
geometryAttribute = name;
}
else //todo: distinguish between numerical and non-numerical types
{
//todo: is the type name inside a <simpleType> element?
fields.push_back(QgsField(name, type));
}
//todo: distinguish between numerical and non-numerical types
fields.push_back(QgsField(name, type));
}
return 0;
}

int QgsWFSProvider::describeFeatureTypePOST(const QString& uri, std::vector<QgsField>& fields)
int QgsWFSProvider::guessAttributesFromFile(const QString& uri, QString& geometryAttribute, std::list<QString>& thematicAttributes) const
{
return 1; //soon...
}
QFile gmlFile(uri);
if(!gmlFile.open(QIODevice::ReadOnly))
{
return 1;
}

int QgsWFSProvider::describeFeatureTypeSOAP(const QString& uri, std::vector<QgsField>& fields)
{
return 1; //soon...
QDomDocument gmlDoc;
if(!gmlDoc.setContent(&gmlFile, true))
{
return 2; //xml file not readable or not valid
}


//find gmlCollection element
QDomElement featureCollectionElement = gmlDoc.documentElement();

//get the first feature to guess attributes
QDomNodeList featureList = featureCollectionElement.elementsByTagNameNS(GML_NAMESPACE, "featureMember");
if(featureList.size() < 1)
{
return 3; //we need at least one attribute
}

QDomElement featureElement = featureList.at(0).toElement();
QDomNode attributeNode = featureElement.firstChild().firstChild();
if(attributeNode.isNull())
{
return 4;
}
QString attributeText;
QDomElement attributeChildElement;
QString attributeChildLocalName;

while(!attributeNode.isNull())//loop over attributes
{
QString attributeNodeName = attributeNode.toElement().localName();
attributeChildElement = attributeNode.firstChild().toElement();
if(attributeChildElement.isNull())//no child element means it is a thematic attribute for sure
{
thematicAttributes.push_back(attributeNode.toElement().localName());
attributeNode = attributeNode.nextSibling();
continue;
}

attributeChildLocalName = attributeChildElement.localName();
if(attributeChildLocalName == "Point" || attributeChildLocalName == "LineString" || \
attributeChildLocalName == "Polygon" || attributeChildLocalName == "MultiPoint" || \
attributeChildLocalName == "MultiLineString" || attributeChildLocalName == "MultiPolygon" || \
attributeChildLocalName == "Surface" || attributeChildLocalName == "MultiSurface")
{
geometryAttribute = attributeNode.toElement().localName(); //a geometry attribute
}
else
{
thematicAttributes.push_back(attributeNode.toElement().localName()); //a thematic attribute
}
attributeNode = attributeNode.nextSibling();
}

return 0;
}

int QgsWFSProvider::getExtentFromGML2(QgsRect* extent, const QDomElement& wfsCollectionElement) const

0 comments on commit a7b3bc4

Please sign in to comment.
You can’t perform that action at this time.