30 #include <QStringList>
31 #include <QTextStream>
33 #include <QRegularExpression>
36 #include <netinet/in.h>
42 #define GML_NAMESPACE QStringLiteral( "http://www.opengis.net/gml" )
43 #define GML32_NAMESPACE QStringLiteral( "http://www.opengis.net/gml/3.2" )
44 #define OGC_NAMESPACE QStringLiteral( "http://www.opengis.net/ogc" )
45 #define FES_NAMESPACE QStringLiteral( "http://www.opengis.net/fes/2.0" )
51 const QString &srsName,
52 bool honourAxisOrientation,
53 bool invertAxisOrientation )
56 , mGMLVersion( gmlVersion )
57 , mFilterVersion( filterVersion )
60 , mInvertAxisOrientation( invertAxisOrientation )
61 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
62 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
66 if ( !mSrsName.isEmpty() )
72 mInvertAxisOrientation = !mInvertAxisOrientation;
79 QDomElement geometryTypeElement = geometryNode.toElement();
80 QString geomType = geometryTypeElement.tagName();
83 if ( !( geomType == QLatin1String(
"Point" ) || geomType == QLatin1String(
"LineString" ) || geomType == QLatin1String(
"Polygon" ) ||
84 geomType == QLatin1String(
"MultiPoint" ) || geomType == QLatin1String(
"MultiLineString" ) || geomType == QLatin1String(
"MultiPolygon" ) ||
85 geomType == QLatin1String(
"Box" ) || geomType == QLatin1String(
"Envelope" ) ) )
87 QDomNode geometryChild = geometryNode.firstChild();
88 if ( geometryChild.isNull() )
92 geometryTypeElement = geometryChild.toElement();
93 geomType = geometryTypeElement.tagName();
96 if ( !( geomType == QLatin1String(
"Point" ) || geomType == QLatin1String(
"LineString" ) || geomType == QLatin1String(
"Polygon" ) ||
97 geomType == QLatin1String(
"MultiPoint" ) || geomType == QLatin1String(
"MultiLineString" ) || geomType == QLatin1String(
"MultiPolygon" ) ||
98 geomType == QLatin1String(
"Box" ) || geomType == QLatin1String(
"Envelope" ) ) )
101 if ( geomType == QLatin1String(
"Point" ) )
103 geometry = geometryFromGMLPoint( geometryTypeElement );
105 else if ( geomType == QLatin1String(
"LineString" ) )
107 geometry = geometryFromGMLLineString( geometryTypeElement );
109 else if ( geomType == QLatin1String(
"Polygon" ) )
111 geometry = geometryFromGMLPolygon( geometryTypeElement );
113 else if ( geomType == QLatin1String(
"MultiPoint" ) )
115 geometry = geometryFromGMLMultiPoint( geometryTypeElement );
117 else if ( geomType == QLatin1String(
"MultiLineString" ) )
119 geometry = geometryFromGMLMultiLineString( geometryTypeElement );
121 else if ( geomType == QLatin1String(
"MultiPolygon" ) )
123 geometry = geometryFromGMLMultiPolygon( geometryTypeElement );
125 else if ( geomType == QLatin1String(
"Box" ) )
129 else if ( geomType == QLatin1String(
"Envelope" ) )
143 if ( geometryTypeElement.hasAttribute( QStringLiteral(
"srsName" ) ) )
145 QString srsName { geometryTypeElement.attribute( QStringLiteral(
"srsName" ) ) };
148 const bool ignoreAxisOrientation { srsName.startsWith( QLatin1String(
"http://www.opengis.net/gml/srs/" ) ) || srsName.startsWith( QLatin1String(
"EPSG:" ) ) };
152 if ( srsName.startsWith( QLatin1String(
"http://www.opengis.net/gml/srs/" ) ) )
154 const auto parts { srsName.split( QRegularExpression( QStringLiteral( R
"raw(/|#|\.)raw" ) ) ) };
155 if ( parts.length() == 10 )
157 srsName = QStringLiteral(
"http://www.opengis.net/def/crs/%1/0/%2" ).arg( parts[ 7 ].toUpper(), parts[ 9 ] );
171 if ( result != QgsGeometry::OperationResult::Success )
173 QgsDebugMsgLevel( QStringLiteral(
"Error transforming geometry: %1" ).arg( result ), 2 );
190 QString xml = QStringLiteral(
"<tmp xmlns=\"%1\" xmlns:gml=\"%1\">%2</tmp>" ).arg(
GML_NAMESPACE, xmlString );
192 if ( !doc.setContent( xml,
true ) )
195 return geometryFromGML( doc.documentElement().firstChildElement(), context );
199 QgsGeometry QgsOgcUtils::geometryFromGMLPoint(
const QDomElement &geometryElement )
203 QDomNodeList coordList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
204 if ( !coordList.isEmpty() )
206 QDomElement coordElement = coordList.at( 0 ).toElement();
207 if ( readGMLCoordinates( pointCoordinate, coordElement ) != 0 )
214 QDomNodeList posList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pos" ) );
215 if ( posList.size() < 1 )
219 QDomElement posElement = posList.at( 0 ).toElement();
220 if ( readGMLPositions( pointCoordinate, posElement ) != 0 )
226 if ( pointCoordinate.empty() )
231 QgsPolylineXY::const_iterator point_it = pointCoordinate.constBegin();
232 char e = htonl( 1 ) != 1;
233 double x = point_it->x();
234 double y = point_it->y();
235 int size = 1 +
sizeof( int ) + 2 *
sizeof(
double );
238 unsigned char *wkb =
new unsigned char[size];
241 memcpy( &( wkb )[wkbPosition], &e, 1 );
243 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
244 wkbPosition +=
sizeof( int );
245 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
246 wkbPosition +=
sizeof( double );
247 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
254 QgsGeometry QgsOgcUtils::geometryFromGMLLineString(
const QDomElement &geometryElement )
258 QDomNodeList coordList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
259 if ( !coordList.isEmpty() )
261 QDomElement coordElement = coordList.at( 0 ).toElement();
262 if ( readGMLCoordinates( lineCoordinates, coordElement ) != 0 )
269 QDomNodeList posList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
270 if ( posList.size() < 1 )
274 QDomElement posElement = posList.at( 0 ).toElement();
275 if ( readGMLPositions( lineCoordinates, posElement ) != 0 )
281 char e = htonl( 1 ) != 1;
282 int size = 1 + 2 *
sizeof( int ) + lineCoordinates.size() * 2 *
sizeof( double );
285 unsigned char *wkb =
new unsigned char[size];
289 int nPoints = lineCoordinates.size();
292 memcpy( &( wkb )[wkbPosition], &e, 1 );
294 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
295 wkbPosition +=
sizeof( int );
296 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
297 wkbPosition +=
sizeof( int );
299 QgsPolylineXY::const_iterator iter;
300 for ( iter = lineCoordinates.constBegin(); iter != lineCoordinates.constEnd(); ++iter )
304 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
305 wkbPosition +=
sizeof( double );
306 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
307 wkbPosition +=
sizeof( double );
315 QgsGeometry QgsOgcUtils::geometryFromGMLPolygon(
const QDomElement &geometryElement )
322 QDomNodeList outerBoundaryList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"outerBoundaryIs" ) );
323 if ( !outerBoundaryList.isEmpty() )
325 QDomElement coordinatesElement = outerBoundaryList.at( 0 ).firstChild().firstChild().toElement();
326 if ( coordinatesElement.isNull() )
330 if ( readGMLCoordinates( exteriorPointList, coordinatesElement ) != 0 )
334 ringCoordinates.push_back( exteriorPointList );
337 QDomNodeList innerBoundaryList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"innerBoundaryIs" ) );
338 for (
int i = 0; i < innerBoundaryList.size(); ++i )
341 coordinatesElement = innerBoundaryList.at( i ).firstChild().firstChild().toElement();
342 if ( coordinatesElement.isNull() )
346 if ( readGMLCoordinates( interiorPointList, coordinatesElement ) != 0 )
350 ringCoordinates.push_back( interiorPointList );
356 QDomNodeList exteriorList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"exterior" ) );
357 if ( exteriorList.size() < 1 )
361 QDomElement posElement = exteriorList.at( 0 ).firstChild().firstChild().toElement();
362 if ( posElement.isNull() )
366 if ( readGMLPositions( exteriorPointList, posElement ) != 0 )
370 ringCoordinates.push_back( exteriorPointList );
373 QDomNodeList interiorList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"interior" ) );
374 for (
int i = 0; i < interiorList.size(); ++i )
377 QDomElement posElement = interiorList.at( i ).firstChild().firstChild().toElement();
378 if ( posElement.isNull() )
383 if ( readGMLPositions( interiorPointList, posElement ) )
387 ringCoordinates.push_back( interiorPointList );
392 int nrings = ringCoordinates.size();
397 for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
399 npoints += it->size();
401 int size = 1 + 2 *
sizeof( int ) + nrings *
sizeof(
int ) + 2 * npoints *
sizeof( double );
404 unsigned char *wkb =
new unsigned char[size];
407 char e = htonl( 1 ) != 1;
409 int nPointsInRing = 0;
413 memcpy( &( wkb )[wkbPosition], &e, 1 );
415 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
416 wkbPosition +=
sizeof( int );
417 memcpy( &( wkb )[wkbPosition], &nrings,
sizeof(
int ) );
418 wkbPosition +=
sizeof( int );
419 for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
421 nPointsInRing = it->size();
422 memcpy( &( wkb )[wkbPosition], &nPointsInRing,
sizeof(
int ) );
423 wkbPosition +=
sizeof( int );
425 QgsPolylineXY::const_iterator iter;
426 for ( iter = it->begin(); iter != it->end(); ++iter )
431 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
432 wkbPosition +=
sizeof( double );
433 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
434 wkbPosition +=
sizeof( double );
443 QgsGeometry QgsOgcUtils::geometryFromGMLMultiPoint(
const QDomElement &geometryElement )
447 QDomNodeList pointMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pointMember" ) );
448 if ( pointMemberList.size() < 1 )
452 QDomNodeList pointNodeList;
454 QDomNodeList coordinatesList;
455 QDomNodeList posList;
456 for (
int i = 0; i < pointMemberList.size(); ++i )
459 pointNodeList = pointMemberList.at( i ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"Point" ) );
460 if ( pointNodeList.size() < 1 )
465 coordinatesList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
466 if ( !coordinatesList.isEmpty() )
468 currentPoint.clear();
469 if ( readGMLCoordinates( currentPoint, coordinatesList.at( 0 ).toElement() ) != 0 )
473 if ( currentPoint.empty() )
477 pointList.push_back( ( *currentPoint.begin() ) );
483 posList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pos" ) );
484 if ( posList.size() < 1 )
488 currentPoint.clear();
489 if ( readGMLPositions( currentPoint, posList.at( 0 ).toElement() ) != 0 )
493 if ( currentPoint.empty() )
497 pointList.push_back( ( *currentPoint.begin() ) );
501 int nPoints = pointList.size();
506 int size = 1 + 2 *
sizeof( int ) + pointList.size() * ( 2 *
sizeof( double ) + 1 +
sizeof(
int ) );
509 unsigned char *wkb =
new unsigned char[size];
512 char e = htonl( 1 ) != 1;
515 memcpy( &( wkb )[wkbPosition], &e, 1 );
517 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
518 wkbPosition +=
sizeof( int );
519 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
520 wkbPosition +=
sizeof( int );
522 for ( QgsPolylineXY::const_iterator it = pointList.constBegin(); it != pointList.constEnd(); ++it )
524 memcpy( &( wkb )[wkbPosition], &e, 1 );
526 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
527 wkbPosition +=
sizeof( int );
529 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
530 wkbPosition +=
sizeof( double );
532 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
533 wkbPosition +=
sizeof( double );
541 QgsGeometry QgsOgcUtils::geometryFromGMLMultiLineString(
const QDomElement &geometryElement )
552 QList< QgsPolylineXY > lineCoordinates;
553 QDomElement currentLineStringElement;
554 QDomNodeList currentCoordList;
555 QDomNodeList currentPosList;
557 QDomNodeList lineStringMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"lineStringMember" ) );
558 if ( !lineStringMemberList.isEmpty() )
560 for (
int i = 0; i < lineStringMemberList.size(); ++i )
562 QDomNodeList lineStringNodeList = lineStringMemberList.at( i ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LineString" ) );
563 if ( lineStringNodeList.size() < 1 )
567 currentLineStringElement = lineStringNodeList.at( 0 ).toElement();
568 currentCoordList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
569 if ( !currentCoordList.isEmpty() )
572 if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
576 lineCoordinates.push_back( currentPointList );
580 currentPosList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
581 if ( currentPosList.size() < 1 )
586 if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
590 lineCoordinates.push_back( currentPointList );
596 QDomNodeList lineStringList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LineString" ) );
597 if ( !lineStringList.isEmpty() )
599 for (
int i = 0; i < lineStringList.size(); ++i )
601 currentLineStringElement = lineStringList.at( i ).toElement();
602 currentCoordList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
603 if ( !currentCoordList.isEmpty() )
606 if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
610 lineCoordinates.push_back( currentPointList );
615 currentPosList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
616 if ( currentPosList.size() < 1 )
621 if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
625 lineCoordinates.push_back( currentPointList );
635 int nLines = lineCoordinates.size();
640 int size = ( lineCoordinates.size() + 1 ) * ( 1 + 2 *
sizeof(
int ) );
641 for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
643 size += it->size() * 2 *
sizeof( double );
647 unsigned char *wkb =
new unsigned char[size];
650 char e = htonl( 1 ) != 1;
654 memcpy( &( wkb )[wkbPosition], &e, 1 );
656 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
657 wkbPosition +=
sizeof( int );
658 memcpy( &( wkb )[wkbPosition], &nLines,
sizeof(
int ) );
659 wkbPosition +=
sizeof( int );
661 for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
663 memcpy( &( wkb )[wkbPosition], &e, 1 );
665 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
666 wkbPosition +=
sizeof( int );
667 nPoints = it->size();
668 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
669 wkbPosition +=
sizeof( int );
670 for ( QgsPolylineXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
675 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
676 wkbPosition +=
sizeof( double );
677 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
678 wkbPosition +=
sizeof( double );
687 QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon(
const QDomElement &geometryElement )
691 QDomElement currentPolygonMemberElement;
692 QDomNodeList polygonList;
693 QDomElement currentPolygonElement;
695 QDomNodeList outerBoundaryList;
696 QDomElement currentOuterBoundaryElement;
697 QDomNodeList innerBoundaryList;
698 QDomElement currentInnerBoundaryElement;
700 QDomNodeList exteriorList;
701 QDomElement currentExteriorElement;
702 QDomElement currentInteriorElement;
703 QDomNodeList interiorList;
705 QDomNodeList linearRingNodeList;
706 QDomElement currentLinearRingElement;
708 QDomNodeList currentCoordinateList;
709 QDomNodeList currentPosList;
711 QDomNodeList polygonMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"polygonMember" ) );
713 for (
int i = 0; i < polygonMemberList.size(); ++i )
715 currentPolygonList.resize( 0 );
716 currentPolygonMemberElement = polygonMemberList.at( i ).toElement();
717 polygonList = currentPolygonMemberElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"Polygon" ) );
718 if ( polygonList.size() < 1 )
722 currentPolygonElement = polygonList.at( 0 ).toElement();
725 outerBoundaryList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"outerBoundaryIs" ) );
726 if ( !outerBoundaryList.isEmpty() )
728 currentOuterBoundaryElement = outerBoundaryList.at( 0 ).toElement();
731 linearRingNodeList = currentOuterBoundaryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
732 if ( linearRingNodeList.size() < 1 )
736 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
737 currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
738 if ( currentCoordinateList.size() < 1 )
742 if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
746 currentPolygonList.push_back( ringCoordinates );
749 QDomNodeList innerBoundaryList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"innerBoundaryIs" ) );
750 for (
int j = 0; j < innerBoundaryList.size(); ++j )
753 currentInnerBoundaryElement = innerBoundaryList.at( j ).toElement();
754 linearRingNodeList = currentInnerBoundaryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
755 if ( linearRingNodeList.size() < 1 )
759 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
760 currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
761 if ( currentCoordinateList.size() < 1 )
765 if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
769 currentPolygonList.push_back( ringCoordinates );
775 exteriorList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"exterior" ) );
776 if ( exteriorList.size() < 1 )
781 currentExteriorElement = exteriorList.at( 0 ).toElement();
784 linearRingNodeList = currentExteriorElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
785 if ( linearRingNodeList.size() < 1 )
789 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
790 currentPosList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
791 if ( currentPosList.size() < 1 )
795 if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
799 currentPolygonList.push_back( ringPositions );
802 QDomNodeList interiorList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"interior" ) );
803 for (
int j = 0; j < interiorList.size(); ++j )
806 currentInteriorElement = interiorList.at( j ).toElement();
807 linearRingNodeList = currentInteriorElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
808 if ( linearRingNodeList.size() < 1 )
812 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
813 currentPosList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
814 if ( currentPosList.size() < 1 )
818 if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
822 currentPolygonList.push_back( ringPositions );
825 multiPolygonPoints.push_back( currentPolygonList );
828 int nPolygons = multiPolygonPoints.size();
832 int size = 1 + 2 *
sizeof( int );
834 for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
836 size += 1 + 2 *
sizeof( int );
837 for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
839 size +=
sizeof( int ) + 2 * iter->size() *
sizeof( double );
844 unsigned char *wkb =
new unsigned char[size];
846 char e = htonl( 1 ) != 1;
853 memcpy( &( wkb )[wkbPosition], &e, 1 );
855 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
856 wkbPosition +=
sizeof( int );
857 memcpy( &( wkb )[wkbPosition], &nPolygons,
sizeof(
int ) );
858 wkbPosition +=
sizeof( int );
862 for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
864 memcpy( &( wkb )[wkbPosition], &e, 1 );
866 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
867 wkbPosition +=
sizeof( int );
869 memcpy( &( wkb )[wkbPosition], &nRings,
sizeof(
int ) );
870 wkbPosition +=
sizeof( int );
871 for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
873 nPointsInRing = iter->size();
874 memcpy( &( wkb )[wkbPosition], &nPointsInRing,
sizeof(
int ) );
875 wkbPosition +=
sizeof( int );
876 for ( QgsPolylineXY::const_iterator iterator = iter->begin(); iterator != iter->end(); ++iterator )
880 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
881 wkbPosition +=
sizeof( double );
882 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
883 wkbPosition +=
sizeof( double );
893 bool QgsOgcUtils::readGMLCoordinates(
QgsPolylineXY &coords,
const QDomElement &elem )
895 QString coordSeparator = QStringLiteral(
"," );
896 QString tupelSeparator = QStringLiteral(
" " );
901 if ( elem.hasAttribute( QStringLiteral(
"cs" ) ) )
903 coordSeparator = elem.attribute( QStringLiteral(
"cs" ) );
905 if ( elem.hasAttribute( QStringLiteral(
"ts" ) ) )
907 tupelSeparator = elem.attribute( QStringLiteral(
"ts" ) );
910 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
911 QStringList tupels = elem.text().split( tupelSeparator, QString::SkipEmptyParts );
913 QStringList tupels = elem.text().split( tupelSeparator, Qt::SkipEmptyParts );
915 QStringList tuple_coords;
917 bool conversionSuccess;
919 QStringList::const_iterator it;
920 for ( it = tupels.constBegin(); it != tupels.constEnd(); ++it )
922 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
923 tuple_coords = ( *it ).split( coordSeparator, QString::SkipEmptyParts );
925 tuple_coords = ( *it ).split( coordSeparator, Qt::SkipEmptyParts );
927 if ( tuple_coords.size() < 2 )
931 x = tuple_coords.at( 0 ).toDouble( &conversionSuccess );
932 if ( !conversionSuccess )
936 y = tuple_coords.at( 1 ).toDouble( &conversionSuccess );
937 if ( !conversionSuccess )
950 QDomElement boxElem = boxNode.toElement();
951 if ( boxElem.tagName() != QLatin1String(
"Box" ) )
954 QDomElement bElem = boxElem.firstChild().toElement();
955 QString coordSeparator = QStringLiteral(
"," );
956 QString tupelSeparator = QStringLiteral(
" " );
957 if ( bElem.hasAttribute( QStringLiteral(
"cs" ) ) )
959 coordSeparator = bElem.attribute( QStringLiteral(
"cs" ) );
961 if ( bElem.hasAttribute( QStringLiteral(
"ts" ) ) )
963 tupelSeparator = bElem.attribute( QStringLiteral(
"ts" ) );
966 QString bString = bElem.text();
967 bool ok1, ok2, ok3, ok4;
968 double xmin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 0, 0 ).toDouble( &ok1 );
969 double ymin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 1, 1 ).toDouble( &ok2 );
970 double xmax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 0, 0 ).toDouble( &ok3 );
971 double ymax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 1, 1 ).toDouble( &ok4 );
973 if ( ok1 && ok2 && ok3 && ok4 )
982 bool QgsOgcUtils::readGMLPositions(
QgsPolylineXY &coords,
const QDomElement &elem )
986 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
987 QStringList pos = elem.text().split(
' ', QString::SkipEmptyParts );
989 QStringList pos = elem.text().split(
' ', Qt::SkipEmptyParts );
992 bool conversionSuccess;
993 int posSize = pos.size();
995 int srsDimension = 2;
996 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
998 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
999 if ( !conversionSuccess )
1004 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1006 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1007 if ( !conversionSuccess )
1013 for (
int i = 0; i < posSize / srsDimension; i++ )
1015 x = pos.at( i * srsDimension ).toDouble( &conversionSuccess );
1016 if ( !conversionSuccess )
1020 y = pos.at( i * srsDimension + 1 ).toDouble( &conversionSuccess );
1021 if ( !conversionSuccess )
1035 QDomElement envelopeElem = envelopeNode.toElement();
1036 if ( envelopeElem.tagName() != QLatin1String(
"Envelope" ) )
1039 QDomNodeList lowerCornerList = envelopeElem.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"lowerCorner" ) );
1040 if ( lowerCornerList.size() < 1 )
1043 QDomNodeList upperCornerList = envelopeElem.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"upperCorner" ) );
1044 if ( upperCornerList.size() < 1 )
1047 bool conversionSuccess;
1048 int srsDimension = 2;
1050 QDomElement elem = lowerCornerList.at( 0 ).toElement();
1051 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
1053 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
1054 if ( !conversionSuccess )
1059 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1061 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1062 if ( !conversionSuccess )
1067 QString bString = elem.text();
1069 double xmin = bString.section(
' ', 0, 0 ).toDouble( &conversionSuccess );
1070 if ( !conversionSuccess )
1072 double ymin = bString.section(
' ', 1, 1 ).toDouble( &conversionSuccess );
1073 if ( !conversionSuccess )
1076 elem = upperCornerList.at( 0 ).toElement();
1077 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
1079 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
1080 if ( !conversionSuccess )
1085 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1087 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1088 if ( !conversionSuccess )
1094 Q_UNUSED( srsDimension )
1096 bString = elem.text();
1097 double xmax = bString.section(
' ', 0, 0 ).toDouble( &conversionSuccess );
1098 if ( !conversionSuccess )
1100 double ymax = bString.section(
' ', 1, 1 ).toDouble( &conversionSuccess );
1101 if ( !conversionSuccess )
1116 const QString &srsName,
1117 bool invertAxisOrientation,
1122 return QDomElement();
1125 QDomElement boxElem = doc.createElement( QStringLiteral(
"gml:Box" ) );
1126 if ( !srsName.isEmpty() )
1128 boxElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1130 QDomElement coordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1131 coordElem.setAttribute( QStringLiteral(
"cs" ), QStringLiteral(
"," ) );
1132 coordElem.setAttribute( QStringLiteral(
"ts" ), QStringLiteral(
" " ) );
1134 QString coordString;
1143 QDomText coordText = doc.createTextNode( coordString );
1144 coordElem.appendChild( coordText );
1145 boxElem.appendChild( coordElem );
1156 const QString &srsName,
1157 bool invertAxisOrientation,
1162 return QDomElement();
1165 QDomElement envElem = doc.createElement( QStringLiteral(
"gml:Envelope" ) );
1166 if ( !srsName.isEmpty() )
1168 envElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1172 QDomElement lowerCornerElem = doc.createElement( QStringLiteral(
"gml:lowerCorner" ) );
1176 QDomText lowerCornerText = doc.createTextNode( posList );
1177 lowerCornerElem.appendChild( lowerCornerText );
1178 envElem.appendChild( lowerCornerElem );
1180 QDomElement upperCornerElem = doc.createElement( QStringLiteral(
"gml:upperCorner" ) );
1184 QDomText upperCornerText = doc.createTextNode( posList );
1185 upperCornerElem.appendChild( upperCornerText );
1186 envElem.appendChild( upperCornerElem );
1199 const QString &srsName,
1200 bool invertAxisOrientation,
1201 const QString &gmlIdBase,
1205 return QDomElement();
1208 QString cs = QStringLiteral(
"," );
1210 QString ts = QStringLiteral(
" " );
1212 QDomElement baseCoordElem;
1214 bool hasZValue =
false;
1216 QByteArray wkb( geometry.
asWkb() );
1226 return QDomElement();
1237 baseCoordElem = doc.createElement( QStringLiteral(
"gml:pos" ) );
1240 baseCoordElem = doc.createElement( QStringLiteral(
"gml:posList" ) );
1243 baseCoordElem.setAttribute( QStringLiteral(
"srsDimension" ), QStringLiteral(
"2" ) );
1248 baseCoordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1249 baseCoordElem.setAttribute( QStringLiteral(
"cs" ), cs );
1250 baseCoordElem.setAttribute( QStringLiteral(
"ts" ), ts );
1260 QDomElement pointElem = doc.createElement( QStringLiteral(
"gml:Point" ) );
1261 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1262 pointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1263 if ( !srsName.isEmpty() )
1264 pointElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1265 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1269 if ( invertAxisOrientation )
1275 coordElem.appendChild( coordText );
1276 pointElem.appendChild( coordElem );
1285 QDomElement multiPointElem = doc.createElement( QStringLiteral(
"gml:MultiPoint" ) );
1286 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1287 multiPointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1288 if ( !srsName.isEmpty() )
1289 multiPointElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1294 for (
int idx = 0; idx < nPoints; ++idx )
1296 QDomElement pointMemberElem = doc.createElement( QStringLiteral(
"gml:pointMember" ) );
1297 QDomElement pointElem = doc.createElement( QStringLiteral(
"gml:Point" ) );
1298 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1299 pointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( idx + 1 ) );
1300 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1306 if ( invertAxisOrientation )
1312 coordElem.appendChild( coordText );
1313 pointElem.appendChild( coordElem );
1317 wkbPtr +=
sizeof( double );
1319 pointMemberElem.appendChild( pointElem );
1320 multiPointElem.appendChild( pointMemberElem );
1322 return multiPointElem;
1330 QDomElement lineStringElem = doc.createElement( QStringLiteral(
"gml:LineString" ) );
1331 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1332 lineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1333 if ( !srsName.isEmpty() )
1334 lineStringElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1340 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1341 QString coordString;
1342 for (
int idx = 0; idx < nPoints; ++idx )
1351 if ( invertAxisOrientation )
1359 wkbPtr +=
sizeof( double );
1362 QDomText coordText = doc.createTextNode( coordString );
1363 coordElem.appendChild( coordText );
1364 lineStringElem.appendChild( coordElem );
1365 return lineStringElem;
1373 QDomElement multiLineStringElem = doc.createElement( QStringLiteral(
"gml:MultiLineString" ) );
1374 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1375 multiLineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1376 if ( !srsName.isEmpty() )
1377 multiLineStringElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1382 for (
int jdx = 0; jdx < nLines; jdx++ )
1384 QDomElement lineStringMemberElem = doc.createElement( QStringLiteral(
"gml:lineStringMember" ) );
1385 QDomElement lineStringElem = doc.createElement( QStringLiteral(
"gml:LineString" ) );
1386 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1387 lineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( jdx + 1 ) );
1394 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1395 QString coordString;
1396 for (
int idx = 0; idx < nPoints; idx++ )
1405 if ( invertAxisOrientation )
1414 wkbPtr +=
sizeof( double );
1417 QDomText coordText = doc.createTextNode( coordString );
1418 coordElem.appendChild( coordText );
1419 lineStringElem.appendChild( coordElem );
1420 lineStringMemberElem.appendChild( lineStringElem );
1421 multiLineStringElem.appendChild( lineStringMemberElem );
1423 return multiLineStringElem;
1431 QDomElement polygonElem = doc.createElement( QStringLiteral(
"gml:Polygon" ) );
1432 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1433 polygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1434 if ( !srsName.isEmpty() )
1435 polygonElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1441 if ( numRings == 0 )
1442 return QDomElement();
1444 for (
int idx = 0; idx < numRings; idx++ )
1446 QString boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:outerBoundaryIs" :
"gml:exterior";
1449 boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:innerBoundaryIs" :
"gml:interior";
1451 QDomElement boundaryElem = doc.createElement( boundaryName );
1452 QDomElement ringElem = doc.createElement( QStringLiteral(
"gml:LinearRing" ) );
1457 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1458 QString coordString;
1459 for (
int jdx = 0; jdx < nPoints; jdx++ )
1468 if ( invertAxisOrientation )
1476 wkbPtr +=
sizeof( double );
1479 QDomText coordText = doc.createTextNode( coordString );
1480 coordElem.appendChild( coordText );
1481 ringElem.appendChild( coordElem );
1482 boundaryElem.appendChild( ringElem );
1483 polygonElem.appendChild( boundaryElem );
1493 QDomElement multiPolygonElem = doc.createElement( QStringLiteral(
"gml:MultiPolygon" ) );
1494 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1495 multiPolygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1496 if ( !srsName.isEmpty() )
1497 multiPolygonElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1500 wkbPtr >> numPolygons;
1502 for (
int kdx = 0; kdx < numPolygons; kdx++ )
1504 QDomElement polygonMemberElem = doc.createElement( QStringLiteral(
"gml:polygonMember" ) );
1505 QDomElement polygonElem = doc.createElement( QStringLiteral(
"gml:Polygon" ) );
1506 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1507 polygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( kdx + 1 ) );
1514 for (
int idx = 0; idx < numRings; idx++ )
1516 QString boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:outerBoundaryIs" :
"gml:exterior";
1519 boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:innerBoundaryIs" :
"gml:interior";
1521 QDomElement boundaryElem = doc.createElement( boundaryName );
1522 QDomElement ringElem = doc.createElement( QStringLiteral(
"gml:LinearRing" ) );
1527 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1528 QString coordString;
1529 for (
int jdx = 0; jdx < nPoints; jdx++ )
1538 if ( invertAxisOrientation )
1547 wkbPtr +=
sizeof( double );
1550 QDomText coordText = doc.createTextNode( coordString );
1551 coordElem.appendChild( coordText );
1552 ringElem.appendChild( coordElem );
1553 boundaryElem.appendChild( ringElem );
1554 polygonElem.appendChild( boundaryElem );
1555 polygonMemberElem.appendChild( polygonElem );
1556 multiPolygonElem.appendChild( polygonMemberElem );
1559 return multiPolygonElem;
1562 return QDomElement();
1568 return QDomElement();
1577 QDomElement QgsOgcUtils::createGMLCoordinates(
const QgsPolylineXY &points, QDomDocument &doc )
1579 QDomElement coordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1580 coordElem.setAttribute( QStringLiteral(
"cs" ), QStringLiteral(
"," ) );
1581 coordElem.setAttribute( QStringLiteral(
"ts" ), QStringLiteral(
" " ) );
1583 QString coordString;
1584 QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
1585 for ( ; pointIt != points.constEnd(); ++pointIt )
1587 if ( pointIt != points.constBegin() )
1596 QDomText coordText = doc.createTextNode( coordString );
1597 coordElem.appendChild( coordText );
1601 QDomElement QgsOgcUtils::createGMLPositions(
const QgsPolylineXY &points, QDomDocument &doc )
1603 QDomElement posElem = doc.createElement( QStringLiteral(
"gml:pos" ) );
1604 if ( points.size() > 1 )
1605 posElem = doc.createElement( QStringLiteral(
"gml:posList" ) );
1606 posElem.setAttribute( QStringLiteral(
"srsDimension" ), QStringLiteral(
"2" ) );
1608 QString coordString;
1609 QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
1610 for ( ; pointIt != points.constEnd(); ++pointIt )
1612 if ( pointIt != points.constBegin() )
1621 QDomText coordText = doc.createTextNode( coordString );
1622 posElem.appendChild( coordText );
1632 if ( fillElement.isNull() || !fillElement.hasChildNodes() )
1640 QDomElement cssElem = fillElement.firstChildElement( QStringLiteral(
"CssParameter" ) );
1641 while ( !cssElem.isNull() )
1643 cssName = cssElem.attribute( QStringLiteral(
"name" ), QStringLiteral(
"not_found" ) );
1644 if ( cssName != QLatin1String(
"not_found" ) )
1646 elemText = cssElem.text();
1647 if ( cssName == QLatin1String(
"fill" ) )
1649 color.setNamedColor( elemText );
1651 else if ( cssName == QLatin1String(
"fill-opacity" ) )
1654 double opacity = elemText.toDouble( &ok );
1657 color.setAlphaF( opacity );
1662 cssElem = cssElem.nextSiblingElement( QStringLiteral(
"CssParameter" ) );
1676 if ( element.isNull() || !element.hasChildNodes() )
1683 if ( element.firstChild().nodeType() == QDomNode::TextNode )
1693 QDomElement childElem = element.firstChildElement();
1694 while ( !childElem.isNull() )
1706 if ( !expr->d->mRootNode )
1708 expr->d->mRootNode = node;
1715 childElem = childElem.nextSiblingElement();
1719 expr->d->mExp = expr->
dump();
1745 static
int binaryOperatorFromTagName( const QString &tagName )
1748 return BINARY_OPERATORS_TAG_NAMES_MAP()->value( tagName, -1 );
1755 return QStringLiteral(
"PropertyIsLike" );
1757 return BINARY_OPERATORS_TAG_NAMES_MAP()->key( op, QString() );
1760 static bool isBinaryOperator(
const QString &tagName )
1762 return binaryOperatorFromTagName( tagName ) >= 0;
1766 static bool isSpatialOperator(
const QString &tagName )
1768 static QStringList spatialOps;
1769 if ( spatialOps.isEmpty() )
1771 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
1772 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
1775 return spatialOps.contains( tagName );
1782 errorMessage = utils.errorMessage();
1790 errorMessage = utils.errorMessage();
1798 errorMessage = utils.errorMessage();
1806 errorMessage = utils.errorMessage();
1814 errorMessage = utils.errorMessage();
1822 errorMessage = utils.errorMessage();
1830 errorMessage = utils.errorMessage();
1834 QgsExpressionNode *QgsOgcUtils::nodeIsBetweenFromOgcFilter( QDomElement &element, QString &errorMessage )
1838 errorMessage = utils.errorMessage();
1846 errorMessage = utils.errorMessage();
1857 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage );
1863 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage );
1871 const QString &srsName,
1872 bool honourAxisOrientation,
1873 bool invertAxisOrientation,
1874 QString *errorMessage )
1877 return QDomElement();
1887 if ( exprRootElem.isNull() )
1888 return QDomElement();
1890 QDomElement filterElem =
1892 doc.createElementNS(
FES_NAMESPACE, QStringLiteral(
"fes:Filter" ) ) :
1893 doc.createElementNS(
OGC_NAMESPACE, QStringLiteral(
"ogc:Filter" ) );
1896 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:gml" ) );
1901 filterElem.setAttributeNode( attr );
1903 filterElem.appendChild( exprRootElem );
1912 const QString &srsName,
1913 bool honourAxisOrientation,
1914 bool invertAxisOrientation,
1915 QString *errorMessage )
1924 return QDomElement();
1938 if ( !exprRootElem.isNull() )
1940 return exprRootElem;
1947 *errorMessage = QObject::tr(
"Node type not supported in expression translation: %1" ).arg( node->
nodeType() );
1951 return QDomElement();
1958 const QList<LayerProperties> &layerProperties,
1959 bool honourAxisOrientation,
1960 bool invertAxisOrientation,
1961 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename,
1962 QString *errorMessage )
1965 return QDomElement();
1968 layerProperties, honourAxisOrientation, invertAxisOrientation,
1969 mapUnprefixedTypenameToPrefixedTypename );
1973 if ( exprRootElem.isNull() )
1974 return QDomElement();
1976 QDomElement filterElem =
1978 doc.createElementNS(
FES_NAMESPACE, QStringLiteral(
"fes:Filter" ) ) :
1979 doc.createElementNS(
OGC_NAMESPACE, QStringLiteral(
"ogc:Filter" ) );
1982 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:gml" ) );
1987 filterElem.setAttributeNode( attr );
1989 filterElem.appendChild( exprRootElem );
2014 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
2015 return QDomElement();
2022 if ( !mErrorMessage.isEmpty() )
2023 return QDomElement();
2026 switch ( node->
op() )
2029 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2034 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
2035 mDoc.removeChild( operandElem );
2039 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
2040 return QDomElement();
2044 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
2045 uoElem.appendChild( operandElem );
2049 mErrorMessage = QObject::tr(
"Unary operator '%1' not implemented yet" ).arg( node->
text() );
2050 return QDomElement();
2060 if ( !mErrorMessage.isEmpty() )
2061 return QDomElement();
2071 if ( rightLit->
value().isNull() )
2074 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2075 elem.appendChild( leftElem );
2079 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2080 notElem.appendChild( elem );
2094 if ( !mErrorMessage.isEmpty() )
2095 return QDomElement();
2098 QString opText = binaryOperatorToTagName( op );
2099 if ( opText.isEmpty() )
2103 mErrorMessage = QObject::tr(
"Binary operator %1 not implemented yet" ).arg( node->
text() );
2104 return QDomElement();
2107 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2112 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2115 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2116 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2118 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2120 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2123 boElem.appendChild( leftElem );
2124 boElem.appendChild( rightElem );
2131 Q_UNUSED( expression )
2134 switch ( node->
value().type() )
2137 value = QString::number( node->
value().toInt() );
2139 case QVariant::Double:
2142 case QVariant::String:
2143 value = node->
value().toString();
2145 case QVariant::Date:
2146 value = node->
value().toDate().toString( Qt::ISODate );
2148 case QVariant::DateTime:
2149 value = node->
value().toDateTime().toString( Qt::ISODate );
2153 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2154 return QDomElement();
2157 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2158 litElem.appendChild( mDoc.createTextNode( value ) );
2165 Q_UNUSED( expression )
2167 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2168 propElem.appendChild( mDoc.createTextNode( node->
name() ) );
2176 if ( node->
list()->
list().size() == 1 )
2179 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2182 const auto constList = node->
list()->
list();
2186 if ( !mErrorMessage.isEmpty() )
2187 return QDomElement();
2189 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2190 eqElem.appendChild( leftNode.cloneNode() );
2191 eqElem.appendChild( listNode );
2193 orElem.appendChild( eqElem );
2198 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2199 notElem.appendChild( orElem );
2208 { QLatin1String(
"disjoint" ), QLatin1String(
"Disjoint" ) },
2209 { QLatin1String(
"intersects" ), QLatin1String(
"Intersects" )},
2210 { QLatin1String(
"touches" ), QLatin1String(
"Touches" ) },
2211 { QLatin1String(
"crosses" ), QLatin1String(
"Crosses" ) },
2212 { QLatin1String(
"contains" ), QLatin1String(
"Contains" ) },
2213 { QLatin1String(
"overlaps" ), QLatin1String(
"Overlaps" ) },
2214 { QLatin1String(
"within" ), QLatin1String(
"Within" ) }
2217 static
bool isBinarySpatialOperator( const QString &fnName )
2219 return BINARY_SPATIAL_OPS_MAP()->contains( fnName );
2222 static QString tagNameForSpatialOperator(
const QString &fnName )
2224 return BINARY_SPATIAL_OPS_MAP()->value( fnName );
2234 return fd->
name() == QLatin1String(
"$geometry" );
2246 if ( fnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2248 const QList<QgsExpressionNode *> &args = fnNode->
args()->
list();
2264 if ( fd->
name() == QLatin1String(
"intersects_bbox" ) )
2266 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2267 Q_ASSERT( argNodes.count() == 2 );
2269 QgsGeometry geom = geometryFromConstExpr( argNodes[1] );
2270 if ( !geom.
isNull() && isGeometryColumn( argNodes[0] ) )
2280 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2281 geomProperty.appendChild( mDoc.createTextNode( mGeometryName ) );
2283 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":BBOX" );
2284 funcElem.appendChild( geomProperty );
2285 funcElem.appendChild( elemBox );
2290 mErrorMessage = QObject::tr(
"<BBOX> is currently supported only in form: bbox($geometry, geomFromWKT('…'))" );
2291 return QDomElement();
2295 if ( isBinarySpatialOperator( fd->
name() ) )
2297 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2298 Q_ASSERT( argNodes.count() == 2 );
2301 if ( isGeometryColumn( argNodes[0] ) )
2302 otherNode = argNodes[1];
2303 else if ( isGeometryColumn( argNodes[1] ) )
2304 otherNode = argNodes[0];
2307 mErrorMessage = QObject::tr(
"Unable to translate spatial operator: at least one must refer to geometry." );
2308 return QDomElement();
2311 QDomElement otherGeomElem;
2316 mErrorMessage = QObject::tr(
"spatial operator: the other operator must be a geometry constructor function" );
2317 return QDomElement();
2322 if ( otherFnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2327 mErrorMessage = QObject::tr(
"geom_from_wkt: argument must be string literal" );
2328 return QDomElement();
2333 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2336 else if ( otherFnDef->
name() == QLatin1String(
"geom_from_gml" ) )
2341 mErrorMessage = QObject::tr(
"geom_from_gml: argument must be string literal" );
2342 return QDomElement();
2345 QDomDocument geomDoc;
2347 if ( !geomDoc.setContent( gml,
true ) )
2349 mErrorMessage = QObject::tr(
"geom_from_gml: unable to parse XML" );
2350 return QDomElement();
2353 QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(),
true );
2354 otherGeomElem = geomNode.toElement();
2358 mErrorMessage = QObject::tr(
"spatial operator: unknown geometry constructor function" );
2359 return QDomElement();
2364 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + tagNameForSpatialOperator( fd->
name() ) );
2365 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2366 geomProperty.appendChild( mDoc.createTextNode( mGeometryName ) );
2367 funcElem.appendChild( geomProperty );
2368 funcElem.appendChild( otherGeomElem );
2372 if ( fd->
isStatic( node, expression, context ) )
2374 QVariant result = fd->
run( node->
args(), context, expression, node );
2376 return expressionLiteralToOgcFilter( &literal, expression, context );
2381 mErrorMessage = QObject::tr(
"Special columns/constants are not supported." );
2382 return QDomElement();
2386 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
2387 funcElem.setAttribute( QStringLiteral(
"name" ), fd->
name() );
2388 const auto constList = node->
args()->
list();
2392 if ( !mErrorMessage.isEmpty() )
2393 return QDomElement();
2395 funcElem.appendChild( childElem );
2406 const QList<QgsOgcUtils::LayerProperties> &layerProperties,
2407 bool honourAxisOrientation,
2408 bool invertAxisOrientation,
2409 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename )
2412 , mGMLVersion( gmlVersion )
2413 , mFilterVersion( filterVersion )
2414 , mLayerProperties( layerProperties )
2415 , mHonourAxisOrientation( honourAxisOrientation )
2416 , mInvertAxisOrientation( invertAxisOrientation )
2417 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
2418 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
2420 , mMapUnprefixedTypenameToPrefixedTypename( mapUnprefixedTypenameToPrefixedTypename )
2446 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
2447 return QDomElement();
2456 if ( !mErrorMessage.isEmpty() )
2457 return QDomElement();
2460 switch ( node->
op() )
2463 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2468 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
2469 mDoc.removeChild( operandElem );
2473 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
2474 return QDomElement();
2478 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
2479 uoElem.appendChild( operandElem );
2484 return QDomElement();
2494 if ( !mErrorMessage.isEmpty() )
2495 return QDomElement();
2505 if ( rightLit->
value().isNull() )
2508 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2509 elem.appendChild( leftElem );
2513 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2514 notElem.appendChild( elem );
2528 if ( !mErrorMessage.isEmpty() )
2529 return QDomElement();
2534 opText = QStringLiteral(
"Or" );
2536 opText = QStringLiteral(
"And" );
2538 opText = QStringLiteral(
"PropertyIsEqualTo" );
2540 opText = QStringLiteral(
"PropertyIsNotEqualTo" );
2542 opText = QStringLiteral(
"PropertyIsLessThanOrEqualTo" );
2544 opText = QStringLiteral(
"PropertyIsGreaterThanOrEqualTo" );
2546 opText = QStringLiteral(
"PropertyIsLessThan" );
2548 opText = QStringLiteral(
"PropertyIsGreaterThan" );
2550 opText = QStringLiteral(
"PropertyIsLike" );
2552 opText = QStringLiteral(
"PropertyIsLike" );
2554 if ( opText.isEmpty() )
2558 return QDomElement();
2561 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2566 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2569 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2570 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2572 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2574 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2577 boElem.appendChild( leftElem );
2578 boElem.appendChild( rightElem );
2586 switch ( node->
value().type() )
2589 value = QString::number( node->
value().toInt() );
2591 case QVariant::LongLong:
2592 value = QString::number( node->
value().toLongLong() );
2594 case QVariant::Double:
2597 case QVariant::String:
2598 value = node->
value().toString();
2602 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2603 return QDomElement();
2606 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2607 litElem.appendChild( mDoc.createTextNode( value ) );
2614 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2615 if ( node->
tableName().isEmpty() || mLayerProperties.size() == 1 )
2616 propElem.appendChild( mDoc.createTextNode( node->
name() ) );
2619 QString tableName( mMapTableAliasToNames[node->
tableName()] );
2620 if ( mMapUnprefixedTypenameToPrefixedTypename.contains( tableName ) )
2621 tableName = mMapUnprefixedTypenameToPrefixedTypename[tableName];
2622 propElem.appendChild( mDoc.createTextNode( tableName +
"/" + node->
name() ) );
2629 if ( node->
list()->
list().size() == 1 )
2632 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2635 const auto constList = node->
list()->
list();
2639 if ( !mErrorMessage.isEmpty() )
2640 return QDomElement();
2642 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2643 eqElem.appendChild( leftNode.cloneNode() );
2644 eqElem.appendChild( listNode );
2646 orElem.appendChild( eqElem );
2651 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2652 notElem.appendChild( orElem );
2661 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsBetween" );
2663 QDomElement lowerBoundary = mDoc.createElement( mFilterPrefix +
":LowerBoundary" );
2665 elem.appendChild( lowerBoundary );
2666 QDomElement upperBoundary = mDoc.createElement( mFilterPrefix +
":UpperBoundary" );
2668 elem.appendChild( upperBoundary );
2672 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2673 notElem.appendChild( elem );
2680 static QString mapBinarySpatialToOgc(
const QString &name )
2682 QString nameCompare( name );
2683 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 2)
2684 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2685 nameCompare = name.mid( 3 );
2687 if ( name.size() > 3 && QStringView {name}.mid( 0, 3 ).toString().compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2688 nameCompare = name.mid( 3 );
2690 QStringList spatialOps;
2691 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
2692 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
2693 const auto constSpatialOps = spatialOps;
2694 for ( QString op : constSpatialOps )
2696 if ( nameCompare.compare( op, Qt::CaseInsensitive ) == 0 )
2702 static QString mapTernarySpatialToOgc(
const QString &name )
2704 QString nameCompare( name );
2705 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 2)
2706 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2707 nameCompare = name.mid( 3 );
2709 if ( name.size() > 3 && QStringView {name}.mid( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2710 nameCompare = name.mid( 3 );
2712 if ( nameCompare.compare( QLatin1String(
"DWithin" ), Qt::CaseInsensitive ) == 0 )
2713 return QStringLiteral(
"DWithin" );
2714 if ( nameCompare.compare( QLatin1String(
"Beyond" ), Qt::CaseInsensitive ) == 0 )
2715 return QStringLiteral(
"Beyond" );
2719 QString QgsOgcUtilsSQLStatementToFilter::getGeometryColumnSRSName(
const QgsSQLStatement::Node *node )
2727 const auto constMLayerProperties = mLayerProperties;
2730 if ( prop.mName.compare( mMapTableAliasToNames[col->
tableName()], Qt::CaseInsensitive ) == 0 &&
2731 prop.mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2733 return prop.mSRSName;
2737 if ( !mLayerProperties.empty() &&
2738 mLayerProperties.at( 0 ).mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2740 return mLayerProperties.at( 0 ).mSRSName;
2746 QList<QgsSQLStatement::Node *> args,
2747 bool lastArgIsSRSName,
2749 bool &axisInversion )
2751 srsName = mCurrentSRSName;
2752 axisInversion = mInvertAxisOrientation;
2754 if ( lastArgIsSRSName )
2759 mErrorMessage = QObject::tr(
"%1: Last argument must be string or integer literal" ).arg( mainNode->
name() );
2763 if ( lit->
value().type() == QVariant::Int )
2767 srsName =
"EPSG:" + QString::number( lit->
value().toInt() );
2771 srsName =
"urn:ogc:def:crs:EPSG::" + QString::number( lit->
value().toInt() );
2776 srsName = lit->
value().toString();
2777 if ( srsName.startsWith( QLatin1String(
"EPSG:" ), Qt::CaseInsensitive ) )
2783 if ( !srsName.isEmpty() )
2789 axisInversion = !axisInversion;
2799 if ( node->
name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 )
2801 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2802 if ( args.size() != 1 && args.size() != 2 )
2804 mErrorMessage = QObject::tr(
"Function %1 should have 1 or 2 arguments" ).arg( node->
name() );
2805 return QDomElement();
2811 mErrorMessage = QObject::tr(
"%1: First argument must be string literal" ).arg( node->
name() );
2812 return QDomElement();
2817 if ( ! processSRSName( node, args, args.size() == 2, srsName, axisInversion ) )
2819 return QDomElement();
2825 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2827 if ( geomElem.isNull() )
2829 mErrorMessage = QObject::tr(
"%1: invalid WKT" ).arg( node->
name() );
2830 return QDomElement();
2837 if ( node->
name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 )
2839 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2840 if ( args.size() != 4 && args.size() != 5 )
2842 mErrorMessage = QObject::tr(
"Function %1 should have 4 or 5 arguments" ).arg( node->
name() );
2843 return QDomElement();
2848 for (
int i = 0; i < 4; i++ )
2853 mErrorMessage = QObject::tr(
"%1: Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2854 return QDomElement();
2858 if ( lit->
value().type() == QVariant::Int )
2859 val = lit->
value().toInt();
2860 else if ( lit->
value().type() == QVariant::LongLong )
2861 val = lit->
value().toLongLong();
2862 else if ( lit->
value().type() == QVariant::Double )
2863 val = lit->
value().toDouble();
2866 mErrorMessage = QObject::tr(
"%1 Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2867 return QDomElement();
2881 if ( ! processSRSName( node, args, args.size() == 5, srsName, axisInversion ) )
2883 return QDomElement();
2890 QgsOgcUtils::rectangleToGMLEnvelope( &rect, mDoc, srsName, axisInversion, 15 );
2894 if ( node->
name().compare( QLatin1String(
"ST_GeomFromGML" ), Qt::CaseInsensitive ) == 0 )
2896 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2897 if ( args.size() != 1 )
2899 mErrorMessage = QObject::tr(
"Function %1 should have 1 argument" ).arg( node->
name() );
2900 return QDomElement();
2906 mErrorMessage = QObject::tr(
"%1: Argument must be string literal" ).arg( node->
name() );
2907 return QDomElement();
2910 QDomDocument geomDoc;
2912 if ( !geomDoc.setContent( gml,
true ) )
2914 mErrorMessage = QObject::tr(
"ST_GeomFromGML: unable to parse XML" );
2915 return QDomElement();
2918 QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(),
true );
2920 return geomNode.toElement();
2924 QString ogcName( mapBinarySpatialToOgc( node->
name() ) );
2925 if ( !ogcName.isEmpty() )
2927 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2928 if ( args.size() != 2 )
2930 mErrorMessage = QObject::tr(
"Function %1 should have 2 arguments" ).arg( node->
name() );
2931 return QDomElement();
2934 for (
int i = 0; i < 2; i ++ )
2937 (
static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
2938 static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
2940 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
2947 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + ogcName );
2948 const auto constArgs = args;
2952 if ( !mErrorMessage.isEmpty() )
2954 mCurrentSRSName.clear();
2955 return QDomElement();
2958 funcElem.appendChild( childElem );
2961 mCurrentSRSName.clear();
2965 ogcName = mapTernarySpatialToOgc( node->
name() );
2966 if ( !ogcName.isEmpty() )
2968 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2969 if ( args.size() != 3 )
2971 mErrorMessage = QObject::tr(
"Function %1 should have 3 arguments" ).arg( node->
name() );
2972 return QDomElement();
2975 for (
int i = 0; i < 2; i ++ )
2978 (
static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
2979 static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
2981 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
2986 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + node->
name().mid( 3 ) );
2987 for (
int i = 0; i < 2; i++ )
2990 if ( !mErrorMessage.isEmpty() )
2992 mCurrentSRSName.clear();
2993 return QDomElement();
2996 funcElem.appendChild( childElem );
2998 mCurrentSRSName.clear();
3003 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() );
3004 return QDomElement();
3007 if ( lit->
value().isNull() )
3009 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() );
3010 return QDomElement();
3013 QString unit( QStringLiteral(
"m" ) );
3014 switch ( lit->
value().type() )
3017 distance = QString::number( lit->
value().toInt() );
3019 case QVariant::LongLong:
3020 distance = QString::number( lit->
value().toLongLong() );
3022 case QVariant::Double:
3025 case QVariant::String:
3027 distance = lit->
value().toString();
3028 for (
int i = 0; i < distance.size(); i++ )
3030 if ( !( ( distance[i] >=
'0' && distance[i] <=
'9' ) || distance[i] ==
'-' || distance[i] ==
'.' || distance[i] ==
'e' || distance[i] ==
'E' ) )
3032 unit = distance.mid( i ).trimmed();
3033 distance = distance.mid( 0, i );
3041 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( lit->
value().type() );
3042 return QDomElement();
3045 QDomElement distanceElem = mDoc.createElement( mFilterPrefix +
":Distance" );
3047 distanceElem.setAttribute( QStringLiteral(
"uom" ), unit );
3049 distanceElem.setAttribute( QStringLiteral(
"unit" ), unit );
3050 distanceElem.appendChild( mDoc.createTextNode( distance ) );
3051 funcElem.appendChild( distanceElem );
3056 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
3057 funcElem.setAttribute( QStringLiteral(
"name" ), node->
name() );
3058 const auto constList = node->
args()->
list();
3062 if ( !mErrorMessage.isEmpty() )
3063 return QDomElement();
3065 funcElem.appendChild( childElem );
3071 const QString &leftTable )
3079 QList<QDomElement> listElem;
3081 for (
const QString &columnName : constUsingColumns )
3083 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
3084 QDomElement propElem1 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3085 propElem1.appendChild( mDoc.createTextNode( leftTable +
"/" + columnName ) );
3086 eqElem.appendChild( propElem1 );
3087 QDomElement propElem2 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3088 propElem2.appendChild( mDoc.createTextNode( node->
tableDef()->
name() +
"/" + columnName ) );
3089 eqElem.appendChild( propElem2 );
3090 listElem.append( eqElem );
3093 if ( listElem.size() == 1 )
3097 else if ( listElem.size() > 1 )
3099 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3100 const auto constListElem = listElem;
3101 for (
const QDomElement &elem : constListElem )
3103 andElem.appendChild( elem );
3108 return QDomElement();
3113 if ( node->
alias().isEmpty() )
3115 mMapTableAliasToNames[ node->
name()] = node->
name();
3119 mMapTableAliasToNames[ node->
alias()] = node->
name();
3125 QList<QDomElement> listElem;
3128 ( node->
tables().size() != 1 || !node->
joins().empty() ) )
3130 mErrorMessage = QObject::tr(
"Joins are only supported with WFS 2.0" );
3131 return QDomElement();
3135 const auto constTables = node->
tables();
3140 const auto constJoins = node->
joins();
3143 visit( join->tableDef() );
3147 QList< QgsSQLStatement::NodeTableDef *> nodeTables = node->
tables();
3148 QString leftTable = nodeTables.at( nodeTables.length() - 1 )->name();
3151 QDomElement joinElem =
toOgcFilter( join, leftTable );
3152 if ( !mErrorMessage.isEmpty() )
3153 return QDomElement();
3154 listElem.append( joinElem );
3155 leftTable = join->tableDef()->name();
3159 if ( node->
where() )
3162 if ( !mErrorMessage.isEmpty() )
3163 return QDomElement();
3164 listElem.append( whereElem );
3168 if ( listElem.size() == 1 )
3172 else if ( listElem.size() > 1 )
3174 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3175 const auto constListElem = listElem;
3176 for (
const QDomElement &elem : constListElem )
3178 andElem.appendChild( elem );
3183 return QDomElement();
3189 mPropertyName = QStringLiteral(
"PropertyName" );
3190 mPrefix = QStringLiteral(
"ogc" );
3194 mPropertyName = QStringLiteral(
"ValueReference" );
3195 mPrefix = QStringLiteral(
"fes" );
3201 if ( element.isNull() )
3205 if ( isBinaryOperator( element.tagName() ) )
3211 if ( isSpatialOperator( element.tagName() ) )
3217 if ( element.tagName() == QLatin1String(
"Not" ) )
3221 else if ( element.tagName() == QLatin1String(
"PropertyIsNull" ) )
3225 else if ( element.tagName() == QLatin1String(
"Literal" ) )
3229 else if ( element.tagName() == QLatin1String(
"Function" ) )
3233 else if ( element.tagName() == mPropertyName )
3237 else if ( element.tagName() == QLatin1String(
"PropertyIsBetween" ) )
3242 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() );
3248 if ( element.isNull() )
3251 int op = binaryOperatorFromTagName( element.tagName() );
3254 mErrorMessage = QObject::tr(
"'%1' binary operator not supported." ).arg( element.tagName() );
3258 if ( op ==
QgsExpressionNodeBinaryOperator::boLike && element.hasAttribute( QStringLiteral(
"matchCase" ) ) && element.attribute( QStringLiteral(
"matchCase" ) ) == QLatin1String(
"false" ) )
3263 QDomElement operandElem = element.firstChildElement();
3268 mErrorMessage = QObject::tr(
"invalid left operand for '%1' binary operator" ).arg( element.tagName() );
3272 std::unique_ptr<QgsExpressionNode> leftOp( expr->clone() );
3273 for ( operandElem = operandElem.nextSiblingElement(); !operandElem.isNull(); operandElem = operandElem.nextSiblingElement() )
3278 mErrorMessage = QObject::tr(
"invalid right operand for '%1' binary operator" ).arg( element.tagName() );
3285 if ( element.hasAttribute( QStringLiteral(
"wildCard" ) ) )
3287 wildCard = element.attribute( QStringLiteral(
"wildCard" ) );
3290 if ( element.hasAttribute( QStringLiteral(
"singleChar" ) ) )
3292 singleChar = element.attribute( QStringLiteral(
"singleChar" ) );
3294 QString escape = QStringLiteral(
"\\" );
3295 if ( element.hasAttribute( QStringLiteral(
"escape" ) ) )
3297 escape = element.attribute( QStringLiteral(
"escape" ) );
3299 if ( element.hasAttribute( QStringLiteral(
"escapeChar" ) ) )
3301 escape = element.attribute( QStringLiteral(
"escapeChar" ) );
3305 if ( !wildCard.isEmpty() && wildCard != QLatin1String(
"%" ) )
3307 oprValue.replace(
'%', QLatin1String(
"\\%" ) );
3308 if ( oprValue.startsWith( wildCard ) )
3310 oprValue.replace( 0, 1, QStringLiteral(
"%" ) );
3312 QRegExp rx(
"[^" + QRegExp::escape( escape ) +
"](" + QRegExp::escape( wildCard ) +
")" );
3314 while ( ( pos = rx.indexIn( oprValue, pos ) ) != -1 )
3316 oprValue.replace( pos + 1, 1, QStringLiteral(
"%" ) );
3319 oprValue.replace( escape + wildCard, wildCard );
3321 if ( !singleChar.isEmpty() && singleChar != QLatin1String(
"_" ) )
3323 oprValue.replace(
'_', QLatin1String(
"\\_" ) );
3324 if ( oprValue.startsWith( singleChar ) )
3326 oprValue.replace( 0, 1, QStringLiteral(
"_" ) );
3328 QRegExp rx(
"[^" + QRegExp::escape( escape ) +
"](" + QRegExp::escape( singleChar ) +
")" );
3330 while ( ( pos = rx.indexIn( oprValue, pos ) ) != -1 )
3332 oprValue.replace( pos + 1, 1, QStringLiteral(
"_" ) );
3335 oprValue.replace( escape + singleChar, singleChar );
3337 if ( !escape.isEmpty() && escape != QLatin1String(
"\\" ) )
3339 oprValue.replace( escape + escape, escape );
3347 if ( expr == leftOp )
3349 mErrorMessage = QObject::tr(
"only one operand for '%1' binary operator" ).arg( element.tagName() );
3363 QDomElement childElem = element.firstChildElement();
3365 while ( !childElem.isNull() && gml2Str.isEmpty() )
3367 if ( childElem.tagName() != mPropertyName )
3369 QTextStream gml2Stream( &gml2Str );
3370 childElem.save( gml2Stream, 0 );
3372 childElem = childElem.nextSiblingElement();
3374 if ( !gml2Str.isEmpty() )
3380 mErrorMessage = QObject::tr(
"No OGC Geometry found" );
3393 if ( element.isNull() || element.tagName() != mPropertyName )
3395 mErrorMessage = QObject::tr(
"%1:PropertyName expected, got %2" ).arg( mPrefix, element.tagName() );
3404 if ( element.isNull() || element.tagName() != QLatin1String(
"Literal" ) )
3406 mErrorMessage = QObject::tr(
"%1:Literal expected, got %2" ).arg( mPrefix, element.tagName() );
3410 std::unique_ptr<QgsExpressionNode> root;
3413 QDomNode childNode = element.firstChild();
3414 while ( !childNode.isNull() )
3416 std::unique_ptr<QgsExpressionNode> operand;
3418 if ( childNode.nodeType() == QDomNode::ElementNode )
3421 const QDomElement operandElem = childNode.toElement();
3425 mErrorMessage = QObject::tr(
"'%1' is an invalid or not supported content for %2:Literal" ).arg( operandElem.tagName(), mPrefix );
3432 QVariant value = childNode.nodeValue();
3434 bool converted =
false;
3439 QDomElement propertyNameElement = element.previousSiblingElement( mPropertyName );
3440 if ( propertyNameElement.isNull() || propertyNameElement.tagName() != mPropertyName )
3442 propertyNameElement = element.nextSiblingElement( mPropertyName );
3444 if ( !propertyNameElement.isNull() || propertyNameElement.tagName() == mPropertyName )
3446 const int fieldIndex = mLayer->
fields().
indexOf( propertyNameElement.firstChild().nodeValue() );
3447 if ( fieldIndex != -1 )
3460 const double d = value.toDouble( &ok );
3473 root = std::move( operand );
3480 childNode = childNode.nextSibling();
3484 return root.release();
3491 if ( element.tagName() != QLatin1String(
"Not" ) )
3494 const QDomElement operandElem = element.firstChildElement();
3498 mErrorMessage = QObject::tr(
"invalid operand for '%1' unary operator" ).arg( element.tagName() );
3508 if ( element.tagName() != QLatin1String(
"PropertyIsNull" ) )
3513 const QDomElement operandElem = element.firstChildElement();
3524 if ( element.isNull() || element.tagName() != QLatin1String(
"Function" ) )
3526 mErrorMessage = QObject::tr(
"%1:Function expected, got %2" ).arg( mPrefix, element.tagName() );
3534 if ( element.attribute( QStringLiteral(
"name" ) ) != funcDef->
name() )
3539 QDomElement operandElem = element.firstChildElement();
3540 while ( !operandElem.isNull() )
3547 args->append( op.release() );
3549 operandElem = operandElem.nextSiblingElement();
3561 std::unique_ptr<QgsExpressionNode> operand;
3562 std::unique_ptr<QgsExpressionNode> lowerBound;
3563 std::unique_ptr<QgsExpressionNode> upperBound;
3565 QDomElement operandElem = element.firstChildElement();
3566 while ( !operandElem.isNull() )
3568 if ( operandElem.tagName() == QLatin1String(
"LowerBoundary" ) )
3570 QDomElement lowerBoundElem = operandElem.firstChildElement();
3573 else if ( operandElem.tagName() == QLatin1String(
"UpperBoundary" ) )
3575 QDomElement upperBoundElem = operandElem.firstChildElement();
3584 if ( operand && lowerBound && upperBound )
3587 operandElem = operandElem.nextSiblingElement();
3590 if ( !operand || !lowerBound || !upperBound )
3592 mErrorMessage = QObject::tr(
"missing some required sub-elements in %1:PropertyIsBetween" ).arg( mPrefix );
3603 return mErrorMessage;
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.
QgsExpressionNodeBinaryOperator::BinaryOperator op() const
Returns the binary operator.
QgsExpressionNode * opRight() const
Returns the node to the right of the operator.
QString text() const
Returns a the name of this operator without the operands.
QgsExpressionNode * opLeft() const
Returns the node to the left of the operator.
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.
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
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.)
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.
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
OperationResult
Success or failure of a geometry operation.
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
OperationResult transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection direction=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
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
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 &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 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 QDomElement expressionToOgcExpression(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates an OGC expression XML element.
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 * maxVal() const
Maximum bound.
bool isNotBetween() const
Whether this is a NOT BETWEEN operator.
QgsSQLStatement::Node * node() const
Variable at the left of BETWEEN.
QgsSQLStatement::Node * minVal() const
Minimum bound.
Binary logical/arithmetical operator (AND, OR, =, +, ...)
QgsSQLStatement::Node * opRight() const
Right operand.
QgsSQLStatement::Node * opLeft() const
Left operand.
QgsSQLStatement::BinaryOperator op() const
Operator.
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::NodeList * list() const
Values list.
QgsSQLStatement::Node * node() const
Variable at the left of IN.
QgsSQLStatement::NodeTableDef * tableDef() const
Table definition.
QList< QString > usingColumns() const
Columns referenced by USING.
QgsSQLStatement::Node * onExpr() const
On expression. Will be nullptr if usingColumns() is not empty.
QList< QgsSQLStatement::Node * > list()
Returns list.
Literal value (integer, integer64, double, string)
QVariant value() const
The value of the literal.
QgsSQLStatement::Node * where() const
Returns the where clause.
QList< QgsSQLStatement::NodeJoin * > joins() const
Returns the list of joins.
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::Node * operand() const
Operand.
QgsSQLStatement::UnaryOperator op() const
Operator.
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[]
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.
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