34#include <QRegularExpression>
37#include <netinet/in.h>
43#define GML_NAMESPACE QStringLiteral( "http://www.opengis.net/gml" )
44#define GML32_NAMESPACE QStringLiteral( "http://www.opengis.net/gml/3.2" )
45#define OGC_NAMESPACE QStringLiteral( "http://www.opengis.net/ogc" )
46#define FES_NAMESPACE QStringLiteral( "http://www.opengis.net/fes/2.0" )
51 const QString &namespacePrefix,
52 const QString &namespaceURI,
55 bool honourAxisOrientation,
56 bool invertAxisOrientation )
59 , mGMLVersion( gmlVersion )
60 , mFilterVersion( filterVersion )
61 , mNamespacePrefix( namespacePrefix )
62 , mNamespaceURI( namespaceURI )
65 , mInvertAxisOrientation( invertAxisOrientation )
66 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
67 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
71 if ( !mSrsName.isEmpty() )
77 mInvertAxisOrientation = !mInvertAxisOrientation;
84 QDomElement geometryTypeElement = geometryNode.toElement();
85 QString geomType = geometryTypeElement.tagName();
88 if ( !( geomType == QLatin1String(
"Point" ) || geomType == QLatin1String(
"LineString" ) || geomType == QLatin1String(
"Polygon" ) ||
89 geomType == QLatin1String(
"MultiPoint" ) || geomType == QLatin1String(
"MultiLineString" ) || geomType == QLatin1String(
"MultiPolygon" ) ||
90 geomType == QLatin1String(
"Box" ) || geomType == QLatin1String(
"Envelope" ) ) )
92 const QDomNode geometryChild = geometryNode.firstChild();
93 if ( geometryChild.isNull() )
97 geometryTypeElement = geometryChild.toElement();
98 geomType = geometryTypeElement.tagName();
101 if ( !( geomType == QLatin1String(
"Point" ) || geomType == QLatin1String(
"LineString" ) || geomType == QLatin1String(
"Polygon" ) ||
102 geomType == QLatin1String(
"MultiPoint" ) || geomType == QLatin1String(
"MultiLineString" ) || geomType == QLatin1String(
"MultiPolygon" ) ||
103 geomType == QLatin1String(
"Box" ) || geomType == QLatin1String(
"Envelope" ) ) )
106 if ( geomType == QLatin1String(
"Point" ) )
108 geometry = geometryFromGMLPoint( geometryTypeElement );
110 else if ( geomType == QLatin1String(
"LineString" ) )
112 geometry = geometryFromGMLLineString( geometryTypeElement );
114 else if ( geomType == QLatin1String(
"Polygon" ) )
116 geometry = geometryFromGMLPolygon( geometryTypeElement );
118 else if ( geomType == QLatin1String(
"MultiPoint" ) )
120 geometry = geometryFromGMLMultiPoint( geometryTypeElement );
122 else if ( geomType == QLatin1String(
"MultiLineString" ) )
124 geometry = geometryFromGMLMultiLineString( geometryTypeElement );
126 else if ( geomType == QLatin1String(
"MultiPolygon" ) )
128 geometry = geometryFromGMLMultiPolygon( geometryTypeElement );
130 else if ( geomType == QLatin1String(
"Box" ) )
134 else if ( geomType == QLatin1String(
"Envelope" ) )
148 if ( geometryTypeElement.hasAttribute( QStringLiteral(
"srsName" ) ) )
150 QString
srsName { geometryTypeElement.attribute( QStringLiteral(
"srsName" ) ) };
153 const bool ignoreAxisOrientation {
srsName.startsWith( QLatin1String(
"http://www.opengis.net/gml/srs/" ) ) ||
srsName.startsWith( QLatin1String(
"EPSG:" ) ) };
157 if (
srsName.startsWith( QLatin1String(
"http://www.opengis.net/gml/srs/" ) ) )
159 const auto parts {
srsName.split( QRegularExpression( QStringLiteral( R
"raw(/|#|\.)raw" ) ) ) };
160 if ( parts.length() == 10 )
162 srsName = QStringLiteral(
"http://www.opengis.net/def/crs/%1/0/%2" ).arg( parts[ 7 ].toUpper(), parts[ 9 ] );
195 const QString xml = QStringLiteral(
"<tmp xmlns=\"%1\" xmlns:gml=\"%1\">%2</tmp>" ).arg(
GML_NAMESPACE, xmlString );
197 if ( !doc.setContent( xml,
true ) )
200 return geometryFromGML( doc.documentElement().firstChildElement(), context );
204QgsGeometry QgsOgcUtils::geometryFromGMLPoint(
const QDomElement &geometryElement )
208 const QDomNodeList coordList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
209 if ( !coordList.isEmpty() )
211 const QDomElement coordElement = coordList.at( 0 ).toElement();
212 if ( readGMLCoordinates( pointCoordinate, coordElement ) != 0 )
219 const QDomNodeList posList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pos" ) );
220 if ( posList.size() < 1 )
224 const QDomElement posElement = posList.at( 0 ).toElement();
225 if ( readGMLPositions( pointCoordinate, posElement ) != 0 )
231 if ( pointCoordinate.empty() )
236 QgsPolylineXY::const_iterator point_it = pointCoordinate.constBegin();
237 char e = htonl( 1 ) != 1;
238 double x = point_it->x();
239 double y = point_it->y();
240 const int size = 1 +
sizeof( int ) + 2 *
sizeof(
double );
243 unsigned char *wkb =
new unsigned char[size];
246 memcpy( &( wkb )[wkbPosition], &e, 1 );
248 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
249 wkbPosition +=
sizeof( int );
250 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
251 wkbPosition +=
sizeof( double );
252 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
259QgsGeometry QgsOgcUtils::geometryFromGMLLineString(
const QDomElement &geometryElement )
263 const QDomNodeList coordList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
264 if ( !coordList.isEmpty() )
266 const QDomElement coordElement = coordList.at( 0 ).toElement();
267 if ( readGMLCoordinates( lineCoordinates, coordElement ) != 0 )
274 const QDomNodeList posList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
275 if ( posList.size() < 1 )
279 const QDomElement posElement = posList.at( 0 ).toElement();
280 if ( readGMLPositions( lineCoordinates, posElement ) != 0 )
286 char e = htonl( 1 ) != 1;
287 const int size = 1 + 2 *
sizeof( int ) + lineCoordinates.size() * 2 *
sizeof( double );
290 unsigned char *wkb =
new unsigned char[size];
294 int nPoints = lineCoordinates.size();
297 memcpy( &( wkb )[wkbPosition], &e, 1 );
299 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
300 wkbPosition +=
sizeof( int );
301 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
302 wkbPosition +=
sizeof( int );
304 QgsPolylineXY::const_iterator iter;
305 for ( iter = lineCoordinates.constBegin(); iter != lineCoordinates.constEnd(); ++iter )
309 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
310 wkbPosition +=
sizeof( double );
311 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
312 wkbPosition +=
sizeof( double );
320QgsGeometry QgsOgcUtils::geometryFromGMLPolygon(
const QDomElement &geometryElement )
327 const QDomNodeList outerBoundaryList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"outerBoundaryIs" ) );
328 if ( !outerBoundaryList.isEmpty() )
330 QDomElement coordinatesElement = outerBoundaryList.at( 0 ).firstChild().firstChild().toElement();
331 if ( coordinatesElement.isNull() )
335 if ( readGMLCoordinates( exteriorPointList, coordinatesElement ) != 0 )
339 ringCoordinates.push_back( exteriorPointList );
342 const QDomNodeList innerBoundaryList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"innerBoundaryIs" ) );
343 for (
int i = 0; i < innerBoundaryList.size(); ++i )
346 coordinatesElement = innerBoundaryList.at( i ).firstChild().firstChild().toElement();
347 if ( coordinatesElement.isNull() )
351 if ( readGMLCoordinates( interiorPointList, coordinatesElement ) != 0 )
355 ringCoordinates.push_back( interiorPointList );
361 const QDomNodeList exteriorList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"exterior" ) );
362 if ( exteriorList.size() < 1 )
366 const QDomElement posElement = exteriorList.at( 0 ).firstChild().firstChild().toElement();
367 if ( posElement.isNull() )
371 if ( readGMLPositions( exteriorPointList, posElement ) != 0 )
375 ringCoordinates.push_back( exteriorPointList );
378 const QDomNodeList interiorList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"interior" ) );
379 for (
int i = 0; i < interiorList.size(); ++i )
382 const QDomElement posElement = interiorList.at( i ).firstChild().firstChild().toElement();
383 if ( posElement.isNull() )
388 if ( readGMLPositions( interiorPointList, posElement ) )
392 ringCoordinates.push_back( interiorPointList );
397 int nrings = ringCoordinates.size();
402 for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
404 npoints += it->size();
406 const int size = 1 + 2 *
sizeof( int ) + nrings *
sizeof(
int ) + 2 * npoints *
sizeof( double );
409 unsigned char *wkb =
new unsigned char[size];
412 char e = htonl( 1 ) != 1;
414 int nPointsInRing = 0;
418 memcpy( &( wkb )[wkbPosition], &e, 1 );
420 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
421 wkbPosition +=
sizeof( int );
422 memcpy( &( wkb )[wkbPosition], &nrings,
sizeof(
int ) );
423 wkbPosition +=
sizeof( int );
424 for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
426 nPointsInRing = it->size();
427 memcpy( &( wkb )[wkbPosition], &nPointsInRing,
sizeof(
int ) );
428 wkbPosition +=
sizeof( int );
430 QgsPolylineXY::const_iterator iter;
431 for ( iter = it->begin(); iter != it->end(); ++iter )
436 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
437 wkbPosition +=
sizeof( double );
438 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
439 wkbPosition +=
sizeof( double );
448QgsGeometry QgsOgcUtils::geometryFromGMLMultiPoint(
const QDomElement &geometryElement )
452 const QDomNodeList pointMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pointMember" ) );
453 if ( pointMemberList.size() < 1 )
457 QDomNodeList pointNodeList;
459 QDomNodeList coordinatesList;
460 QDomNodeList posList;
461 for (
int i = 0; i < pointMemberList.size(); ++i )
464 pointNodeList = pointMemberList.at( i ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"Point" ) );
465 if ( pointNodeList.size() < 1 )
470 coordinatesList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
471 if ( !coordinatesList.isEmpty() )
473 currentPoint.clear();
474 if ( readGMLCoordinates( currentPoint, coordinatesList.at( 0 ).toElement() ) != 0 )
478 if ( currentPoint.empty() )
482 pointList.push_back( ( *currentPoint.begin() ) );
488 posList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pos" ) );
489 if ( posList.size() < 1 )
493 currentPoint.clear();
494 if ( readGMLPositions( currentPoint, posList.at( 0 ).toElement() ) != 0 )
498 if ( currentPoint.empty() )
502 pointList.push_back( ( *currentPoint.begin() ) );
506 int nPoints = pointList.size();
511 const int size = 1 + 2 *
sizeof( int ) + pointList.size() * ( 2 *
sizeof( double ) + 1 +
sizeof(
int ) );
514 unsigned char *wkb =
new unsigned char[size];
517 char e = htonl( 1 ) != 1;
520 memcpy( &( wkb )[wkbPosition], &e, 1 );
522 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
523 wkbPosition +=
sizeof( int );
524 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
525 wkbPosition +=
sizeof( int );
527 for ( QgsPolylineXY::const_iterator it = pointList.constBegin(); it != pointList.constEnd(); ++it )
529 memcpy( &( wkb )[wkbPosition], &e, 1 );
531 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
532 wkbPosition +=
sizeof( int );
534 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
535 wkbPosition +=
sizeof( double );
537 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
538 wkbPosition +=
sizeof( double );
546QgsGeometry QgsOgcUtils::geometryFromGMLMultiLineString(
const QDomElement &geometryElement )
557 QList< QgsPolylineXY > lineCoordinates;
558 QDomElement currentLineStringElement;
559 QDomNodeList currentCoordList;
560 QDomNodeList currentPosList;
562 const QDomNodeList lineStringMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"lineStringMember" ) );
563 if ( !lineStringMemberList.isEmpty() )
565 for (
int i = 0; i < lineStringMemberList.size(); ++i )
567 const QDomNodeList lineStringNodeList = lineStringMemberList.at( i ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LineString" ) );
568 if ( lineStringNodeList.size() < 1 )
572 currentLineStringElement = lineStringNodeList.at( 0 ).toElement();
573 currentCoordList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
574 if ( !currentCoordList.isEmpty() )
577 if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
581 lineCoordinates.push_back( currentPointList );
585 currentPosList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
586 if ( currentPosList.size() < 1 )
591 if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
595 lineCoordinates.push_back( currentPointList );
601 const QDomNodeList lineStringList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LineString" ) );
602 if ( !lineStringList.isEmpty() )
604 for (
int i = 0; i < lineStringList.size(); ++i )
606 currentLineStringElement = lineStringList.at( i ).toElement();
607 currentCoordList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
608 if ( !currentCoordList.isEmpty() )
611 if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
615 lineCoordinates.push_back( currentPointList );
620 currentPosList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
621 if ( currentPosList.size() < 1 )
626 if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
630 lineCoordinates.push_back( currentPointList );
640 int nLines = lineCoordinates.size();
645 int size = ( lineCoordinates.size() + 1 ) * ( 1 + 2 *
sizeof(
int ) );
646 for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
648 size += it->size() * 2 *
sizeof( double );
652 unsigned char *wkb =
new unsigned char[size];
655 char e = htonl( 1 ) != 1;
659 memcpy( &( wkb )[wkbPosition], &e, 1 );
661 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
662 wkbPosition +=
sizeof( int );
663 memcpy( &( wkb )[wkbPosition], &nLines,
sizeof(
int ) );
664 wkbPosition +=
sizeof( int );
666 for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
668 memcpy( &( wkb )[wkbPosition], &e, 1 );
670 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
671 wkbPosition +=
sizeof( int );
672 nPoints = it->size();
673 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
674 wkbPosition +=
sizeof( int );
675 for ( QgsPolylineXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
680 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
681 wkbPosition +=
sizeof( double );
682 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
683 wkbPosition +=
sizeof( double );
692QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon(
const QDomElement &geometryElement )
696 QDomElement currentPolygonMemberElement;
697 QDomNodeList polygonList;
698 QDomElement currentPolygonElement;
700 QDomNodeList outerBoundaryList;
701 QDomElement currentOuterBoundaryElement;
702 const QDomNodeList innerBoundaryList;
703 QDomElement currentInnerBoundaryElement;
705 QDomNodeList exteriorList;
706 QDomElement currentExteriorElement;
707 QDomElement currentInteriorElement;
708 const QDomNodeList interiorList;
710 QDomNodeList linearRingNodeList;
711 QDomElement currentLinearRingElement;
713 QDomNodeList currentCoordinateList;
714 QDomNodeList currentPosList;
716 const QDomNodeList polygonMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"polygonMember" ) );
718 for (
int i = 0; i < polygonMemberList.size(); ++i )
720 currentPolygonList.resize( 0 );
721 currentPolygonMemberElement = polygonMemberList.at( i ).toElement();
722 polygonList = currentPolygonMemberElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"Polygon" ) );
723 if ( polygonList.size() < 1 )
727 currentPolygonElement = polygonList.at( 0 ).toElement();
730 outerBoundaryList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"outerBoundaryIs" ) );
731 if ( !outerBoundaryList.isEmpty() )
733 currentOuterBoundaryElement = outerBoundaryList.at( 0 ).toElement();
736 linearRingNodeList = currentOuterBoundaryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
737 if ( linearRingNodeList.size() < 1 )
741 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
742 currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
743 if ( currentCoordinateList.size() < 1 )
747 if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
751 currentPolygonList.push_back( ringCoordinates );
754 const QDomNodeList innerBoundaryList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"innerBoundaryIs" ) );
755 for (
int j = 0; j < innerBoundaryList.size(); ++j )
758 currentInnerBoundaryElement = innerBoundaryList.at( j ).toElement();
759 linearRingNodeList = currentInnerBoundaryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
760 if ( linearRingNodeList.size() < 1 )
764 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
765 currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
766 if ( currentCoordinateList.size() < 1 )
770 if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
774 currentPolygonList.push_back( ringCoordinates );
780 exteriorList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"exterior" ) );
781 if ( exteriorList.size() < 1 )
786 currentExteriorElement = exteriorList.at( 0 ).toElement();
789 linearRingNodeList = currentExteriorElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
790 if ( linearRingNodeList.size() < 1 )
794 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
795 currentPosList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
796 if ( currentPosList.size() < 1 )
800 if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
804 currentPolygonList.push_back( ringPositions );
807 const QDomNodeList interiorList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"interior" ) );
808 for (
int j = 0; j < interiorList.size(); ++j )
811 currentInteriorElement = interiorList.at( j ).toElement();
812 linearRingNodeList = currentInteriorElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
813 if ( linearRingNodeList.size() < 1 )
817 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
818 currentPosList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
819 if ( currentPosList.size() < 1 )
823 if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
827 currentPolygonList.push_back( ringPositions );
830 multiPolygonPoints.push_back( currentPolygonList );
833 int nPolygons = multiPolygonPoints.size();
837 int size = 1 + 2 *
sizeof( int );
839 for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
841 size += 1 + 2 *
sizeof( int );
842 for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
844 size +=
sizeof( int ) + 2 * iter->size() *
sizeof( double );
849 unsigned char *wkb =
new unsigned char[size];
851 char e = htonl( 1 ) != 1;
858 memcpy( &( wkb )[wkbPosition], &e, 1 );
860 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
861 wkbPosition +=
sizeof( int );
862 memcpy( &( wkb )[wkbPosition], &nPolygons,
sizeof(
int ) );
863 wkbPosition +=
sizeof( int );
867 for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
869 memcpy( &( wkb )[wkbPosition], &e, 1 );
871 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
872 wkbPosition +=
sizeof( int );
874 memcpy( &( wkb )[wkbPosition], &nRings,
sizeof(
int ) );
875 wkbPosition +=
sizeof( int );
876 for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
878 nPointsInRing = iter->size();
879 memcpy( &( wkb )[wkbPosition], &nPointsInRing,
sizeof(
int ) );
880 wkbPosition +=
sizeof( int );
881 for ( QgsPolylineXY::const_iterator iterator = iter->begin(); iterator != iter->end(); ++iterator )
885 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
886 wkbPosition +=
sizeof( double );
887 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
888 wkbPosition +=
sizeof( double );
898QDomElement QgsOgcUtils::filterElement( QDomDocument &doc, GMLVersion gmlVersion, FilterVersion filterVersion,
bool GMLUsed )
900 QDomElement filterElem =
902 doc.createElementNS(
FES_NAMESPACE, QStringLiteral(
"fes:Filter" ) ) :
903 doc.createElementNS(
OGC_NAMESPACE, QStringLiteral(
"ogc:Filter" ) );
907 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:gml" ) );
912 filterElem.setAttributeNode( attr );
918bool QgsOgcUtils::readGMLCoordinates(
QgsPolylineXY &coords,
const QDomElement &elem )
920 QString coordSeparator = QStringLiteral(
"," );
921 QString tupelSeparator = QStringLiteral(
" " );
926 if ( elem.hasAttribute( QStringLiteral(
"cs" ) ) )
928 coordSeparator = elem.attribute( QStringLiteral(
"cs" ) );
930 if ( elem.hasAttribute( QStringLiteral(
"ts" ) ) )
932 tupelSeparator = elem.attribute( QStringLiteral(
"ts" ) );
935#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
936 QStringList tupels = elem.text().split( tupelSeparator, QString::SkipEmptyParts );
938 const QStringList tupels = elem.text().split( tupelSeparator, Qt::SkipEmptyParts );
940 QStringList tuple_coords;
942 bool conversionSuccess;
944 QStringList::const_iterator it;
945 for ( it = tupels.constBegin(); it != tupels.constEnd(); ++it )
947#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
948 tuple_coords = ( *it ).split( coordSeparator, QString::SkipEmptyParts );
950 tuple_coords = ( *it ).split( coordSeparator, Qt::SkipEmptyParts );
952 if ( tuple_coords.size() < 2 )
956 x = tuple_coords.at( 0 ).toDouble( &conversionSuccess );
957 if ( !conversionSuccess )
961 y = tuple_coords.at( 1 ).toDouble( &conversionSuccess );
962 if ( !conversionSuccess )
975 const QDomElement boxElem = boxNode.toElement();
976 if ( boxElem.tagName() != QLatin1String(
"Box" ) )
979 const QDomElement bElem = boxElem.firstChild().toElement();
980 QString coordSeparator = QStringLiteral(
"," );
981 QString tupelSeparator = QStringLiteral(
" " );
982 if ( bElem.hasAttribute( QStringLiteral(
"cs" ) ) )
984 coordSeparator = bElem.attribute( QStringLiteral(
"cs" ) );
986 if ( bElem.hasAttribute( QStringLiteral(
"ts" ) ) )
988 tupelSeparator = bElem.attribute( QStringLiteral(
"ts" ) );
991 const QString bString = bElem.text();
992 bool ok1, ok2, ok3, ok4;
993 const double xmin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 0, 0 ).toDouble( &ok1 );
994 const double ymin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 1, 1 ).toDouble( &ok2 );
995 const double xmax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 0, 0 ).toDouble( &ok3 );
996 const double ymax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 1, 1 ).toDouble( &ok4 );
998 if ( ok1 && ok2 && ok3 && ok4 )
1007bool QgsOgcUtils::readGMLPositions(
QgsPolylineXY &coords,
const QDomElement &elem )
1011#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1012 QStringList pos = elem.text().split(
' ', QString::SkipEmptyParts );
1014 const QStringList pos = elem.text().split(
' ', Qt::SkipEmptyParts );
1017 bool conversionSuccess;
1018 const int posSize = pos.size();
1020 int srsDimension = 2;
1021 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
1023 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
1024 if ( !conversionSuccess )
1029 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1031 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1032 if ( !conversionSuccess )
1038 for (
int i = 0; i < posSize / srsDimension; i++ )
1040 x = pos.at( i * srsDimension ).toDouble( &conversionSuccess );
1041 if ( !conversionSuccess )
1045 y = pos.at( i * srsDimension + 1 ).toDouble( &conversionSuccess );
1046 if ( !conversionSuccess )
1060 const QDomElement envelopeElem = envelopeNode.toElement();
1061 if ( envelopeElem.tagName() != QLatin1String(
"Envelope" ) )
1064 const QDomNodeList lowerCornerList = envelopeElem.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"lowerCorner" ) );
1065 if ( lowerCornerList.size() < 1 )
1068 const QDomNodeList upperCornerList = envelopeElem.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"upperCorner" ) );
1069 if ( upperCornerList.size() < 1 )
1072 bool conversionSuccess;
1073 int srsDimension = 2;
1075 QDomElement elem = lowerCornerList.at( 0 ).toElement();
1076 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
1078 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
1079 if ( !conversionSuccess )
1084 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1086 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1087 if ( !conversionSuccess )
1092 QString bString = elem.text();
1094 const double xmin = bString.section(
' ', 0, 0 ).toDouble( &conversionSuccess );
1095 if ( !conversionSuccess )
1097 const double ymin = bString.section(
' ', 1, 1 ).toDouble( &conversionSuccess );
1098 if ( !conversionSuccess )
1101 elem = upperCornerList.at( 0 ).toElement();
1102 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
1104 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
1105 if ( !conversionSuccess )
1110 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1112 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1113 if ( !conversionSuccess )
1119 Q_UNUSED( srsDimension )
1121 bString = elem.text();
1122 const double xmax = bString.section(
' ', 0, 0 ).toDouble( &conversionSuccess );
1123 if ( !conversionSuccess )
1125 const double ymax = bString.section(
' ', 1, 1 ).toDouble( &conversionSuccess );
1126 if ( !conversionSuccess )
1142 bool invertAxisOrientation,
1147 return QDomElement();
1150 QDomElement boxElem = doc.createElement( QStringLiteral(
"gml:Box" ) );
1153 boxElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1155 QDomElement coordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1156 coordElem.setAttribute( QStringLiteral(
"cs" ), QStringLiteral(
"," ) );
1157 coordElem.setAttribute( QStringLiteral(
"ts" ), QStringLiteral(
" " ) );
1159 QString coordString;
1168 const QDomText coordText = doc.createTextNode( coordString );
1169 coordElem.appendChild( coordText );
1170 boxElem.appendChild( coordElem );
1182 bool invertAxisOrientation,
1187 return QDomElement();
1190 QDomElement envElem = doc.createElement( QStringLiteral(
"gml:Envelope" ) );
1193 envElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1197 QDomElement lowerCornerElem = doc.createElement( QStringLiteral(
"gml:lowerCorner" ) );
1201 const QDomText lowerCornerText = doc.createTextNode( posList );
1202 lowerCornerElem.appendChild( lowerCornerText );
1203 envElem.appendChild( lowerCornerElem );
1205 QDomElement upperCornerElem = doc.createElement( QStringLiteral(
"gml:upperCorner" ) );
1209 const QDomText upperCornerText = doc.createTextNode( posList );
1210 upperCornerElem.appendChild( upperCornerText );
1211 envElem.appendChild( upperCornerElem );
1225 bool invertAxisOrientation,
1226 const QString &gmlIdBase,
1230 return QDomElement();
1233 QString cs = QStringLiteral(
"," );
1235 const QString ts = QStringLiteral(
" " );
1237 QDomElement baseCoordElem;
1239 bool hasZValue =
false;
1241 const QByteArray wkb( geometry.
asWkb() );
1251 return QDomElement();
1262 baseCoordElem = doc.createElement( QStringLiteral(
"gml:pos" ) );
1265 baseCoordElem = doc.createElement( QStringLiteral(
"gml:posList" ) );
1268 baseCoordElem.setAttribute( QStringLiteral(
"srsDimension" ), QStringLiteral(
"2" ) );
1273 baseCoordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1274 baseCoordElem.setAttribute( QStringLiteral(
"cs" ), cs );
1275 baseCoordElem.setAttribute( QStringLiteral(
"ts" ), ts );
1285 QDomElement pointElem = doc.createElement( QStringLiteral(
"gml:Point" ) );
1286 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1287 pointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1289 pointElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1290 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1294 if ( invertAxisOrientation )
1300 coordElem.appendChild( coordText );
1301 pointElem.appendChild( coordElem );
1310 QDomElement multiPointElem = doc.createElement( QStringLiteral(
"gml:MultiPoint" ) );
1311 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1312 multiPointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1314 multiPointElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1319 for (
int idx = 0; idx < nPoints; ++idx )
1321 QDomElement pointMemberElem = doc.createElement( QStringLiteral(
"gml:pointMember" ) );
1322 QDomElement pointElem = doc.createElement( QStringLiteral(
"gml:Point" ) );
1323 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1324 pointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( idx + 1 ) );
1325 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1331 if ( invertAxisOrientation )
1337 coordElem.appendChild( coordText );
1338 pointElem.appendChild( coordElem );
1342 wkbPtr +=
sizeof( double );
1344 pointMemberElem.appendChild( pointElem );
1345 multiPointElem.appendChild( pointMemberElem );
1347 return multiPointElem;
1355 QDomElement lineStringElem = doc.createElement( QStringLiteral(
"gml:LineString" ) );
1356 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1357 lineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1359 lineStringElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1365 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1366 QString coordString;
1367 for (
int idx = 0; idx < nPoints; ++idx )
1376 if ( invertAxisOrientation )
1384 wkbPtr +=
sizeof( double );
1387 const QDomText coordText = doc.createTextNode( coordString );
1388 coordElem.appendChild( coordText );
1389 lineStringElem.appendChild( coordElem );
1390 return lineStringElem;
1398 QDomElement multiLineStringElem = doc.createElement( QStringLiteral(
"gml:MultiLineString" ) );
1399 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1400 multiLineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1402 multiLineStringElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1407 for (
int jdx = 0; jdx < nLines; jdx++ )
1409 QDomElement lineStringMemberElem = doc.createElement( QStringLiteral(
"gml:lineStringMember" ) );
1410 QDomElement lineStringElem = doc.createElement( QStringLiteral(
"gml:LineString" ) );
1411 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1412 lineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( jdx + 1 ) );
1419 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1420 QString coordString;
1421 for (
int idx = 0; idx < nPoints; idx++ )
1430 if ( invertAxisOrientation )
1439 wkbPtr +=
sizeof( double );
1442 const QDomText coordText = doc.createTextNode( coordString );
1443 coordElem.appendChild( coordText );
1444 lineStringElem.appendChild( coordElem );
1445 lineStringMemberElem.appendChild( lineStringElem );
1446 multiLineStringElem.appendChild( lineStringMemberElem );
1448 return multiLineStringElem;
1456 QDomElement polygonElem = doc.createElement( QStringLiteral(
"gml:Polygon" ) );
1457 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1458 polygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1460 polygonElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1466 if ( numRings == 0 )
1467 return QDomElement();
1469 for (
int idx = 0; idx < numRings; idx++ )
1471 QString boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:outerBoundaryIs" :
"gml:exterior";
1474 boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:innerBoundaryIs" :
"gml:interior";
1476 QDomElement boundaryElem = doc.createElement( boundaryName );
1477 QDomElement ringElem = doc.createElement( QStringLiteral(
"gml:LinearRing" ) );
1482 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1483 QString coordString;
1484 for (
int jdx = 0; jdx < nPoints; jdx++ )
1493 if ( invertAxisOrientation )
1501 wkbPtr +=
sizeof( double );
1504 const QDomText coordText = doc.createTextNode( coordString );
1505 coordElem.appendChild( coordText );
1506 ringElem.appendChild( coordElem );
1507 boundaryElem.appendChild( ringElem );
1508 polygonElem.appendChild( boundaryElem );
1518 QDomElement multiPolygonElem = doc.createElement( QStringLiteral(
"gml:MultiPolygon" ) );
1519 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1520 multiPolygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1522 multiPolygonElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1525 wkbPtr >> numPolygons;
1527 for (
int kdx = 0; kdx < numPolygons; kdx++ )
1529 QDomElement polygonMemberElem = doc.createElement( QStringLiteral(
"gml:polygonMember" ) );
1530 QDomElement polygonElem = doc.createElement( QStringLiteral(
"gml:Polygon" ) );
1531 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1532 polygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( kdx + 1 ) );
1539 for (
int idx = 0; idx < numRings; idx++ )
1541 QString boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:outerBoundaryIs" :
"gml:exterior";
1544 boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:innerBoundaryIs" :
"gml:interior";
1546 QDomElement boundaryElem = doc.createElement( boundaryName );
1547 QDomElement ringElem = doc.createElement( QStringLiteral(
"gml:LinearRing" ) );
1552 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1553 QString coordString;
1554 for (
int jdx = 0; jdx < nPoints; jdx++ )
1563 if ( invertAxisOrientation )
1572 wkbPtr +=
sizeof( double );
1575 const QDomText coordText = doc.createTextNode( coordString );
1576 coordElem.appendChild( coordText );
1577 ringElem.appendChild( coordElem );
1578 boundaryElem.appendChild( ringElem );
1579 polygonElem.appendChild( boundaryElem );
1580 polygonMemberElem.appendChild( polygonElem );
1581 multiPolygonElem.appendChild( polygonMemberElem );
1584 return multiPolygonElem;
1587 return QDomElement();
1593 return QDomElement();
1602QDomElement QgsOgcUtils::createGMLCoordinates(
const QgsPolylineXY &points, QDomDocument &doc )
1604 QDomElement coordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1605 coordElem.setAttribute( QStringLiteral(
"cs" ), QStringLiteral(
"," ) );
1606 coordElem.setAttribute( QStringLiteral(
"ts" ), QStringLiteral(
" " ) );
1608 QString coordString;
1609 QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
1610 for ( ; pointIt != points.constEnd(); ++pointIt )
1612 if ( pointIt != points.constBegin() )
1621 const QDomText coordText = doc.createTextNode( coordString );
1622 coordElem.appendChild( coordText );
1626QDomElement QgsOgcUtils::createGMLPositions(
const QgsPolylineXY &points, QDomDocument &doc )
1628 QDomElement posElem = doc.createElement( QStringLiteral(
"gml:pos" ) );
1629 if ( points.size() > 1 )
1630 posElem = doc.createElement( QStringLiteral(
"gml:posList" ) );
1631 posElem.setAttribute( QStringLiteral(
"srsDimension" ), QStringLiteral(
"2" ) );
1633 QString coordString;
1634 QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
1635 for ( ; pointIt != points.constEnd(); ++pointIt )
1637 if ( pointIt != points.constBegin() )
1646 const QDomText coordText = doc.createTextNode( coordString );
1647 posElem.appendChild( coordText );
1657 if ( fillElement.isNull() || !fillElement.hasChildNodes() )
1665 QDomElement cssElem = fillElement.firstChildElement( QStringLiteral(
"CssParameter" ) );
1666 while ( !cssElem.isNull() )
1668 cssName = cssElem.attribute( QStringLiteral(
"name" ), QStringLiteral(
"not_found" ) );
1669 if ( cssName != QLatin1String(
"not_found" ) )
1671 elemText = cssElem.text();
1672 if ( cssName == QLatin1String(
"fill" ) )
1674 color.setNamedColor( elemText );
1676 else if ( cssName == QLatin1String(
"fill-opacity" ) )
1679 const double opacity = elemText.toDouble( &ok );
1682 color.setAlphaF( opacity );
1687 cssElem = cssElem.nextSiblingElement( QStringLiteral(
"CssParameter" ) );
1701 if ( element.isNull() || !element.hasChildNodes() )
1708 if ( element.firstChild().nodeType() == QDomNode::TextNode )
1718 QDomElement childElem = element.firstChildElement();
1719 while ( !childElem.isNull() )
1731 if ( !expr->d->mRootNode )
1733 expr->d->mRootNode = node;
1740 childElem = childElem.nextSiblingElement();
1744 expr->d->mExp = expr->
dump();
1770static
int binaryOperatorFromTagName( const QString &tagName )
1773 return BINARY_OPERATORS_TAG_NAMES_MAP()->value( tagName, -1 );
1780 return QStringLiteral(
"PropertyIsLike" );
1782 return BINARY_OPERATORS_TAG_NAMES_MAP()->key( op, QString() );
1785static bool isBinaryOperator(
const QString &tagName )
1787 return binaryOperatorFromTagName( tagName ) >= 0;
1791static bool isSpatialOperator(
const QString &tagName )
1793 static QStringList spatialOps;
1794 if ( spatialOps.isEmpty() )
1796 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
1797 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
1800 return spatialOps.contains( tagName );
1807 errorMessage = utils.errorMessage();
1815 errorMessage = utils.errorMessage();
1823 errorMessage = utils.errorMessage();
1831 errorMessage = utils.errorMessage();
1839 errorMessage = utils.errorMessage();
1847 errorMessage = utils.errorMessage();
1855 errorMessage = utils.errorMessage();
1859QgsExpressionNode *QgsOgcUtils::nodeIsBetweenFromOgcFilter( QDomElement &element, QString &errorMessage )
1863 errorMessage = utils.errorMessage();
1871 errorMessage = utils.errorMessage();
1882 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage );
1888 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage, requiresFilterElement );
1896 const QString &namespacePrefix,
1897 const QString &namespaceURI,
1900 bool honourAxisOrientation,
1901 bool invertAxisOrientation,
1902 QString *errorMessage )
1905 return QDomElement();
1915 if ( exprRootElem.isNull() )
1916 return QDomElement();
1918 QDomElement filterElem = filterElement( doc, gmlVersion, filterVersion, utils.
GMLNamespaceUsed() );
1920 if ( !namespacePrefix.isEmpty() && !namespaceURI.isEmpty() )
1922 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:" ) + namespacePrefix );
1923 attr.setValue( namespaceURI );
1924 filterElem.setAttributeNode( attr );
1927 filterElem.appendChild( exprRootElem );
1937 bool honourAxisOrientation,
1938 bool invertAxisOrientation,
1939 QString *errorMessage,
1940 bool requiresFilterElement )
1949 return QDomElement();
1963 if ( !exprRootElem.isNull() )
1965 if ( requiresFilterElement )
1967 QDomElement filterElem = filterElement( doc, gmlVersion, filterVersion, utils.
GMLNamespaceUsed() );
1969 filterElem.appendChild( exprRootElem );
1972 return exprRootElem;
1979 *errorMessage = QObject::tr(
"Node type not supported in expression translation: %1" ).arg( node->
nodeType() );
1983 return QDomElement();
1990 const QList<LayerProperties> &layerProperties,
1991 bool honourAxisOrientation,
1992 bool invertAxisOrientation,
1993 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename,
1994 QString *errorMessage )
1997 return QDomElement();
2000 layerProperties, honourAxisOrientation, invertAxisOrientation,
2001 mapUnprefixedTypenameToPrefixedTypename );
2005 if ( exprRootElem.isNull() )
2006 return QDomElement();
2008 QDomElement filterElem = filterElement( doc, gmlVersion, filterVersion, utils.
GMLNamespaceUsed() );
2010 QSet<QString> setNamespaceURI;
2013 if ( !props.mNamespacePrefix.isEmpty() && !props.mNamespaceURI.isEmpty() &&
2014 !setNamespaceURI.contains( props.mNamespaceURI ) )
2016 setNamespaceURI.insert( props.mNamespaceURI );
2017 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:" ) + props.mNamespacePrefix );
2018 attr.setValue( props.mNamespaceURI );
2019 filterElem.setAttributeNode( attr );
2022 filterElem.appendChild( exprRootElem );
2047 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
2048 return QDomElement();
2055 if ( !mErrorMessage.isEmpty() )
2056 return QDomElement();
2059 switch ( node->
op() )
2062 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2067 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
2068 mDoc.removeChild( operandElem );
2072 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
2073 return QDomElement();
2077 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
2078 uoElem.appendChild( operandElem );
2082 mErrorMessage = QObject::tr(
"Unary operator '%1' not implemented yet" ).arg( node->
text() );
2083 return QDomElement();
2093 if ( !mErrorMessage.isEmpty() )
2094 return QDomElement();
2107 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2108 elem.appendChild( leftElem );
2112 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2113 notElem.appendChild( elem );
2127 if ( !mErrorMessage.isEmpty() )
2128 return QDomElement();
2131 const QString opText = binaryOperatorToTagName( op );
2132 if ( opText.isEmpty() )
2136 mErrorMessage = QObject::tr(
"Binary operator %1 not implemented yet" ).arg( node->
text() );
2137 return QDomElement();
2140 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2145 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2148 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2149 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2151 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2153 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2156 boElem.appendChild( leftElem );
2157 boElem.appendChild( rightElem );
2164 Q_UNUSED( expression )
2167 switch ( node->
value().type() )
2170 value = QString::number( node->
value().toInt() );
2172 case QVariant::Double:
2175 case QVariant::String:
2176 value = node->
value().toString();
2178 case QVariant::Date:
2179 value = node->
value().toDate().toString( Qt::ISODate );
2181 case QVariant::DateTime:
2182 value = node->
value().toDateTime().toString( Qt::ISODate );
2186 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2187 return QDomElement();
2190 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2191 litElem.appendChild( mDoc.createTextNode( value ) );
2198 Q_UNUSED( expression )
2200 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2201 QString columnRef( node->
name() );
2202 if ( !mNamespacePrefix.isEmpty() && !mNamespaceURI.isEmpty() )
2203 columnRef = mNamespacePrefix + QStringLiteral(
":" ) + columnRef;
2204 propElem.appendChild( mDoc.createTextNode( columnRef ) );
2212 if ( node->
list()->
list().size() == 1 )
2215 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2218 const auto constList = node->
list()->
list();
2222 if ( !mErrorMessage.isEmpty() )
2223 return QDomElement();
2225 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2226 eqElem.appendChild( leftNode.cloneNode() );
2227 eqElem.appendChild( listNode );
2229 orElem.appendChild( eqElem );
2234 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2235 notElem.appendChild( orElem );
2244 { QLatin1String(
"disjoint" ), QLatin1String(
"Disjoint" ) },
2245 { QLatin1String(
"intersects" ), QLatin1String(
"Intersects" )},
2246 { QLatin1String(
"touches" ), QLatin1String(
"Touches" ) },
2247 { QLatin1String(
"crosses" ), QLatin1String(
"Crosses" ) },
2248 { QLatin1String(
"contains" ), QLatin1String(
"Contains" ) },
2249 { QLatin1String(
"overlaps" ), QLatin1String(
"Overlaps" ) },
2250 { QLatin1String(
"within" ), QLatin1String(
"Within" ) }
2253static
bool isBinarySpatialOperator( const QString &fnName )
2255 return BINARY_SPATIAL_OPS_MAP()->contains( fnName );
2258static QString tagNameForSpatialOperator(
const QString &fnName )
2260 return BINARY_SPATIAL_OPS_MAP()->value( fnName );
2270 return fd->
name() == QLatin1String(
"$geometry" );
2282 if ( fnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2284 const QList<QgsExpressionNode *> &args = fnNode->
args()->
list();
2300 if ( fd->
name() == QLatin1String(
"intersects_bbox" ) )
2302 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2303 Q_ASSERT( argNodes.count() == 2 );
2305 const QgsGeometry geom = geometryFromConstExpr( argNodes[1] );
2306 if ( !geom.
isNull() && isGeometryColumn( argNodes[0] ) )
2316 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":BBOX" );
2318 if ( !mGeometryName.isEmpty() )
2321 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2322 QString columnRef( mGeometryName );
2323 if ( !mNamespacePrefix.isEmpty() && !mNamespaceURI.isEmpty() )
2324 columnRef = mNamespacePrefix + QStringLiteral(
":" ) + columnRef;
2325 geomProperty.appendChild( mDoc.createTextNode( columnRef ) );
2327 funcElem.appendChild( geomProperty );
2329 funcElem.appendChild( elemBox );
2334 mErrorMessage = QObject::tr(
"<BBOX> is currently supported only in form: bbox($geometry, geomFromWKT('…'))" );
2335 return QDomElement();
2339 if ( isBinarySpatialOperator( fd->
name() ) )
2341 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2342 Q_ASSERT( argNodes.count() == 2 );
2345 if ( isGeometryColumn( argNodes[0] ) )
2346 otherNode = argNodes[1];
2347 else if ( isGeometryColumn( argNodes[1] ) )
2348 otherNode = argNodes[0];
2351 mErrorMessage = QObject::tr(
"Unable to translate spatial operator: at least one must refer to geometry." );
2352 return QDomElement();
2355 QDomElement otherGeomElem;
2360 mErrorMessage = QObject::tr(
"spatial operator: the other operator must be a geometry constructor function" );
2361 return QDomElement();
2366 if ( otherFnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2371 mErrorMessage = QObject::tr(
"geom_from_wkt: argument must be string literal" );
2372 return QDomElement();
2377 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2378 if ( otherGeomElem.isNull() )
2380 mErrorMessage = QObject::tr(
"geom_from_wkt: unable to generate GML from wkt geometry" );
2381 return QDomElement();
2385 else if ( otherFnDef->
name() == QLatin1String(
"geom_from_gml" ) )
2390 mErrorMessage = QObject::tr(
"geom_from_gml: argument must be string literal" );
2391 return QDomElement();
2394 QDomDocument geomDoc;
2396 if ( !geomDoc.setContent( gml,
true ) )
2398 mErrorMessage = QObject::tr(
"geom_from_gml: unable to parse XML" );
2399 return QDomElement();
2402 const QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(),
true );
2403 otherGeomElem = geomNode.toElement();
2409 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2410 if ( otherGeomElem.
isNull() )
2412 mErrorMessage = QObject::tr(
"geom from static value: unable to generate GML from static variable" );
2413 return QDomElement();
2419 mErrorMessage = QObject::tr(
"spatial operator: unknown geometry constructor function" );
2420 return QDomElement();
2425 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + tagNameForSpatialOperator( fd->
name() ) );
2426 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2427 QString columnRef( mGeometryName );
2428 if ( !mNamespacePrefix.isEmpty() && !mNamespaceURI.isEmpty() )
2429 columnRef = mNamespacePrefix + QStringLiteral(
":" ) + columnRef;
2430 geomProperty.appendChild( mDoc.createTextNode( columnRef ) );
2431 funcElem.appendChild( geomProperty );
2432 funcElem.appendChild( otherGeomElem );
2436 if ( fd->
isStatic( node, expression, context ) )
2438 const QVariant result = fd->
run( node->
args(), context, expression, node );
2440 return expressionLiteralToOgcFilter( &literal, expression, context );
2445 mErrorMessage = QObject::tr(
"Special columns/constants are not supported." );
2446 return QDomElement();
2450 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
2451 funcElem.setAttribute( QStringLiteral(
"name" ), fd->
name() );
2452 const auto constList = node->
args()->
list();
2456 if ( !mErrorMessage.isEmpty() )
2457 return QDomElement();
2459 funcElem.appendChild( childElem );
2470 const QList<QgsOgcUtils::LayerProperties> &layerProperties,
2471 bool honourAxisOrientation,
2472 bool invertAxisOrientation,
2473 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename )
2476 , mGMLVersion( gmlVersion )
2477 , mFilterVersion( filterVersion )
2478 , mLayerProperties( layerProperties )
2479 , mHonourAxisOrientation( honourAxisOrientation )
2480 , mInvertAxisOrientation( invertAxisOrientation )
2481 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
2482 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
2484 , mMapUnprefixedTypenameToPrefixedTypename( mapUnprefixedTypenameToPrefixedTypename )
2510 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
2511 return QDomElement();
2520 if ( !mErrorMessage.isEmpty() )
2521 return QDomElement();
2524 switch ( node->
op() )
2527 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2532 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
2533 mDoc.removeChild( operandElem );
2537 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
2538 return QDomElement();
2542 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
2543 uoElem.appendChild( operandElem );
2548 return QDomElement();
2558 if ( !mErrorMessage.isEmpty() )
2559 return QDomElement();
2572 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2573 elem.appendChild( leftElem );
2577 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2578 notElem.appendChild( elem );
2592 if ( !mErrorMessage.isEmpty() )
2593 return QDomElement();
2598 opText = QStringLiteral(
"Or" );
2600 opText = QStringLiteral(
"And" );
2602 opText = QStringLiteral(
"PropertyIsEqualTo" );
2604 opText = QStringLiteral(
"PropertyIsNotEqualTo" );
2606 opText = QStringLiteral(
"PropertyIsLessThanOrEqualTo" );
2608 opText = QStringLiteral(
"PropertyIsGreaterThanOrEqualTo" );
2610 opText = QStringLiteral(
"PropertyIsLessThan" );
2612 opText = QStringLiteral(
"PropertyIsGreaterThan" );
2614 opText = QStringLiteral(
"PropertyIsLike" );
2616 opText = QStringLiteral(
"PropertyIsLike" );
2618 if ( opText.isEmpty() )
2622 return QDomElement();
2625 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2630 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2633 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2634 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2636 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2638 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2641 boElem.appendChild( leftElem );
2642 boElem.appendChild( rightElem );
2650 switch ( node->
value().type() )
2653 value = QString::number( node->
value().toInt() );
2655 case QVariant::LongLong:
2656 value = QString::number( node->
value().toLongLong() );
2658 case QVariant::Double:
2661 case QVariant::String:
2662 value = node->
value().toString();
2666 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2667 return QDomElement();
2670 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2671 litElem.appendChild( mDoc.createTextNode( value ) );
2678 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2679 if ( node->
tableName().isEmpty() || mLayerProperties.size() == 1 )
2681 if ( mLayerProperties.size() == 1 && !mLayerProperties[0].mNamespacePrefix.isEmpty() && !mLayerProperties[0].mNamespaceURI.isEmpty() )
2682 propElem.appendChild( mDoc.createTextNode(
2683 mLayerProperties[0].mNamespacePrefix + QStringLiteral(
":" ) + node->
name() ) );
2685 propElem.appendChild( mDoc.createTextNode( node->
name() ) );
2689 QString tableName( mMapTableAliasToNames[node->
tableName()] );
2690 if ( mMapUnprefixedTypenameToPrefixedTypename.contains( tableName ) )
2691 tableName = mMapUnprefixedTypenameToPrefixedTypename[tableName];
2692 propElem.appendChild( mDoc.createTextNode( tableName +
"/" + node->
name() ) );
2699 if ( node->
list()->
list().size() == 1 )
2702 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2705 const auto constList = node->
list()->
list();
2709 if ( !mErrorMessage.isEmpty() )
2710 return QDomElement();
2712 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2713 eqElem.appendChild( leftNode.cloneNode() );
2714 eqElem.appendChild( listNode );
2716 orElem.appendChild( eqElem );
2721 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2722 notElem.appendChild( orElem );
2731 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsBetween" );
2733 QDomElement lowerBoundary = mDoc.createElement( mFilterPrefix +
":LowerBoundary" );
2735 elem.appendChild( lowerBoundary );
2736 QDomElement upperBoundary = mDoc.createElement( mFilterPrefix +
":UpperBoundary" );
2738 elem.appendChild( upperBoundary );
2742 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2743 notElem.appendChild( elem );
2750static QString mapBinarySpatialToOgc(
const QString &name )
2752 QString nameCompare( name );
2753#if QT_VERSION < QT_VERSION_CHECK(5, 15, 2)
2754 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2755 nameCompare = name.mid( 3 );
2757 if ( name.size() > 3 && QStringView {name}.mid( 0, 3 ).toString().compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2758 nameCompare = name.mid( 3 );
2760 QStringList spatialOps;
2761 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
2762 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
2763 const auto constSpatialOps = spatialOps;
2764 for ( QString op : constSpatialOps )
2766 if ( nameCompare.compare( op, Qt::CaseInsensitive ) == 0 )
2772static QString mapTernarySpatialToOgc(
const QString &name )
2774 QString nameCompare( name );
2775#if QT_VERSION < QT_VERSION_CHECK(5, 15, 2)
2776 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2777 nameCompare = name.mid( 3 );
2779 if ( name.size() > 3 && QStringView {name}.mid( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2780 nameCompare = name.mid( 3 );
2782 if ( nameCompare.compare( QLatin1String(
"DWithin" ), Qt::CaseInsensitive ) == 0 )
2783 return QStringLiteral(
"DWithin" );
2784 if ( nameCompare.compare( QLatin1String(
"Beyond" ), Qt::CaseInsensitive ) == 0 )
2785 return QStringLiteral(
"Beyond" );
2789QString QgsOgcUtilsSQLStatementToFilter::getGeometryColumnSRSName(
const QgsSQLStatement::Node *node )
2797 const auto constMLayerProperties = mLayerProperties;
2800 if ( prop.mName.compare( mMapTableAliasToNames[col->
tableName()], Qt::CaseInsensitive ) == 0 &&
2801 prop.mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2803 return prop.mSRSName;
2807 if ( !mLayerProperties.empty() &&
2808 mLayerProperties.at( 0 ).mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2810 return mLayerProperties.at( 0 ).mSRSName;
2816 QList<QgsSQLStatement::Node *> args,
2817 bool lastArgIsSRSName,
2819 bool &axisInversion )
2822 axisInversion = mInvertAxisOrientation;
2824 if ( lastArgIsSRSName )
2829 mErrorMessage = QObject::tr(
"%1: Last argument must be string or integer literal" ).arg( mainNode->
name() );
2833 if ( lit->
value().type() == QVariant::Int )
2837 srsName =
"EPSG:" + QString::number( lit->
value().toInt() );
2841 srsName =
"urn:ogc:def:crs:EPSG::" + QString::number( lit->
value().toInt() );
2847 if (
srsName.startsWith( QLatin1String(
"EPSG:" ), Qt::CaseInsensitive ) )
2859 axisInversion = !axisInversion;
2869 if ( node->
name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 )
2871 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2872 if ( args.size() != 1 && args.size() != 2 )
2874 mErrorMessage = QObject::tr(
"Function %1 should have 1 or 2 arguments" ).arg( node->
name() );
2875 return QDomElement();
2881 mErrorMessage = QObject::tr(
"%1: First argument must be string literal" ).arg( node->
name() );
2882 return QDomElement();
2887 if ( ! processSRSName( node, args, args.size() == 2,
srsName, axisInversion ) )
2889 return QDomElement();
2895 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2897 if ( geomElem.isNull() )
2899 mErrorMessage = QObject::tr(
"%1: invalid WKT" ).arg( node->
name() );
2900 return QDomElement();
2907 if ( node->
name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 )
2909 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2910 if ( args.size() != 4 && args.size() != 5 )
2912 mErrorMessage = QObject::tr(
"Function %1 should have 4 or 5 arguments" ).arg( node->
name() );
2913 return QDomElement();
2918 for (
int i = 0; i < 4; i++ )
2923 mErrorMessage = QObject::tr(
"%1: Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2924 return QDomElement();
2928 if ( lit->
value().type() == QVariant::Int )
2929 val = lit->
value().toInt();
2930 else if ( lit->
value().type() == QVariant::LongLong )
2931 val = lit->
value().toLongLong();
2932 else if ( lit->
value().type() == QVariant::Double )
2933 val = lit->
value().toDouble();
2936 mErrorMessage = QObject::tr(
"%1 Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2937 return QDomElement();
2951 if ( ! processSRSName( node, args, args.size() == 5,
srsName, axisInversion ) )
2953 return QDomElement();
2964 if ( node->
name().compare( QLatin1String(
"ST_GeomFromGML" ), Qt::CaseInsensitive ) == 0 )
2966 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2967 if ( args.size() != 1 )
2969 mErrorMessage = QObject::tr(
"Function %1 should have 1 argument" ).arg( node->
name() );
2970 return QDomElement();
2976 mErrorMessage = QObject::tr(
"%1: Argument must be string literal" ).arg( node->
name() );
2977 return QDomElement();
2980 QDomDocument geomDoc;
2982 if ( !geomDoc.setContent( gml,
true ) )
2984 mErrorMessage = QObject::tr(
"ST_GeomFromGML: unable to parse XML" );
2985 return QDomElement();
2988 const QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(),
true );
2990 return geomNode.toElement();
2994 QString ogcName( mapBinarySpatialToOgc( node->
name() ) );
2995 if ( !ogcName.isEmpty() )
2997 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2998 if ( args.size() != 2 )
3000 mErrorMessage = QObject::tr(
"Function %1 should have 2 arguments" ).arg( node->
name() );
3001 return QDomElement();
3004 for (
int i = 0; i < 2; i ++ )
3007 (
static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
3008 static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
3010 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
3017 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + ogcName );
3018 const auto constArgs = args;
3022 if ( !mErrorMessage.isEmpty() )
3024 mCurrentSRSName.clear();
3025 return QDomElement();
3028 funcElem.appendChild( childElem );
3031 mCurrentSRSName.clear();
3035 ogcName = mapTernarySpatialToOgc( node->
name() );
3036 if ( !ogcName.isEmpty() )
3038 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
3039 if ( args.size() != 3 )
3041 mErrorMessage = QObject::tr(
"Function %1 should have 3 arguments" ).arg( node->
name() );
3042 return QDomElement();
3045 for (
int i = 0; i < 2; i ++ )
3048 (
static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
3049 static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
3051 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
3056 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + node->
name().mid( 3 ) );
3057 for (
int i = 0; i < 2; i++ )
3059 const QDomElement childElem =
toOgcFilter( args[i] );
3060 if ( !mErrorMessage.isEmpty() )
3062 mCurrentSRSName.clear();
3063 return QDomElement();
3066 funcElem.appendChild( childElem );
3068 mCurrentSRSName.clear();
3073 mErrorMessage = QObject::tr(
"Function %1 3rd argument should be a numeric value or a string made of a numeric value followed by a string" ).arg( node->
name() );
3074 return QDomElement();
3079 mErrorMessage = QObject::tr(
"Function %1 3rd argument should be a numeric value or a string made of a numeric value followed by a string" ).arg( node->
name() );
3080 return QDomElement();
3083 QString unit( QStringLiteral(
"m" ) );
3084 switch ( lit->
value().type() )
3087 distance = QString::number( lit->
value().toInt() );
3089 case QVariant::LongLong:
3090 distance = QString::number( lit->
value().toLongLong() );
3092 case QVariant::Double:
3095 case QVariant::String:
3097 distance = lit->
value().toString();
3098 for (
int i = 0; i < distance.size(); i++ )
3100 if ( !( ( distance[i] >=
'0' && distance[i] <=
'9' ) || distance[i] ==
'-' || distance[i] ==
'.' || distance[i] ==
'e' || distance[i] ==
'E' ) )
3102 unit = distance.mid( i ).trimmed();
3103 distance = distance.mid( 0, i );
3111 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( lit->
value().type() );
3112 return QDomElement();
3115 QDomElement distanceElem = mDoc.createElement( mFilterPrefix +
":Distance" );
3117 distanceElem.setAttribute( QStringLiteral(
"uom" ), unit );
3119 distanceElem.setAttribute( QStringLiteral(
"unit" ), unit );
3120 distanceElem.appendChild( mDoc.createTextNode( distance ) );
3121 funcElem.appendChild( distanceElem );
3126 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
3127 funcElem.setAttribute( QStringLiteral(
"name" ), node->
name() );
3128 const auto constList = node->
args()->
list();
3132 if ( !mErrorMessage.isEmpty() )
3133 return QDomElement();
3135 funcElem.appendChild( childElem );
3141 const QString &leftTable )
3149 QList<QDomElement> listElem;
3151 for (
const QString &columnName : constUsingColumns )
3153 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
3154 QDomElement propElem1 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3155 propElem1.appendChild( mDoc.createTextNode( leftTable +
"/" + columnName ) );
3156 eqElem.appendChild( propElem1 );
3157 QDomElement propElem2 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3158 propElem2.appendChild( mDoc.createTextNode( node->
tableDef()->
name() +
"/" + columnName ) );
3159 eqElem.appendChild( propElem2 );
3160 listElem.append( eqElem );
3163 if ( listElem.size() == 1 )
3167 else if ( listElem.size() > 1 )
3169 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3170 const auto constListElem = listElem;
3171 for (
const QDomElement &elem : constListElem )
3173 andElem.appendChild( elem );
3178 return QDomElement();
3183 if ( node->
alias().isEmpty() )
3185 mMapTableAliasToNames[ node->
name()] = node->
name();
3189 mMapTableAliasToNames[ node->
alias()] = node->
name();
3195 QList<QDomElement> listElem;
3198 ( node->
tables().size() != 1 || !node->
joins().empty() ) )
3200 mErrorMessage = QObject::tr(
"Joins are only supported with WFS 2.0" );
3201 return QDomElement();
3205 const auto constTables = node->
tables();
3210 const auto constJoins = node->
joins();
3213 visit( join->tableDef() );
3217 const QList< QgsSQLStatement::NodeTableDef *> nodeTables = node->
tables();
3218 QString leftTable = nodeTables.at( nodeTables.length() - 1 )->name();
3221 const QDomElement joinElem =
toOgcFilter( join, leftTable );
3222 if ( !mErrorMessage.isEmpty() )
3223 return QDomElement();
3224 listElem.append( joinElem );
3225 leftTable = join->tableDef()->name();
3229 if ( node->
where() )
3232 if ( !mErrorMessage.isEmpty() )
3233 return QDomElement();
3234 listElem.append( whereElem );
3238 if ( listElem.size() == 1 )
3242 else if ( listElem.size() > 1 )
3244 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3245 const auto constListElem = listElem;
3246 for (
const QDomElement &elem : constListElem )
3248 andElem.appendChild( elem );
3253 return QDomElement();
3259 mPropertyName = QStringLiteral(
"PropertyName" );
3260 mPrefix = QStringLiteral(
"ogc" );
3264 mPropertyName = QStringLiteral(
"ValueReference" );
3265 mPrefix = QStringLiteral(
"fes" );
3271 if ( element.isNull() )
3275 if ( isBinaryOperator( element.tagName() ) )
3281 if ( isSpatialOperator( element.tagName() ) )
3287 if ( element.tagName() == QLatin1String(
"Not" ) )
3291 else if ( element.tagName() == QLatin1String(
"PropertyIsNull" ) )
3295 else if ( element.tagName() == QLatin1String(
"Literal" ) )
3299 else if ( element.tagName() == QLatin1String(
"Function" ) )
3303 else if ( element.tagName() == mPropertyName )
3307 else if ( element.tagName() == QLatin1String(
"PropertyIsBetween" ) )
3312 mErrorMessage += QObject::tr(
"unable to convert '%1' element to a valid expression: it is not supported yet or it has invalid arguments" ).arg( element.tagName() );
3318 if ( element.isNull() )
3321 int op = binaryOperatorFromTagName( element.tagName() );
3324 mErrorMessage = QObject::tr(
"'%1' binary operator not supported." ).arg( element.tagName() );
3328 if ( op ==
QgsExpressionNodeBinaryOperator::boLike && element.hasAttribute( QStringLiteral(
"matchCase" ) ) && element.attribute( QStringLiteral(
"matchCase" ) ) == QLatin1String(
"false" ) )
3333 QDomElement operandElem = element.firstChildElement();
3338 mErrorMessage = QObject::tr(
"invalid left operand for '%1' binary operator" ).arg( element.tagName() );
3342 const std::unique_ptr<QgsExpressionNode> leftOp( expr->clone() );
3343 for ( operandElem = operandElem.nextSiblingElement(); !operandElem.isNull(); operandElem = operandElem.nextSiblingElement() )
3348 mErrorMessage = QObject::tr(
"invalid right operand for '%1' binary operator" ).arg( element.tagName() );
3355 if ( element.hasAttribute( QStringLiteral(
"wildCard" ) ) )
3357 wildCard = element.attribute( QStringLiteral(
"wildCard" ) );
3360 if ( element.hasAttribute( QStringLiteral(
"singleChar" ) ) )
3362 singleChar = element.attribute( QStringLiteral(
"singleChar" ) );
3364 QString escape = QStringLiteral(
"\\" );
3365 if ( element.hasAttribute( QStringLiteral(
"escape" ) ) )
3367 escape = element.attribute( QStringLiteral(
"escape" ) );
3369 if ( element.hasAttribute( QStringLiteral(
"escapeChar" ) ) )
3371 escape = element.attribute( QStringLiteral(
"escapeChar" ) );
3375 if ( !wildCard.isEmpty() && wildCard != QLatin1String(
"%" ) )
3377 oprValue.replace(
'%', QLatin1String(
"\\%" ) );
3378 if ( oprValue.startsWith( wildCard ) )
3380 oprValue.replace( 0, 1, QStringLiteral(
"%" ) );
3383 QRegularExpressionMatch match = rx.match( oprValue );
3385 while ( match.hasMatch() )
3387 pos = match.capturedStart();
3388 oprValue.replace( pos + 1, 1, QStringLiteral(
"%" ) );
3390 match = rx.match( oprValue, pos );
3392 oprValue.replace( escape + wildCard, wildCard );
3394 if ( !singleChar.isEmpty() && singleChar != QLatin1String(
"_" ) )
3396 oprValue.replace(
'_', QLatin1String(
"\\_" ) );
3397 if ( oprValue.startsWith( singleChar ) )
3399 oprValue.replace( 0, 1, QStringLiteral(
"_" ) );
3402 QRegularExpressionMatch match = rx.match( oprValue );
3404 while ( match.hasMatch() )
3406 pos = match.capturedStart();
3407 oprValue.replace( pos + 1, 1, QStringLiteral(
"_" ) );
3409 match = rx.match( oprValue, pos );
3411 oprValue.replace( escape + singleChar, singleChar );
3413 if ( !escape.isEmpty() && escape != QLatin1String(
"\\" ) )
3415 oprValue.replace( escape + escape, escape );
3423 if ( expr == leftOp )
3425 mErrorMessage = QObject::tr(
"only one operand for '%1' binary operator" ).arg( element.tagName() );
3439 QDomElement childElem = element.firstChildElement();
3441 while ( !childElem.isNull() && gml2Str.isEmpty() )
3443 if ( childElem.tagName() != mPropertyName )
3445 QTextStream gml2Stream( &gml2Str );
3446 childElem.save( gml2Stream, 0 );
3448 childElem = childElem.nextSiblingElement();
3450 if ( !gml2Str.isEmpty() )
3456 mErrorMessage = QObject::tr(
"No OGC Geometry found" );
3469 if ( element.isNull() || element.tagName() != mPropertyName )
3471 mErrorMessage = QObject::tr(
"%1:PropertyName expected, got %2" ).arg( mPrefix, element.tagName() );
3480 if ( element.isNull() || element.tagName() != QLatin1String(
"Literal" ) )
3482 mErrorMessage = QObject::tr(
"%1:Literal expected, got %2" ).arg( mPrefix, element.tagName() );
3486 std::unique_ptr<QgsExpressionNode> root;
3487 if ( !element.hasChildNodes() )
3490 return root.release();
3494 QDomNode childNode = element.firstChild();
3495 while ( !childNode.isNull() )
3497 std::unique_ptr<QgsExpressionNode> operand;
3499 if ( childNode.nodeType() == QDomNode::ElementNode )
3502 const QDomElement operandElem = childNode.toElement();
3506 mErrorMessage = QObject::tr(
"'%1' is an invalid or not supported content for %2:Literal" ).arg( operandElem.tagName(), mPrefix );
3513 QVariant value = childNode.nodeValue();
3515 bool converted =
false;
3520 QDomElement propertyNameElement = element.previousSiblingElement( mPropertyName );
3521 if ( propertyNameElement.isNull() || propertyNameElement.tagName() != mPropertyName )
3523 propertyNameElement = element.nextSiblingElement( mPropertyName );
3525 if ( !propertyNameElement.isNull() || propertyNameElement.tagName() == mPropertyName )
3527 const int fieldIndex = mLayer->
fields().
indexOf( propertyNameElement.firstChild().nodeValue() );
3528 if ( fieldIndex != -1 )
3541 const double d = value.toDouble( &ok );
3554 root = std::move( operand );
3561 childNode = childNode.nextSibling();
3565 return root.release();
3572 if ( element.tagName() != QLatin1String(
"Not" ) )
3575 const QDomElement operandElem = element.firstChildElement();
3579 mErrorMessage = QObject::tr(
"invalid operand for '%1' unary operator" ).arg( element.tagName() );
3589 if ( element.tagName() != QLatin1String(
"PropertyIsNull" ) )
3594 const QDomElement operandElem = element.firstChildElement();
3605 if ( element.isNull() || element.tagName() != QLatin1String(
"Function" ) )
3607 mErrorMessage = QObject::tr(
"%1:Function expected, got %2" ).arg( mPrefix, element.tagName() );
3615 if ( element.attribute( QStringLiteral(
"name" ) ) != funcDef->
name() )
3620 QDomElement operandElem = element.firstChildElement();
3621 while ( !operandElem.isNull() )
3628 args->append( op.release() );
3630 operandElem = operandElem.nextSiblingElement();
3642 std::unique_ptr<QgsExpressionNode> operand;
3643 std::unique_ptr<QgsExpressionNode> lowerBound;
3644 std::unique_ptr<QgsExpressionNode> upperBound;
3646 QDomElement operandElem = element.firstChildElement();
3647 while ( !operandElem.isNull() )
3649 if ( operandElem.tagName() == QLatin1String(
"LowerBoundary" ) )
3651 const QDomElement lowerBoundElem = operandElem.firstChildElement();
3654 else if ( operandElem.tagName() == QLatin1String(
"UpperBoundary" ) )
3656 const QDomElement upperBoundElem = operandElem.firstChildElement();
3665 if ( operand && lowerBound && upperBound )
3668 operandElem = operandElem.nextSiblingElement();
3671 if ( !operand || !lowerBound || !upperBound )
3673 mErrorMessage = QObject::tr(
"missing some required sub-elements in %1:PropertyIsBetween" ).arg( mPrefix );
3684 return mErrorMessage;
3689 const thread_local QRegularExpression re_url( QRegularExpression::anchoredPattern( QStringLiteral(
"http://www\\.opengis\\.net/gml/srs/epsg\\.xml#(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
3690 if (
const QRegularExpressionMatch match = re_url.match( crsName ); match.hasMatch() )
3692 authority = QStringLiteral(
"EPSG" );
3693 code = match.captured( 1 );
3697 const thread_local QRegularExpression re_ogc_urn( QRegularExpression::anchoredPattern( QStringLiteral(
"urn:ogc:def:crs:([^:]+).+(?<=:)([^:]+)" ) ), QRegularExpression::CaseInsensitiveOption );
3698 if (
const QRegularExpressionMatch match = re_ogc_urn.match( crsName ); match.hasMatch() )
3700 authority = match.captured( 1 );
3701 code = match.captured( 2 );
3705 const thread_local QRegularExpression re_x_ogc_urn( QRegularExpression::anchoredPattern( QStringLiteral(
"urn:x-ogc:def:crs:([^:]+).+(?<=:)([^:]+)" ) ), QRegularExpression::CaseInsensitiveOption );
3706 if (
const QRegularExpressionMatch match = re_x_ogc_urn.match( crsName ); match.hasMatch() )
3708 authority = match.captured( 1 );
3709 code = match.captured( 2 );
3713 const thread_local QRegularExpression re_http_uri( QRegularExpression::anchoredPattern( QStringLiteral(
"http://www\\.opengis\\.net/def/crs/([^/]+).+/([^/]+)" ) ), QRegularExpression::CaseInsensitiveOption );
3714 if (
const QRegularExpressionMatch match = re_http_uri.match( crsName ); match.hasMatch() )
3716 authority = match.captured( 1 );
3717 code = match.captured( 2 );
3721 const thread_local QRegularExpression re_auth_code( QRegularExpression::anchoredPattern( QStringLiteral(
"([^:]+):(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
3722 if (
const QRegularExpressionMatch match = re_auth_code.match( crsName ); match.hasMatch() )
3724 authority = match.captured( 1 );
3725 code = match.captured( 2 );
GeometryOperationResult
Success or failure of a geometry operation.
@ Success
Operation succeeded.
virtual void swapXy()=0
Swaps the x and y coordinates from the geometry.
QgsWkbTypes::Type readHeader() const
readHeader
This class represents a coordinate reference system (CRS).
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
bool createFromUserInput(const QString &definition)
Set up this CRS from various text formats.
bool hasAxisInverted() const
Returns whether axis is inverted (e.g., for WMS 1.3) for the CRS.
Custom exception class for Coordinate Reference System related exceptions.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
A abstract base class for defining QgsExpression functions.
int params() const
The number of parameters this function takes.
virtual bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
Will be called during prepare to determine if the function is static.
QString name() const
The name of the function.
virtual QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
Evaluates the function, first evaluating all required arguments before passing them to the function's...
A binary expression operator, which operates on two values.
QgsExpressionNode * opLeft() const
Returns the node to the left of the operator.
QgsExpressionNode * opRight() const
Returns the node to the right of the operator.
QgsExpressionNodeBinaryOperator::BinaryOperator op() const
Returns the binary operator.
QString text() const
Returns a the name of this operator without the operands.
BinaryOperator
list of binary operators
An expression node which takes it value from a feature's field.
QString name() const
The name of the column.
An expression node for expression functions.
int fnIndex() const
Returns the index of the node's function.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
An expression node for value IN or NOT IN clauses.
QgsExpressionNode * node() const
Returns the expression node.
QgsExpressionNode::NodeList * list() const
Returns the list of nodes to search for matching values within.
bool isNotIn() const
Returns true if this node is a "NOT IN" operator, or false if the node is a normal "IN" operator.
An expression node for literal values.
QVariant value() const
The value of the literal.
A unary node is either negative as in boolean (not) or as in numbers (minus).
QgsExpressionNodeUnaryOperator::UnaryOperator op() const
Returns the unary operator.
QString text() const
Returns a the name of this operator without the operands.
QgsExpressionNode * operand() const
Returns the node the operator will operate upon.
A list of expression nodes.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
Abstract base class for all nodes that can appear in an expression.
bool hasCachedStaticValue() const
Returns true if the node can be replaced by a static cached value.
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
QVariant cachedStaticValue() const
Returns the node's static cached value.
Class for parsing and evaluation of expressions (formerly called "search strings").
static const QList< QgsExpressionFunction * > & Functions()
void setExpression(const QString &expression)
Set the expression string, will reset the whole internal structure.
static int functionIndex(const QString &name)
Returns index of the function in Functions array.
QString dump() const
Returns an expression string, constructed from the internal abstract syntax tree.
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
Encapsulate a field in an attribute table or data source.
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
A geometry is the spatial representation of a feature.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const
Export the geometry to WKB.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
QgsCoordinateReferenceSystem crs
@ HTTP_EPSG_DOT_XML
e.g EPSG:4326
@ OGC_HTTP_URI
e.g. urn:x-ogc:def:crs:EPSG::4326
@ X_OGC_URN
e.g. urn:ogc:def:crs:EPSG::4326
@ OGC_URN
e.g. http://www.opengis.net/gml/srs/epsg.xml#4326 (called "OGC HTTP URL" in GeoServer WFS configurati...
@ AUTH_CODE
unknown/unhandled flavor
static CRSFlavor parseCrsName(const QString &crsName, QString &authority, QString &code)
Parse a CRS name in one of the flavors of OGC services, and decompose it as authority and code.
Internal use by QgsOgcUtils.
bool GMLNamespaceUsed() const
Returns whether the gml: namespace is used.
QgsOgcUtilsExprToFilter(QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, QgsOgcUtils::FilterVersion filterVersion, const QString &namespacePrefix, const QString &namespaceURI, const QString &geometryName, const QString &srsName, bool honourAxisOrientation, bool invertAxisOrientation)
Constructor.
QDomElement expressionNodeToOgcFilter(const QgsExpressionNode *node, QgsExpression *expression, const QgsExpressionContext *context)
Convert an expression to a OGC filter.
QString errorMessage() const
Returns the error message.
Internal use by QgsOgcUtils.
QgsExpressionNodeFunction * nodeSpatialOperatorFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with spatial operators.
QgsExpressionNodeUnaryOperator * nodeNotFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with Not operator.
QgsExpressionNodeColumnRef * nodeColumnRefFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with column references.
QgsExpressionNode * nodeIsBetweenFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with boudnaries operator.
QgsOgcUtilsExpressionFromFilter(QgsOgcUtils::FilterVersion version=QgsOgcUtils::FILTER_OGC_1_0, const QgsVectorLayer *layer=nullptr)
Constructor for QgsOgcUtilsExpressionFromFilter.
QgsExpressionNodeBinaryOperator * nodeBinaryOperatorFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with binary operators.
QgsExpressionNodeFunction * nodeFunctionFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with functions.
QgsExpressionNode * nodeFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document element.
QgsExpressionNodeBinaryOperator * nodePropertyIsNullFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with IsNull operator.
QString errorMessage() const
Returns the underlying error message, or an empty string in case of no error.
QgsExpressionNode * nodeLiteralFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with literal tag.
Internal use by QgsOgcUtils.
QgsOgcUtilsSQLStatementToFilter(QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, QgsOgcUtils::FilterVersion filterVersion, const QList< QgsOgcUtils::LayerProperties > &layerProperties, bool honourAxisOrientation, bool invertAxisOrientation, const QMap< QString, QString > &mapUnprefixedTypenameToPrefixedTypename)
Constructor.
QDomElement toOgcFilter(const QgsSQLStatement::Node *node)
Convert a SQL statement to a OGC filter.
bool GMLNamespaceUsed() const
Returns whether the gml: namespace is used.
QString errorMessage() const
Returns the error message.
The QgsOgcUtils class provides various utility functions for conversion between OGC (Open Geospatial ...
static QgsRectangle rectangleFromGMLBox(const QDomNode &boxNode)
Read rectangle from GML2 Box.
static QDomElement expressionToOgcExpression(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr, bool requiresFilterElement=false)
Creates an OGC expression XML element from the exp expression with default values for the geometry na...
static QColor colorFromOgcFill(const QDomElement &fillElement)
Parse XML with OGC fill into QColor.
static QDomElement expressionToOgcFilter(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates OGC filter XML element.
FilterVersion
OGC filter version.
static QDomElement SQLStatementToOgcFilter(const QgsSQLStatement &statement, QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, FilterVersion filterVersion, const QList< LayerProperties > &layerProperties, bool honourAxisOrientation, bool invertAxisOrientation, const QMap< QString, QString > &mapUnprefixedTypenameToPrefixedTypename, QString *errorMessage=nullptr)
Creates OGC filter XML element from the WHERE and JOIN clauses of a SQL statement.
static QgsRectangle rectangleFromGMLEnvelope(const QDomNode &envelopeNode)
Read rectangle from GML3 Envelope.
static QDomElement geometryToGML(const QgsGeometry &geometry, QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, const QString &srsName, bool invertAxisOrientation, const QString &gmlIdBase, int precision=17)
Exports the geometry to GML.
static QgsGeometry geometryFromGML(const QString &xmlString, const QgsOgcUtils::Context &context=QgsOgcUtils::Context())
Static method that creates geometry from GML.
static QDomElement rectangleToGMLEnvelope(QgsRectangle *env, QDomDocument &doc, int precision=17)
Exports the rectangle to GML3 Envelope.
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
static QDomElement rectangleToGMLBox(QgsRectangle *box, QDomDocument &doc, int precision=17)
Exports the rectangle to GML2 Box.
A class to represent a 2D point.
A rectangle specified with double values.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
void setYMinimum(double y) SIP_HOLDGIL
Set the minimum y value.
void setXMaximum(double x) SIP_HOLDGIL
Set the maximum x value.
void setXMinimum(double x) SIP_HOLDGIL
Set the minimum x value.
void setYMaximum(double y) SIP_HOLDGIL
Set the maximum y value.
void normalize()
Normalize the rectangle so it has non-negative width/height.
'X BETWEEN y and z' operator
QgsSQLStatement::Node * node() const
Variable at the left of BETWEEN.
QgsSQLStatement::Node * minVal() const
Minimum bound.
bool isNotBetween() const
Whether this is a NOT BETWEEN operator.
QgsSQLStatement::Node * maxVal() const
Maximum bound.
Binary logical/arithmetical operator (AND, OR, =, +, ...)
QgsSQLStatement::Node * opLeft() const
Left operand.
QgsSQLStatement::BinaryOperator op() const
Operator.
QgsSQLStatement::Node * opRight() const
Right operand.
QString name() const
The name of the column.
QString tableName() const
The name of the table. May be empty.
Function with a name and arguments node.
QgsSQLStatement::NodeList * args() const
Returns arguments.
QString name() const
Returns function name.
bool isNotIn() const
Whether this is a NOT IN operator.
QgsSQLStatement::Node * node() const
Variable at the left of IN.
QgsSQLStatement::NodeList * list() const
Values list.
QgsSQLStatement::NodeTableDef * tableDef() const
Table definition.
QgsSQLStatement::Node * onExpr() const
On expression. Will be nullptr if usingColumns() is not empty.
QList< QString > usingColumns() const
Columns referenced by USING.
QList< QgsSQLStatement::Node * > list()
Returns list.
Literal value (integer, integer64, double, string)
QVariant value() const
The value of the literal.
QList< QgsSQLStatement::NodeJoin * > joins() const
Returns the list of joins.
QgsSQLStatement::Node * where() const
Returns the where clause.
QList< QgsSQLStatement::NodeTableDef * > tables() const
Returns the list of tables.
QString name() const
Table name.
QString alias() const
Table alias.
Unary logicial/arithmetical operator ( NOT, - )
QgsSQLStatement::UnaryOperator op() const
Operator.
QgsSQLStatement::Node * operand() const
Operand.
virtual QgsSQLStatement::NodeType nodeType() const =0
Abstract virtual that returns the type of this node.
Class for parsing SQL statements.
BinaryOperator
list of binary operators
static const char * BINARY_OPERATOR_TEXT[]
const QgsSQLStatement::Node * rootNode() const
Returns the root node of the statement.
static const char * UNARY_OPERATOR_TEXT[]
static QString qRegExpEscape(const QString &string)
Returns an escaped string matching the behavior of QRegExp::escape.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
Represents a vector layer which manages a vector based data sets.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Custom exception class for Wkb related exceptions.
Type
The WKB type describes the number of dimensions a geometry has.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
QMap< QString, QString > QgsStringMap
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item.
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
#define QgsDebugMsgLevel(str, level)
Q_GLOBAL_STATIC_WITH_ARGS(IntMap, BINARY_OPERATORS_TAG_NAMES_MAP,({ { QLatin1String("Or"), QgsExpressionNodeBinaryOperator::boOr }, { QLatin1String("And"), QgsExpressionNodeBinaryOperator::boAnd }, { QLatin1String("PropertyIsEqualTo"), QgsExpressionNodeBinaryOperator::boEQ }, { QLatin1String("PropertyIsNotEqualTo"), QgsExpressionNodeBinaryOperator::boNE }, { QLatin1String("PropertyIsLessThanOrEqualTo"), QgsExpressionNodeBinaryOperator::boLE }, { QLatin1String("PropertyIsGreaterThanOrEqualTo"), QgsExpressionNodeBinaryOperator::boGE }, { QLatin1String("PropertyIsLessThan"), QgsExpressionNodeBinaryOperator::boLT }, { QLatin1String("PropertyIsGreaterThan"), QgsExpressionNodeBinaryOperator::boGT }, { QLatin1String("PropertyIsLike"), QgsExpressionNodeBinaryOperator::boLike }, { QLatin1String("Add"), QgsExpressionNodeBinaryOperator::boPlus }, { QLatin1String("Sub"), QgsExpressionNodeBinaryOperator::boMinus }, { QLatin1String("Mul"), QgsExpressionNodeBinaryOperator::boMul }, { QLatin1String("Div"), QgsExpressionNodeBinaryOperator::boDiv }, })) static int binaryOperatorFromTagName(const QString &tagName)
QMap< QString, int > IntMap
const QString & geometryName
const QgsCoordinateReferenceSystem & crs
The Context struct stores the current layer and coordinate transform context.
const QgsMapLayer * layer
QgsCoordinateTransformContext transformContext