31 #include <QStringList>
32 #include <QTextStream>
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" )
53 bool honourAxisOrientation,
54 bool invertAxisOrientation )
57 , mGMLVersion( gmlVersion )
58 , mFilterVersion( filterVersion )
61 , mInvertAxisOrientation( invertAxisOrientation )
62 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
63 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
67 if ( !mSrsName.isEmpty() )
73 mInvertAxisOrientation = !mInvertAxisOrientation;
80 QDomElement geometryTypeElement = geometryNode.toElement();
81 QString geomType = geometryTypeElement.tagName();
84 if ( !( geomType == QLatin1String(
"Point" ) || geomType == QLatin1String(
"LineString" ) || geomType == QLatin1String(
"Polygon" ) ||
85 geomType == QLatin1String(
"MultiPoint" ) || geomType == QLatin1String(
"MultiLineString" ) || geomType == QLatin1String(
"MultiPolygon" ) ||
86 geomType == QLatin1String(
"Box" ) || geomType == QLatin1String(
"Envelope" ) ) )
88 const QDomNode geometryChild = geometryNode.firstChild();
89 if ( geometryChild.isNull() )
93 geometryTypeElement = geometryChild.toElement();
94 geomType = geometryTypeElement.tagName();
97 if ( !( geomType == QLatin1String(
"Point" ) || geomType == QLatin1String(
"LineString" ) || geomType == QLatin1String(
"Polygon" ) ||
98 geomType == QLatin1String(
"MultiPoint" ) || geomType == QLatin1String(
"MultiLineString" ) || geomType == QLatin1String(
"MultiPolygon" ) ||
99 geomType == QLatin1String(
"Box" ) || geomType == QLatin1String(
"Envelope" ) ) )
102 if ( geomType == QLatin1String(
"Point" ) )
104 geometry = geometryFromGMLPoint( geometryTypeElement );
106 else if ( geomType == QLatin1String(
"LineString" ) )
108 geometry = geometryFromGMLLineString( geometryTypeElement );
110 else if ( geomType == QLatin1String(
"Polygon" ) )
112 geometry = geometryFromGMLPolygon( geometryTypeElement );
114 else if ( geomType == QLatin1String(
"MultiPoint" ) )
116 geometry = geometryFromGMLMultiPoint( geometryTypeElement );
118 else if ( geomType == QLatin1String(
"MultiLineString" ) )
120 geometry = geometryFromGMLMultiLineString( geometryTypeElement );
122 else if ( geomType == QLatin1String(
"MultiPolygon" ) )
124 geometry = geometryFromGMLMultiPolygon( geometryTypeElement );
126 else if ( geomType == QLatin1String(
"Box" ) )
130 else if ( geomType == QLatin1String(
"Envelope" ) )
144 if ( geometryTypeElement.hasAttribute( QStringLiteral(
"srsName" ) ) )
146 QString
srsName { geometryTypeElement.attribute( QStringLiteral(
"srsName" ) ) };
149 const bool ignoreAxisOrientation {
srsName.startsWith( QLatin1String(
"http://www.opengis.net/gml/srs/" ) ) ||
srsName.startsWith( QLatin1String(
"EPSG:" ) ) };
153 if (
srsName.startsWith( QLatin1String(
"http://www.opengis.net/gml/srs/" ) ) )
155 const auto parts {
srsName.split( QRegularExpression( QStringLiteral( R
"raw(/|#|\.)raw" ) ) ) };
156 if ( parts.length() == 10 )
158 srsName = QStringLiteral(
"http://www.opengis.net/def/crs/%1/0/%2" ).arg( parts[ 7 ].toUpper(), parts[ 9 ] );
191 const QString xml = QStringLiteral(
"<tmp xmlns=\"%1\" xmlns:gml=\"%1\">%2</tmp>" ).arg(
GML_NAMESPACE, xmlString );
193 if ( !doc.setContent( xml,
true ) )
196 return geometryFromGML( doc.documentElement().firstChildElement(), context );
200 QgsGeometry QgsOgcUtils::geometryFromGMLPoint(
const QDomElement &geometryElement )
204 const QDomNodeList coordList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
205 if ( !coordList.isEmpty() )
207 const QDomElement coordElement = coordList.at( 0 ).toElement();
208 if ( readGMLCoordinates( pointCoordinate, coordElement ) != 0 )
215 const QDomNodeList posList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pos" ) );
216 if ( posList.size() < 1 )
220 const QDomElement posElement = posList.at( 0 ).toElement();
221 if ( readGMLPositions( pointCoordinate, posElement ) != 0 )
227 if ( pointCoordinate.empty() )
232 QgsPolylineXY::const_iterator point_it = pointCoordinate.constBegin();
233 char e = htonl( 1 ) != 1;
234 double x = point_it->x();
235 double y = point_it->y();
236 const int size = 1 +
sizeof( int ) + 2 *
sizeof(
double );
239 unsigned char *wkb =
new unsigned char[size];
242 memcpy( &( wkb )[wkbPosition], &e, 1 );
244 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
245 wkbPosition +=
sizeof( int );
246 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
247 wkbPosition +=
sizeof( double );
248 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
255 QgsGeometry QgsOgcUtils::geometryFromGMLLineString(
const QDomElement &geometryElement )
259 const QDomNodeList coordList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
260 if ( !coordList.isEmpty() )
262 const QDomElement coordElement = coordList.at( 0 ).toElement();
263 if ( readGMLCoordinates( lineCoordinates, coordElement ) != 0 )
270 const QDomNodeList posList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
271 if ( posList.size() < 1 )
275 const QDomElement posElement = posList.at( 0 ).toElement();
276 if ( readGMLPositions( lineCoordinates, posElement ) != 0 )
282 char e = htonl( 1 ) != 1;
283 const int size = 1 + 2 *
sizeof( int ) + lineCoordinates.size() * 2 *
sizeof( double );
286 unsigned char *wkb =
new unsigned char[size];
290 int nPoints = lineCoordinates.size();
293 memcpy( &( wkb )[wkbPosition], &e, 1 );
295 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
296 wkbPosition +=
sizeof( int );
297 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
298 wkbPosition +=
sizeof( int );
300 QgsPolylineXY::const_iterator iter;
301 for ( iter = lineCoordinates.constBegin(); iter != lineCoordinates.constEnd(); ++iter )
305 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
306 wkbPosition +=
sizeof( double );
307 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
308 wkbPosition +=
sizeof( double );
316 QgsGeometry QgsOgcUtils::geometryFromGMLPolygon(
const QDomElement &geometryElement )
323 const QDomNodeList outerBoundaryList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"outerBoundaryIs" ) );
324 if ( !outerBoundaryList.isEmpty() )
326 QDomElement coordinatesElement = outerBoundaryList.at( 0 ).firstChild().firstChild().toElement();
327 if ( coordinatesElement.isNull() )
331 if ( readGMLCoordinates( exteriorPointList, coordinatesElement ) != 0 )
335 ringCoordinates.push_back( exteriorPointList );
338 const QDomNodeList innerBoundaryList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"innerBoundaryIs" ) );
339 for (
int i = 0; i < innerBoundaryList.size(); ++i )
342 coordinatesElement = innerBoundaryList.at( i ).firstChild().firstChild().toElement();
343 if ( coordinatesElement.isNull() )
347 if ( readGMLCoordinates( interiorPointList, coordinatesElement ) != 0 )
351 ringCoordinates.push_back( interiorPointList );
357 const QDomNodeList exteriorList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"exterior" ) );
358 if ( exteriorList.size() < 1 )
362 const QDomElement posElement = exteriorList.at( 0 ).firstChild().firstChild().toElement();
363 if ( posElement.isNull() )
367 if ( readGMLPositions( exteriorPointList, posElement ) != 0 )
371 ringCoordinates.push_back( exteriorPointList );
374 const QDomNodeList interiorList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"interior" ) );
375 for (
int i = 0; i < interiorList.size(); ++i )
378 const QDomElement posElement = interiorList.at( i ).firstChild().firstChild().toElement();
379 if ( posElement.isNull() )
384 if ( readGMLPositions( interiorPointList, posElement ) )
388 ringCoordinates.push_back( interiorPointList );
393 int nrings = ringCoordinates.size();
398 for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
400 npoints += it->size();
402 const int size = 1 + 2 *
sizeof( int ) + nrings *
sizeof(
int ) + 2 * npoints *
sizeof( double );
405 unsigned char *wkb =
new unsigned char[size];
408 char e = htonl( 1 ) != 1;
410 int nPointsInRing = 0;
414 memcpy( &( wkb )[wkbPosition], &e, 1 );
416 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
417 wkbPosition +=
sizeof( int );
418 memcpy( &( wkb )[wkbPosition], &nrings,
sizeof(
int ) );
419 wkbPosition +=
sizeof( int );
420 for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
422 nPointsInRing = it->size();
423 memcpy( &( wkb )[wkbPosition], &nPointsInRing,
sizeof(
int ) );
424 wkbPosition +=
sizeof( int );
426 QgsPolylineXY::const_iterator iter;
427 for ( iter = it->begin(); iter != it->end(); ++iter )
432 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
433 wkbPosition +=
sizeof( double );
434 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
435 wkbPosition +=
sizeof( double );
444 QgsGeometry QgsOgcUtils::geometryFromGMLMultiPoint(
const QDomElement &geometryElement )
448 const QDomNodeList pointMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pointMember" ) );
449 if ( pointMemberList.size() < 1 )
453 QDomNodeList pointNodeList;
455 QDomNodeList coordinatesList;
456 QDomNodeList posList;
457 for (
int i = 0; i < pointMemberList.size(); ++i )
460 pointNodeList = pointMemberList.at( i ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"Point" ) );
461 if ( pointNodeList.size() < 1 )
466 coordinatesList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
467 if ( !coordinatesList.isEmpty() )
469 currentPoint.clear();
470 if ( readGMLCoordinates( currentPoint, coordinatesList.at( 0 ).toElement() ) != 0 )
474 if ( currentPoint.empty() )
478 pointList.push_back( ( *currentPoint.begin() ) );
484 posList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pos" ) );
485 if ( posList.size() < 1 )
489 currentPoint.clear();
490 if ( readGMLPositions( currentPoint, posList.at( 0 ).toElement() ) != 0 )
494 if ( currentPoint.empty() )
498 pointList.push_back( ( *currentPoint.begin() ) );
502 int nPoints = pointList.size();
507 const int size = 1 + 2 *
sizeof( int ) + pointList.size() * ( 2 *
sizeof( double ) + 1 +
sizeof(
int ) );
510 unsigned char *wkb =
new unsigned char[size];
513 char e = htonl( 1 ) != 1;
516 memcpy( &( wkb )[wkbPosition], &e, 1 );
518 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
519 wkbPosition +=
sizeof( int );
520 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
521 wkbPosition +=
sizeof( int );
523 for ( QgsPolylineXY::const_iterator it = pointList.constBegin(); it != pointList.constEnd(); ++it )
525 memcpy( &( wkb )[wkbPosition], &e, 1 );
527 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
528 wkbPosition +=
sizeof( int );
530 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
531 wkbPosition +=
sizeof( double );
533 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
534 wkbPosition +=
sizeof( double );
542 QgsGeometry QgsOgcUtils::geometryFromGMLMultiLineString(
const QDomElement &geometryElement )
553 QList< QgsPolylineXY > lineCoordinates;
554 QDomElement currentLineStringElement;
555 QDomNodeList currentCoordList;
556 QDomNodeList currentPosList;
558 const QDomNodeList lineStringMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"lineStringMember" ) );
559 if ( !lineStringMemberList.isEmpty() )
561 for (
int i = 0; i < lineStringMemberList.size(); ++i )
563 const QDomNodeList lineStringNodeList = lineStringMemberList.at( i ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LineString" ) );
564 if ( lineStringNodeList.size() < 1 )
568 currentLineStringElement = lineStringNodeList.at( 0 ).toElement();
569 currentCoordList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
570 if ( !currentCoordList.isEmpty() )
573 if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
577 lineCoordinates.push_back( currentPointList );
581 currentPosList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
582 if ( currentPosList.size() < 1 )
587 if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
591 lineCoordinates.push_back( currentPointList );
597 const QDomNodeList lineStringList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LineString" ) );
598 if ( !lineStringList.isEmpty() )
600 for (
int i = 0; i < lineStringList.size(); ++i )
602 currentLineStringElement = lineStringList.at( i ).toElement();
603 currentCoordList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
604 if ( !currentCoordList.isEmpty() )
607 if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
611 lineCoordinates.push_back( currentPointList );
616 currentPosList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
617 if ( currentPosList.size() < 1 )
622 if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
626 lineCoordinates.push_back( currentPointList );
636 int nLines = lineCoordinates.size();
641 int size = ( lineCoordinates.size() + 1 ) * ( 1 + 2 *
sizeof(
int ) );
642 for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
644 size += it->size() * 2 *
sizeof( double );
648 unsigned char *wkb =
new unsigned char[size];
651 char e = htonl( 1 ) != 1;
655 memcpy( &( wkb )[wkbPosition], &e, 1 );
657 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
658 wkbPosition +=
sizeof( int );
659 memcpy( &( wkb )[wkbPosition], &nLines,
sizeof(
int ) );
660 wkbPosition +=
sizeof( int );
662 for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
664 memcpy( &( wkb )[wkbPosition], &e, 1 );
666 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
667 wkbPosition +=
sizeof( int );
668 nPoints = it->size();
669 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
670 wkbPosition +=
sizeof( int );
671 for ( QgsPolylineXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
676 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
677 wkbPosition +=
sizeof( double );
678 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
679 wkbPosition +=
sizeof( double );
688 QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon(
const QDomElement &geometryElement )
692 QDomElement currentPolygonMemberElement;
693 QDomNodeList polygonList;
694 QDomElement currentPolygonElement;
696 QDomNodeList outerBoundaryList;
697 QDomElement currentOuterBoundaryElement;
698 const QDomNodeList innerBoundaryList;
699 QDomElement currentInnerBoundaryElement;
701 QDomNodeList exteriorList;
702 QDomElement currentExteriorElement;
703 QDomElement currentInteriorElement;
704 const QDomNodeList interiorList;
706 QDomNodeList linearRingNodeList;
707 QDomElement currentLinearRingElement;
709 QDomNodeList currentCoordinateList;
710 QDomNodeList currentPosList;
712 const QDomNodeList polygonMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"polygonMember" ) );
714 for (
int i = 0; i < polygonMemberList.size(); ++i )
716 currentPolygonList.resize( 0 );
717 currentPolygonMemberElement = polygonMemberList.at( i ).toElement();
718 polygonList = currentPolygonMemberElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"Polygon" ) );
719 if ( polygonList.size() < 1 )
723 currentPolygonElement = polygonList.at( 0 ).toElement();
726 outerBoundaryList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"outerBoundaryIs" ) );
727 if ( !outerBoundaryList.isEmpty() )
729 currentOuterBoundaryElement = outerBoundaryList.at( 0 ).toElement();
732 linearRingNodeList = currentOuterBoundaryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
733 if ( linearRingNodeList.size() < 1 )
737 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
738 currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
739 if ( currentCoordinateList.size() < 1 )
743 if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
747 currentPolygonList.push_back( ringCoordinates );
750 const QDomNodeList innerBoundaryList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"innerBoundaryIs" ) );
751 for (
int j = 0; j < innerBoundaryList.size(); ++j )
754 currentInnerBoundaryElement = innerBoundaryList.at( j ).toElement();
755 linearRingNodeList = currentInnerBoundaryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
756 if ( linearRingNodeList.size() < 1 )
760 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
761 currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
762 if ( currentCoordinateList.size() < 1 )
766 if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
770 currentPolygonList.push_back( ringCoordinates );
776 exteriorList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"exterior" ) );
777 if ( exteriorList.size() < 1 )
782 currentExteriorElement = exteriorList.at( 0 ).toElement();
785 linearRingNodeList = currentExteriorElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
786 if ( linearRingNodeList.size() < 1 )
790 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
791 currentPosList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
792 if ( currentPosList.size() < 1 )
796 if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
800 currentPolygonList.push_back( ringPositions );
803 const QDomNodeList interiorList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"interior" ) );
804 for (
int j = 0; j < interiorList.size(); ++j )
807 currentInteriorElement = interiorList.at( j ).toElement();
808 linearRingNodeList = currentInteriorElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
809 if ( linearRingNodeList.size() < 1 )
813 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
814 currentPosList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
815 if ( currentPosList.size() < 1 )
819 if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
823 currentPolygonList.push_back( ringPositions );
826 multiPolygonPoints.push_back( currentPolygonList );
829 int nPolygons = multiPolygonPoints.size();
833 int size = 1 + 2 *
sizeof( int );
835 for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
837 size += 1 + 2 *
sizeof( int );
838 for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
840 size +=
sizeof( int ) + 2 * iter->size() *
sizeof( double );
845 unsigned char *wkb =
new unsigned char[size];
847 char e = htonl( 1 ) != 1;
854 memcpy( &( wkb )[wkbPosition], &e, 1 );
856 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
857 wkbPosition +=
sizeof( int );
858 memcpy( &( wkb )[wkbPosition], &nPolygons,
sizeof(
int ) );
859 wkbPosition +=
sizeof( int );
863 for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
865 memcpy( &( wkb )[wkbPosition], &e, 1 );
867 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
868 wkbPosition +=
sizeof( int );
870 memcpy( &( wkb )[wkbPosition], &nRings,
sizeof(
int ) );
871 wkbPosition +=
sizeof( int );
872 for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
874 nPointsInRing = iter->size();
875 memcpy( &( wkb )[wkbPosition], &nPointsInRing,
sizeof(
int ) );
876 wkbPosition +=
sizeof( int );
877 for ( QgsPolylineXY::const_iterator iterator = iter->begin(); iterator != iter->end(); ++iterator )
881 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
882 wkbPosition +=
sizeof( double );
883 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
884 wkbPosition +=
sizeof( double );
894 bool QgsOgcUtils::readGMLCoordinates(
QgsPolylineXY &coords,
const QDomElement &elem )
896 QString coordSeparator = QStringLiteral(
"," );
897 QString tupelSeparator = QStringLiteral(
" " );
902 if ( elem.hasAttribute( QStringLiteral(
"cs" ) ) )
904 coordSeparator = elem.attribute( QStringLiteral(
"cs" ) );
906 if ( elem.hasAttribute( QStringLiteral(
"ts" ) ) )
908 tupelSeparator = elem.attribute( QStringLiteral(
"ts" ) );
911 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
912 QStringList tupels = elem.text().split( tupelSeparator, QString::SkipEmptyParts );
914 const QStringList tupels = elem.text().split( tupelSeparator, Qt::SkipEmptyParts );
916 QStringList tuple_coords;
918 bool conversionSuccess;
920 QStringList::const_iterator it;
921 for ( it = tupels.constBegin(); it != tupels.constEnd(); ++it )
923 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
924 tuple_coords = ( *it ).split( coordSeparator, QString::SkipEmptyParts );
926 tuple_coords = ( *it ).split( coordSeparator, Qt::SkipEmptyParts );
928 if ( tuple_coords.size() < 2 )
932 x = tuple_coords.at( 0 ).toDouble( &conversionSuccess );
933 if ( !conversionSuccess )
937 y = tuple_coords.at( 1 ).toDouble( &conversionSuccess );
938 if ( !conversionSuccess )
951 const QDomElement boxElem = boxNode.toElement();
952 if ( boxElem.tagName() != QLatin1String(
"Box" ) )
955 const QDomElement bElem = boxElem.firstChild().toElement();
956 QString coordSeparator = QStringLiteral(
"," );
957 QString tupelSeparator = QStringLiteral(
" " );
958 if ( bElem.hasAttribute( QStringLiteral(
"cs" ) ) )
960 coordSeparator = bElem.attribute( QStringLiteral(
"cs" ) );
962 if ( bElem.hasAttribute( QStringLiteral(
"ts" ) ) )
964 tupelSeparator = bElem.attribute( QStringLiteral(
"ts" ) );
967 const QString bString = bElem.text();
968 bool ok1, ok2, ok3, ok4;
969 const double xmin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 0, 0 ).toDouble( &ok1 );
970 const double ymin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 1, 1 ).toDouble( &ok2 );
971 const double xmax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 0, 0 ).toDouble( &ok3 );
972 const double ymax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 1, 1 ).toDouble( &ok4 );
974 if ( ok1 && ok2 && ok3 && ok4 )
983 bool QgsOgcUtils::readGMLPositions(
QgsPolylineXY &coords,
const QDomElement &elem )
987 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
988 QStringList pos = elem.text().split(
' ', QString::SkipEmptyParts );
990 const QStringList pos = elem.text().split(
' ', Qt::SkipEmptyParts );
993 bool conversionSuccess;
994 const int posSize = pos.size();
996 int srsDimension = 2;
997 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
999 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
1000 if ( !conversionSuccess )
1005 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1007 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1008 if ( !conversionSuccess )
1014 for (
int i = 0; i < posSize / srsDimension; i++ )
1016 x = pos.at( i * srsDimension ).toDouble( &conversionSuccess );
1017 if ( !conversionSuccess )
1021 y = pos.at( i * srsDimension + 1 ).toDouble( &conversionSuccess );
1022 if ( !conversionSuccess )
1036 const QDomElement envelopeElem = envelopeNode.toElement();
1037 if ( envelopeElem.tagName() != QLatin1String(
"Envelope" ) )
1040 const QDomNodeList lowerCornerList = envelopeElem.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"lowerCorner" ) );
1041 if ( lowerCornerList.size() < 1 )
1044 const QDomNodeList upperCornerList = envelopeElem.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"upperCorner" ) );
1045 if ( upperCornerList.size() < 1 )
1048 bool conversionSuccess;
1049 int srsDimension = 2;
1051 QDomElement elem = lowerCornerList.at( 0 ).toElement();
1052 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
1054 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
1055 if ( !conversionSuccess )
1060 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1062 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1063 if ( !conversionSuccess )
1068 QString bString = elem.text();
1070 const double xmin = bString.section(
' ', 0, 0 ).toDouble( &conversionSuccess );
1071 if ( !conversionSuccess )
1073 const double ymin = bString.section(
' ', 1, 1 ).toDouble( &conversionSuccess );
1074 if ( !conversionSuccess )
1077 elem = upperCornerList.at( 0 ).toElement();
1078 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
1080 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
1081 if ( !conversionSuccess )
1086 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1088 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1089 if ( !conversionSuccess )
1095 Q_UNUSED( srsDimension )
1097 bString = elem.text();
1098 const double xmax = bString.section(
' ', 0, 0 ).toDouble( &conversionSuccess );
1099 if ( !conversionSuccess )
1101 const double ymax = bString.section(
' ', 1, 1 ).toDouble( &conversionSuccess );
1102 if ( !conversionSuccess )
1118 bool invertAxisOrientation,
1123 return QDomElement();
1126 QDomElement boxElem = doc.createElement( QStringLiteral(
"gml:Box" ) );
1129 boxElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1131 QDomElement coordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1132 coordElem.setAttribute( QStringLiteral(
"cs" ), QStringLiteral(
"," ) );
1133 coordElem.setAttribute( QStringLiteral(
"ts" ), QStringLiteral(
" " ) );
1135 QString coordString;
1144 const QDomText coordText = doc.createTextNode( coordString );
1145 coordElem.appendChild( coordText );
1146 boxElem.appendChild( coordElem );
1158 bool invertAxisOrientation,
1163 return QDomElement();
1166 QDomElement envElem = doc.createElement( QStringLiteral(
"gml:Envelope" ) );
1169 envElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1173 QDomElement lowerCornerElem = doc.createElement( QStringLiteral(
"gml:lowerCorner" ) );
1177 const QDomText lowerCornerText = doc.createTextNode( posList );
1178 lowerCornerElem.appendChild( lowerCornerText );
1179 envElem.appendChild( lowerCornerElem );
1181 QDomElement upperCornerElem = doc.createElement( QStringLiteral(
"gml:upperCorner" ) );
1185 const QDomText upperCornerText = doc.createTextNode( posList );
1186 upperCornerElem.appendChild( upperCornerText );
1187 envElem.appendChild( upperCornerElem );
1201 bool invertAxisOrientation,
1202 const QString &gmlIdBase,
1206 return QDomElement();
1209 QString cs = QStringLiteral(
"," );
1211 const QString ts = QStringLiteral(
" " );
1213 QDomElement baseCoordElem;
1215 bool hasZValue =
false;
1217 const QByteArray wkb( geometry.
asWkb() );
1227 return QDomElement();
1238 baseCoordElem = doc.createElement( QStringLiteral(
"gml:pos" ) );
1241 baseCoordElem = doc.createElement( QStringLiteral(
"gml:posList" ) );
1244 baseCoordElem.setAttribute( QStringLiteral(
"srsDimension" ), QStringLiteral(
"2" ) );
1249 baseCoordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1250 baseCoordElem.setAttribute( QStringLiteral(
"cs" ), cs );
1251 baseCoordElem.setAttribute( QStringLiteral(
"ts" ), ts );
1261 QDomElement pointElem = doc.createElement( QStringLiteral(
"gml:Point" ) );
1262 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1263 pointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1265 pointElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1266 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1270 if ( invertAxisOrientation )
1276 coordElem.appendChild( coordText );
1277 pointElem.appendChild( coordElem );
1286 QDomElement multiPointElem = doc.createElement( QStringLiteral(
"gml:MultiPoint" ) );
1287 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1288 multiPointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1290 multiPointElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1295 for (
int idx = 0; idx < nPoints; ++idx )
1297 QDomElement pointMemberElem = doc.createElement( QStringLiteral(
"gml:pointMember" ) );
1298 QDomElement pointElem = doc.createElement( QStringLiteral(
"gml:Point" ) );
1299 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1300 pointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( idx + 1 ) );
1301 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1307 if ( invertAxisOrientation )
1313 coordElem.appendChild( coordText );
1314 pointElem.appendChild( coordElem );
1318 wkbPtr +=
sizeof( double );
1320 pointMemberElem.appendChild( pointElem );
1321 multiPointElem.appendChild( pointMemberElem );
1323 return multiPointElem;
1331 QDomElement lineStringElem = doc.createElement( QStringLiteral(
"gml:LineString" ) );
1332 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1333 lineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1335 lineStringElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1341 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1342 QString coordString;
1343 for (
int idx = 0; idx < nPoints; ++idx )
1352 if ( invertAxisOrientation )
1360 wkbPtr +=
sizeof( double );
1363 const QDomText coordText = doc.createTextNode( coordString );
1364 coordElem.appendChild( coordText );
1365 lineStringElem.appendChild( coordElem );
1366 return lineStringElem;
1374 QDomElement multiLineStringElem = doc.createElement( QStringLiteral(
"gml:MultiLineString" ) );
1375 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1376 multiLineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1378 multiLineStringElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1383 for (
int jdx = 0; jdx < nLines; jdx++ )
1385 QDomElement lineStringMemberElem = doc.createElement( QStringLiteral(
"gml:lineStringMember" ) );
1386 QDomElement lineStringElem = doc.createElement( QStringLiteral(
"gml:LineString" ) );
1387 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1388 lineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( jdx + 1 ) );
1395 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1396 QString coordString;
1397 for (
int idx = 0; idx < nPoints; idx++ )
1406 if ( invertAxisOrientation )
1415 wkbPtr +=
sizeof( double );
1418 const QDomText coordText = doc.createTextNode( coordString );
1419 coordElem.appendChild( coordText );
1420 lineStringElem.appendChild( coordElem );
1421 lineStringMemberElem.appendChild( lineStringElem );
1422 multiLineStringElem.appendChild( lineStringMemberElem );
1424 return multiLineStringElem;
1432 QDomElement polygonElem = doc.createElement( QStringLiteral(
"gml:Polygon" ) );
1433 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1434 polygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1436 polygonElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1442 if ( numRings == 0 )
1443 return QDomElement();
1445 for (
int idx = 0; idx < numRings; idx++ )
1447 QString boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:outerBoundaryIs" :
"gml:exterior";
1450 boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:innerBoundaryIs" :
"gml:interior";
1452 QDomElement boundaryElem = doc.createElement( boundaryName );
1453 QDomElement ringElem = doc.createElement( QStringLiteral(
"gml:LinearRing" ) );
1458 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1459 QString coordString;
1460 for (
int jdx = 0; jdx < nPoints; jdx++ )
1469 if ( invertAxisOrientation )
1477 wkbPtr +=
sizeof( double );
1480 const QDomText coordText = doc.createTextNode( coordString );
1481 coordElem.appendChild( coordText );
1482 ringElem.appendChild( coordElem );
1483 boundaryElem.appendChild( ringElem );
1484 polygonElem.appendChild( boundaryElem );
1494 QDomElement multiPolygonElem = doc.createElement( QStringLiteral(
"gml:MultiPolygon" ) );
1495 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1496 multiPolygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1498 multiPolygonElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1501 wkbPtr >> numPolygons;
1503 for (
int kdx = 0; kdx < numPolygons; kdx++ )
1505 QDomElement polygonMemberElem = doc.createElement( QStringLiteral(
"gml:polygonMember" ) );
1506 QDomElement polygonElem = doc.createElement( QStringLiteral(
"gml:Polygon" ) );
1507 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1508 polygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( kdx + 1 ) );
1515 for (
int idx = 0; idx < numRings; idx++ )
1517 QString boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:outerBoundaryIs" :
"gml:exterior";
1520 boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:innerBoundaryIs" :
"gml:interior";
1522 QDomElement boundaryElem = doc.createElement( boundaryName );
1523 QDomElement ringElem = doc.createElement( QStringLiteral(
"gml:LinearRing" ) );
1528 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1529 QString coordString;
1530 for (
int jdx = 0; jdx < nPoints; jdx++ )
1539 if ( invertAxisOrientation )
1548 wkbPtr +=
sizeof( double );
1551 const QDomText coordText = doc.createTextNode( coordString );
1552 coordElem.appendChild( coordText );
1553 ringElem.appendChild( coordElem );
1554 boundaryElem.appendChild( ringElem );
1555 polygonElem.appendChild( boundaryElem );
1556 polygonMemberElem.appendChild( polygonElem );
1557 multiPolygonElem.appendChild( polygonMemberElem );
1560 return multiPolygonElem;
1563 return QDomElement();
1569 return QDomElement();
1578 QDomElement QgsOgcUtils::createGMLCoordinates(
const QgsPolylineXY &points, QDomDocument &doc )
1580 QDomElement coordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1581 coordElem.setAttribute( QStringLiteral(
"cs" ), QStringLiteral(
"," ) );
1582 coordElem.setAttribute( QStringLiteral(
"ts" ), QStringLiteral(
" " ) );
1584 QString coordString;
1585 QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
1586 for ( ; pointIt != points.constEnd(); ++pointIt )
1588 if ( pointIt != points.constBegin() )
1597 const QDomText coordText = doc.createTextNode( coordString );
1598 coordElem.appendChild( coordText );
1602 QDomElement QgsOgcUtils::createGMLPositions(
const QgsPolylineXY &points, QDomDocument &doc )
1604 QDomElement posElem = doc.createElement( QStringLiteral(
"gml:pos" ) );
1605 if ( points.size() > 1 )
1606 posElem = doc.createElement( QStringLiteral(
"gml:posList" ) );
1607 posElem.setAttribute( QStringLiteral(
"srsDimension" ), QStringLiteral(
"2" ) );
1609 QString coordString;
1610 QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
1611 for ( ; pointIt != points.constEnd(); ++pointIt )
1613 if ( pointIt != points.constBegin() )
1622 const QDomText coordText = doc.createTextNode( coordString );
1623 posElem.appendChild( coordText );
1633 if ( fillElement.isNull() || !fillElement.hasChildNodes() )
1641 QDomElement cssElem = fillElement.firstChildElement( QStringLiteral(
"CssParameter" ) );
1642 while ( !cssElem.isNull() )
1644 cssName = cssElem.attribute( QStringLiteral(
"name" ), QStringLiteral(
"not_found" ) );
1645 if ( cssName != QLatin1String(
"not_found" ) )
1647 elemText = cssElem.text();
1648 if ( cssName == QLatin1String(
"fill" ) )
1650 color.setNamedColor( elemText );
1652 else if ( cssName == QLatin1String(
"fill-opacity" ) )
1655 const double opacity = elemText.toDouble( &ok );
1658 color.setAlphaF( opacity );
1663 cssElem = cssElem.nextSiblingElement( QStringLiteral(
"CssParameter" ) );
1677 if ( element.isNull() || !element.hasChildNodes() )
1684 if ( element.firstChild().nodeType() == QDomNode::TextNode )
1694 QDomElement childElem = element.firstChildElement();
1695 while ( !childElem.isNull() )
1707 if ( !expr->d->mRootNode )
1709 expr->d->mRootNode = node;
1716 childElem = childElem.nextSiblingElement();
1720 expr->d->mExp = expr->
dump();
1746 static
int binaryOperatorFromTagName( const QString &tagName )
1749 return BINARY_OPERATORS_TAG_NAMES_MAP()->value( tagName, -1 );
1756 return QStringLiteral(
"PropertyIsLike" );
1758 return BINARY_OPERATORS_TAG_NAMES_MAP()->key( op, QString() );
1761 static bool isBinaryOperator(
const QString &tagName )
1763 return binaryOperatorFromTagName( tagName ) >= 0;
1767 static bool isSpatialOperator(
const QString &tagName )
1769 static QStringList spatialOps;
1770 if ( spatialOps.isEmpty() )
1772 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
1773 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
1776 return spatialOps.contains( tagName );
1783 errorMessage = utils.errorMessage();
1791 errorMessage = utils.errorMessage();
1799 errorMessage = utils.errorMessage();
1807 errorMessage = utils.errorMessage();
1815 errorMessage = utils.errorMessage();
1823 errorMessage = utils.errorMessage();
1831 errorMessage = utils.errorMessage();
1835 QgsExpressionNode *QgsOgcUtils::nodeIsBetweenFromOgcFilter( QDomElement &element, QString &errorMessage )
1839 errorMessage = utils.errorMessage();
1847 errorMessage = utils.errorMessage();
1858 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage );
1864 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage );
1873 bool honourAxisOrientation,
1874 bool invertAxisOrientation,
1875 QString *errorMessage )
1878 return QDomElement();
1888 if ( exprRootElem.isNull() )
1889 return QDomElement();
1891 QDomElement filterElem =
1893 doc.createElementNS(
FES_NAMESPACE, QStringLiteral(
"fes:Filter" ) ) :
1894 doc.createElementNS(
OGC_NAMESPACE, QStringLiteral(
"ogc:Filter" ) );
1897 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:gml" ) );
1902 filterElem.setAttributeNode( attr );
1904 filterElem.appendChild( exprRootElem );
1914 bool honourAxisOrientation,
1915 bool invertAxisOrientation,
1916 QString *errorMessage )
1925 return QDomElement();
1939 if ( !exprRootElem.isNull() )
1941 return exprRootElem;
1948 *errorMessage = QObject::tr(
"Node type not supported in expression translation: %1" ).arg( node->
nodeType() );
1952 return QDomElement();
1959 const QList<LayerProperties> &layerProperties,
1960 bool honourAxisOrientation,
1961 bool invertAxisOrientation,
1962 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename,
1963 QString *errorMessage )
1966 return QDomElement();
1969 layerProperties, honourAxisOrientation, invertAxisOrientation,
1970 mapUnprefixedTypenameToPrefixedTypename );
1974 if ( exprRootElem.isNull() )
1975 return QDomElement();
1977 QDomElement filterElem =
1979 doc.createElementNS(
FES_NAMESPACE, QStringLiteral(
"fes:Filter" ) ) :
1980 doc.createElementNS(
OGC_NAMESPACE, QStringLiteral(
"ogc:Filter" ) );
1983 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:gml" ) );
1988 filterElem.setAttributeNode( attr );
1991 QSet<QString> setNamespaceURI;
1994 if ( !props.mNamespacePrefix.isEmpty() && !props.mNamespaceURI.isEmpty() &&
1995 !setNamespaceURI.contains( props.mNamespaceURI ) )
1997 setNamespaceURI.insert( props.mNamespaceURI );
1998 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:" ) + props.mNamespacePrefix );
1999 attr.setValue( props.mNamespaceURI );
2000 filterElem.setAttributeNode( attr );
2004 filterElem.appendChild( exprRootElem );
2029 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
2030 return QDomElement();
2037 if ( !mErrorMessage.isEmpty() )
2038 return QDomElement();
2041 switch ( node->
op() )
2044 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2049 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
2050 mDoc.removeChild( operandElem );
2054 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
2055 return QDomElement();
2059 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
2060 uoElem.appendChild( operandElem );
2064 mErrorMessage = QObject::tr(
"Unary operator '%1' not implemented yet" ).arg( node->
text() );
2065 return QDomElement();
2075 if ( !mErrorMessage.isEmpty() )
2076 return QDomElement();
2086 if ( rightLit->
value().isNull() )
2089 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2090 elem.appendChild( leftElem );
2094 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2095 notElem.appendChild( elem );
2109 if ( !mErrorMessage.isEmpty() )
2110 return QDomElement();
2113 const QString opText = binaryOperatorToTagName( op );
2114 if ( opText.isEmpty() )
2118 mErrorMessage = QObject::tr(
"Binary operator %1 not implemented yet" ).arg( node->
text() );
2119 return QDomElement();
2122 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2127 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2130 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2131 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2133 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2135 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2138 boElem.appendChild( leftElem );
2139 boElem.appendChild( rightElem );
2146 Q_UNUSED( expression )
2149 switch ( node->
value().type() )
2152 value = QString::number( node->
value().toInt() );
2154 case QVariant::Double:
2157 case QVariant::String:
2158 value = node->
value().toString();
2160 case QVariant::Date:
2161 value = node->
value().toDate().toString( Qt::ISODate );
2163 case QVariant::DateTime:
2164 value = node->
value().toDateTime().toString( Qt::ISODate );
2168 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2169 return QDomElement();
2172 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2173 litElem.appendChild( mDoc.createTextNode( value ) );
2180 Q_UNUSED( expression )
2182 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2183 propElem.appendChild( mDoc.createTextNode( node->
name() ) );
2191 if ( node->
list()->
list().size() == 1 )
2194 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2197 const auto constList = node->
list()->
list();
2201 if ( !mErrorMessage.isEmpty() )
2202 return QDomElement();
2204 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2205 eqElem.appendChild( leftNode.cloneNode() );
2206 eqElem.appendChild( listNode );
2208 orElem.appendChild( eqElem );
2213 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2214 notElem.appendChild( orElem );
2223 { QLatin1String(
"disjoint" ), QLatin1String(
"Disjoint" ) },
2224 { QLatin1String(
"intersects" ), QLatin1String(
"Intersects" )},
2225 { QLatin1String(
"touches" ), QLatin1String(
"Touches" ) },
2226 { QLatin1String(
"crosses" ), QLatin1String(
"Crosses" ) },
2227 { QLatin1String(
"contains" ), QLatin1String(
"Contains" ) },
2228 { QLatin1String(
"overlaps" ), QLatin1String(
"Overlaps" ) },
2229 { QLatin1String(
"within" ), QLatin1String(
"Within" ) }
2232 static
bool isBinarySpatialOperator( const QString &fnName )
2234 return BINARY_SPATIAL_OPS_MAP()->contains( fnName );
2237 static QString tagNameForSpatialOperator(
const QString &fnName )
2239 return BINARY_SPATIAL_OPS_MAP()->value( fnName );
2249 return fd->
name() == QLatin1String(
"$geometry" );
2261 if ( fnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2263 const QList<QgsExpressionNode *> &args = fnNode->
args()->
list();
2279 if ( fd->
name() == QLatin1String(
"intersects_bbox" ) )
2281 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2282 Q_ASSERT( argNodes.count() == 2 );
2284 const QgsGeometry geom = geometryFromConstExpr( argNodes[1] );
2285 if ( !geom.
isNull() && isGeometryColumn( argNodes[0] ) )
2295 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2296 geomProperty.appendChild( mDoc.createTextNode( mGeometryName ) );
2298 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":BBOX" );
2299 funcElem.appendChild( geomProperty );
2300 funcElem.appendChild( elemBox );
2305 mErrorMessage = QObject::tr(
"<BBOX> is currently supported only in form: bbox($geometry, geomFromWKT('…'))" );
2306 return QDomElement();
2310 if ( isBinarySpatialOperator( fd->
name() ) )
2312 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2313 Q_ASSERT( argNodes.count() == 2 );
2316 if ( isGeometryColumn( argNodes[0] ) )
2317 otherNode = argNodes[1];
2318 else if ( isGeometryColumn( argNodes[1] ) )
2319 otherNode = argNodes[0];
2322 mErrorMessage = QObject::tr(
"Unable to translate spatial operator: at least one must refer to geometry." );
2323 return QDomElement();
2326 QDomElement otherGeomElem;
2331 mErrorMessage = QObject::tr(
"spatial operator: the other operator must be a geometry constructor function" );
2332 return QDomElement();
2337 if ( otherFnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2342 mErrorMessage = QObject::tr(
"geom_from_wkt: argument must be string literal" );
2343 return QDomElement();
2348 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2351 else if ( otherFnDef->
name() == QLatin1String(
"geom_from_gml" ) )
2356 mErrorMessage = QObject::tr(
"geom_from_gml: argument must be string literal" );
2357 return QDomElement();
2360 QDomDocument geomDoc;
2362 if ( !geomDoc.setContent( gml,
true ) )
2364 mErrorMessage = QObject::tr(
"geom_from_gml: unable to parse XML" );
2365 return QDomElement();
2368 const QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(),
true );
2369 otherGeomElem = geomNode.toElement();
2373 mErrorMessage = QObject::tr(
"spatial operator: unknown geometry constructor function" );
2374 return QDomElement();
2379 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + tagNameForSpatialOperator( fd->
name() ) );
2380 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2381 geomProperty.appendChild( mDoc.createTextNode( mGeometryName ) );
2382 funcElem.appendChild( geomProperty );
2383 funcElem.appendChild( otherGeomElem );
2387 if ( fd->
isStatic( node, expression, context ) )
2389 const QVariant result = fd->
run( node->
args(), context, expression, node );
2391 return expressionLiteralToOgcFilter( &literal, expression, context );
2396 mErrorMessage = QObject::tr(
"Special columns/constants are not supported." );
2397 return QDomElement();
2401 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
2402 funcElem.setAttribute( QStringLiteral(
"name" ), fd->
name() );
2403 const auto constList = node->
args()->
list();
2407 if ( !mErrorMessage.isEmpty() )
2408 return QDomElement();
2410 funcElem.appendChild( childElem );
2421 const QList<QgsOgcUtils::LayerProperties> &layerProperties,
2422 bool honourAxisOrientation,
2423 bool invertAxisOrientation,
2424 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename )
2427 , mGMLVersion( gmlVersion )
2428 , mFilterVersion( filterVersion )
2429 , mLayerProperties( layerProperties )
2430 , mHonourAxisOrientation( honourAxisOrientation )
2431 , mInvertAxisOrientation( invertAxisOrientation )
2432 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
2433 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
2435 , mMapUnprefixedTypenameToPrefixedTypename( mapUnprefixedTypenameToPrefixedTypename )
2461 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
2462 return QDomElement();
2471 if ( !mErrorMessage.isEmpty() )
2472 return QDomElement();
2475 switch ( node->
op() )
2478 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2483 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
2484 mDoc.removeChild( operandElem );
2488 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
2489 return QDomElement();
2493 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
2494 uoElem.appendChild( operandElem );
2499 return QDomElement();
2509 if ( !mErrorMessage.isEmpty() )
2510 return QDomElement();
2520 if ( rightLit->
value().isNull() )
2523 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2524 elem.appendChild( leftElem );
2528 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2529 notElem.appendChild( elem );
2543 if ( !mErrorMessage.isEmpty() )
2544 return QDomElement();
2549 opText = QStringLiteral(
"Or" );
2551 opText = QStringLiteral(
"And" );
2553 opText = QStringLiteral(
"PropertyIsEqualTo" );
2555 opText = QStringLiteral(
"PropertyIsNotEqualTo" );
2557 opText = QStringLiteral(
"PropertyIsLessThanOrEqualTo" );
2559 opText = QStringLiteral(
"PropertyIsGreaterThanOrEqualTo" );
2561 opText = QStringLiteral(
"PropertyIsLessThan" );
2563 opText = QStringLiteral(
"PropertyIsGreaterThan" );
2565 opText = QStringLiteral(
"PropertyIsLike" );
2567 opText = QStringLiteral(
"PropertyIsLike" );
2569 if ( opText.isEmpty() )
2573 return QDomElement();
2576 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2581 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2584 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2585 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2587 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2589 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2592 boElem.appendChild( leftElem );
2593 boElem.appendChild( rightElem );
2601 switch ( node->
value().type() )
2604 value = QString::number( node->
value().toInt() );
2606 case QVariant::LongLong:
2607 value = QString::number( node->
value().toLongLong() );
2609 case QVariant::Double:
2612 case QVariant::String:
2613 value = node->
value().toString();
2617 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2618 return QDomElement();
2621 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2622 litElem.appendChild( mDoc.createTextNode( value ) );
2629 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2630 if ( node->
tableName().isEmpty() || mLayerProperties.size() == 1 )
2632 if ( mLayerProperties.size() == 1 && !mLayerProperties[0].mNamespacePrefix.isEmpty() )
2633 propElem.appendChild( mDoc.createTextNode(
2634 mLayerProperties[0].mNamespacePrefix + QStringLiteral(
":" ) + node->
name() ) );
2636 propElem.appendChild( mDoc.createTextNode( node->
name() ) );
2640 QString tableName( mMapTableAliasToNames[node->
tableName()] );
2641 if ( mMapUnprefixedTypenameToPrefixedTypename.contains( tableName ) )
2642 tableName = mMapUnprefixedTypenameToPrefixedTypename[tableName];
2643 propElem.appendChild( mDoc.createTextNode( tableName +
"/" + node->
name() ) );
2650 if ( node->
list()->
list().size() == 1 )
2653 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2656 const auto constList = node->
list()->
list();
2660 if ( !mErrorMessage.isEmpty() )
2661 return QDomElement();
2663 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2664 eqElem.appendChild( leftNode.cloneNode() );
2665 eqElem.appendChild( listNode );
2667 orElem.appendChild( eqElem );
2672 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2673 notElem.appendChild( orElem );
2682 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsBetween" );
2684 QDomElement lowerBoundary = mDoc.createElement( mFilterPrefix +
":LowerBoundary" );
2686 elem.appendChild( lowerBoundary );
2687 QDomElement upperBoundary = mDoc.createElement( mFilterPrefix +
":UpperBoundary" );
2689 elem.appendChild( upperBoundary );
2693 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2694 notElem.appendChild( elem );
2701 static QString mapBinarySpatialToOgc(
const QString &name )
2703 QString nameCompare( name );
2704 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 2)
2705 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2706 nameCompare = name.mid( 3 );
2708 if ( name.size() > 3 && QStringView {name}.mid( 0, 3 ).toString().compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2709 nameCompare = name.mid( 3 );
2711 QStringList spatialOps;
2712 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
2713 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
2714 const auto constSpatialOps = spatialOps;
2715 for ( QString op : constSpatialOps )
2717 if ( nameCompare.compare( op, Qt::CaseInsensitive ) == 0 )
2723 static QString mapTernarySpatialToOgc(
const QString &name )
2725 QString nameCompare( name );
2726 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 2)
2727 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2728 nameCompare = name.mid( 3 );
2730 if ( name.size() > 3 && QStringView {name}.mid( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2731 nameCompare = name.mid( 3 );
2733 if ( nameCompare.compare( QLatin1String(
"DWithin" ), Qt::CaseInsensitive ) == 0 )
2734 return QStringLiteral(
"DWithin" );
2735 if ( nameCompare.compare( QLatin1String(
"Beyond" ), Qt::CaseInsensitive ) == 0 )
2736 return QStringLiteral(
"Beyond" );
2740 QString QgsOgcUtilsSQLStatementToFilter::getGeometryColumnSRSName(
const QgsSQLStatement::Node *node )
2748 const auto constMLayerProperties = mLayerProperties;
2751 if ( prop.mName.compare( mMapTableAliasToNames[col->
tableName()], Qt::CaseInsensitive ) == 0 &&
2752 prop.mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2754 return prop.mSRSName;
2758 if ( !mLayerProperties.empty() &&
2759 mLayerProperties.at( 0 ).mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2761 return mLayerProperties.at( 0 ).mSRSName;
2767 QList<QgsSQLStatement::Node *> args,
2768 bool lastArgIsSRSName,
2770 bool &axisInversion )
2773 axisInversion = mInvertAxisOrientation;
2775 if ( lastArgIsSRSName )
2780 mErrorMessage = QObject::tr(
"%1: Last argument must be string or integer literal" ).arg( mainNode->
name() );
2784 if ( lit->
value().type() == QVariant::Int )
2788 srsName =
"EPSG:" + QString::number( lit->
value().toInt() );
2792 srsName =
"urn:ogc:def:crs:EPSG::" + QString::number( lit->
value().toInt() );
2798 if (
srsName.startsWith( QLatin1String(
"EPSG:" ), Qt::CaseInsensitive ) )
2810 axisInversion = !axisInversion;
2820 if ( node->
name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 )
2822 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2823 if ( args.size() != 1 && args.size() != 2 )
2825 mErrorMessage = QObject::tr(
"Function %1 should have 1 or 2 arguments" ).arg( node->
name() );
2826 return QDomElement();
2832 mErrorMessage = QObject::tr(
"%1: First argument must be string literal" ).arg( node->
name() );
2833 return QDomElement();
2838 if ( ! processSRSName( node, args, args.size() == 2,
srsName, axisInversion ) )
2840 return QDomElement();
2846 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2848 if ( geomElem.isNull() )
2850 mErrorMessage = QObject::tr(
"%1: invalid WKT" ).arg( node->
name() );
2851 return QDomElement();
2858 if ( node->
name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 )
2860 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2861 if ( args.size() != 4 && args.size() != 5 )
2863 mErrorMessage = QObject::tr(
"Function %1 should have 4 or 5 arguments" ).arg( node->
name() );
2864 return QDomElement();
2869 for (
int i = 0; i < 4; i++ )
2874 mErrorMessage = QObject::tr(
"%1: Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2875 return QDomElement();
2879 if ( lit->
value().type() == QVariant::Int )
2880 val = lit->
value().toInt();
2881 else if ( lit->
value().type() == QVariant::LongLong )
2882 val = lit->
value().toLongLong();
2883 else if ( lit->
value().type() == QVariant::Double )
2884 val = lit->
value().toDouble();
2887 mErrorMessage = QObject::tr(
"%1 Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2888 return QDomElement();
2902 if ( ! processSRSName( node, args, args.size() == 5,
srsName, axisInversion ) )
2904 return QDomElement();
2915 if ( node->
name().compare( QLatin1String(
"ST_GeomFromGML" ), Qt::CaseInsensitive ) == 0 )
2917 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2918 if ( args.size() != 1 )
2920 mErrorMessage = QObject::tr(
"Function %1 should have 1 argument" ).arg( node->
name() );
2921 return QDomElement();
2927 mErrorMessage = QObject::tr(
"%1: Argument must be string literal" ).arg( node->
name() );
2928 return QDomElement();
2931 QDomDocument geomDoc;
2933 if ( !geomDoc.setContent( gml,
true ) )
2935 mErrorMessage = QObject::tr(
"ST_GeomFromGML: unable to parse XML" );
2936 return QDomElement();
2939 const QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(),
true );
2941 return geomNode.toElement();
2945 QString ogcName( mapBinarySpatialToOgc( node->
name() ) );
2946 if ( !ogcName.isEmpty() )
2948 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2949 if ( args.size() != 2 )
2951 mErrorMessage = QObject::tr(
"Function %1 should have 2 arguments" ).arg( node->
name() );
2952 return QDomElement();
2955 for (
int i = 0; i < 2; i ++ )
2958 (
static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
2959 static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
2961 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
2968 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + ogcName );
2969 const auto constArgs = args;
2973 if ( !mErrorMessage.isEmpty() )
2975 mCurrentSRSName.clear();
2976 return QDomElement();
2979 funcElem.appendChild( childElem );
2982 mCurrentSRSName.clear();
2986 ogcName = mapTernarySpatialToOgc( node->
name() );
2987 if ( !ogcName.isEmpty() )
2989 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2990 if ( args.size() != 3 )
2992 mErrorMessage = QObject::tr(
"Function %1 should have 3 arguments" ).arg( node->
name() );
2993 return QDomElement();
2996 for (
int i = 0; i < 2; i ++ )
2999 (
static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
3000 static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
3002 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
3007 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + node->
name().mid( 3 ) );
3008 for (
int i = 0; i < 2; i++ )
3010 const QDomElement childElem =
toOgcFilter( args[i] );
3011 if ( !mErrorMessage.isEmpty() )
3013 mCurrentSRSName.clear();
3014 return QDomElement();
3017 funcElem.appendChild( childElem );
3019 mCurrentSRSName.clear();
3024 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() );
3025 return QDomElement();
3028 if ( lit->
value().isNull() )
3030 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() );
3031 return QDomElement();
3034 QString unit( QStringLiteral(
"m" ) );
3035 switch ( lit->
value().type() )
3038 distance = QString::number( lit->
value().toInt() );
3040 case QVariant::LongLong:
3041 distance = QString::number( lit->
value().toLongLong() );
3043 case QVariant::Double:
3046 case QVariant::String:
3048 distance = lit->
value().toString();
3049 for (
int i = 0; i < distance.size(); i++ )
3051 if ( !( ( distance[i] >=
'0' && distance[i] <=
'9' ) || distance[i] ==
'-' || distance[i] ==
'.' || distance[i] ==
'e' || distance[i] ==
'E' ) )
3053 unit = distance.mid( i ).trimmed();
3054 distance = distance.mid( 0, i );
3062 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( lit->
value().type() );
3063 return QDomElement();
3066 QDomElement distanceElem = mDoc.createElement( mFilterPrefix +
":Distance" );
3068 distanceElem.setAttribute( QStringLiteral(
"uom" ), unit );
3070 distanceElem.setAttribute( QStringLiteral(
"unit" ), unit );
3071 distanceElem.appendChild( mDoc.createTextNode( distance ) );
3072 funcElem.appendChild( distanceElem );
3077 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
3078 funcElem.setAttribute( QStringLiteral(
"name" ), node->
name() );
3079 const auto constList = node->
args()->
list();
3083 if ( !mErrorMessage.isEmpty() )
3084 return QDomElement();
3086 funcElem.appendChild( childElem );
3092 const QString &leftTable )
3100 QList<QDomElement> listElem;
3102 for (
const QString &columnName : constUsingColumns )
3104 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
3105 QDomElement propElem1 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3106 propElem1.appendChild( mDoc.createTextNode( leftTable +
"/" + columnName ) );
3107 eqElem.appendChild( propElem1 );
3108 QDomElement propElem2 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3109 propElem2.appendChild( mDoc.createTextNode( node->
tableDef()->
name() +
"/" + columnName ) );
3110 eqElem.appendChild( propElem2 );
3111 listElem.append( eqElem );
3114 if ( listElem.size() == 1 )
3118 else if ( listElem.size() > 1 )
3120 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3121 const auto constListElem = listElem;
3122 for (
const QDomElement &elem : constListElem )
3124 andElem.appendChild( elem );
3129 return QDomElement();
3134 if ( node->
alias().isEmpty() )
3136 mMapTableAliasToNames[ node->
name()] = node->
name();
3140 mMapTableAliasToNames[ node->
alias()] = node->
name();
3146 QList<QDomElement> listElem;
3149 ( node->
tables().size() != 1 || !node->
joins().empty() ) )
3151 mErrorMessage = QObject::tr(
"Joins are only supported with WFS 2.0" );
3152 return QDomElement();
3156 const auto constTables = node->
tables();
3161 const auto constJoins = node->
joins();
3164 visit( join->tableDef() );
3168 const QList< QgsSQLStatement::NodeTableDef *> nodeTables = node->
tables();
3169 QString leftTable = nodeTables.at( nodeTables.length() - 1 )->name();
3172 const QDomElement joinElem =
toOgcFilter( join, leftTable );
3173 if ( !mErrorMessage.isEmpty() )
3174 return QDomElement();
3175 listElem.append( joinElem );
3176 leftTable = join->tableDef()->name();
3180 if ( node->
where() )
3183 if ( !mErrorMessage.isEmpty() )
3184 return QDomElement();
3185 listElem.append( whereElem );
3189 if ( listElem.size() == 1 )
3193 else if ( listElem.size() > 1 )
3195 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3196 const auto constListElem = listElem;
3197 for (
const QDomElement &elem : constListElem )
3199 andElem.appendChild( elem );
3204 return QDomElement();
3210 mPropertyName = QStringLiteral(
"PropertyName" );
3211 mPrefix = QStringLiteral(
"ogc" );
3215 mPropertyName = QStringLiteral(
"ValueReference" );
3216 mPrefix = QStringLiteral(
"fes" );
3222 if ( element.isNull() )
3226 if ( isBinaryOperator( element.tagName() ) )
3232 if ( isSpatialOperator( element.tagName() ) )
3238 if ( element.tagName() == QLatin1String(
"Not" ) )
3242 else if ( element.tagName() == QLatin1String(
"PropertyIsNull" ) )
3246 else if ( element.tagName() == QLatin1String(
"Literal" ) )
3250 else if ( element.tagName() == QLatin1String(
"Function" ) )
3254 else if ( element.tagName() == mPropertyName )
3258 else if ( element.tagName() == QLatin1String(
"PropertyIsBetween" ) )
3263 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() );
3269 if ( element.isNull() )
3272 int op = binaryOperatorFromTagName( element.tagName() );
3275 mErrorMessage = QObject::tr(
"'%1' binary operator not supported." ).arg( element.tagName() );
3279 if ( op ==
QgsExpressionNodeBinaryOperator::boLike && element.hasAttribute( QStringLiteral(
"matchCase" ) ) && element.attribute( QStringLiteral(
"matchCase" ) ) == QLatin1String(
"false" ) )
3284 QDomElement operandElem = element.firstChildElement();
3289 mErrorMessage = QObject::tr(
"invalid left operand for '%1' binary operator" ).arg( element.tagName() );
3293 const std::unique_ptr<QgsExpressionNode> leftOp( expr->clone() );
3294 for ( operandElem = operandElem.nextSiblingElement(); !operandElem.isNull(); operandElem = operandElem.nextSiblingElement() )
3299 mErrorMessage = QObject::tr(
"invalid right operand for '%1' binary operator" ).arg( element.tagName() );
3306 if ( element.hasAttribute( QStringLiteral(
"wildCard" ) ) )
3308 wildCard = element.attribute( QStringLiteral(
"wildCard" ) );
3311 if ( element.hasAttribute( QStringLiteral(
"singleChar" ) ) )
3313 singleChar = element.attribute( QStringLiteral(
"singleChar" ) );
3315 QString escape = QStringLiteral(
"\\" );
3316 if ( element.hasAttribute( QStringLiteral(
"escape" ) ) )
3318 escape = element.attribute( QStringLiteral(
"escape" ) );
3320 if ( element.hasAttribute( QStringLiteral(
"escapeChar" ) ) )
3322 escape = element.attribute( QStringLiteral(
"escapeChar" ) );
3326 if ( !wildCard.isEmpty() && wildCard != QLatin1String(
"%" ) )
3328 oprValue.replace(
'%', QLatin1String(
"\\%" ) );
3329 if ( oprValue.startsWith( wildCard ) )
3331 oprValue.replace( 0, 1, QStringLiteral(
"%" ) );
3334 QRegularExpressionMatch match = rx.match( oprValue );
3336 while ( match.hasMatch() )
3338 pos = match.capturedStart();
3339 oprValue.replace( pos + 1, 1, QStringLiteral(
"%" ) );
3341 match = rx.match( oprValue, pos );
3343 oprValue.replace( escape + wildCard, wildCard );
3345 if ( !singleChar.isEmpty() && singleChar != QLatin1String(
"_" ) )
3347 oprValue.replace(
'_', QLatin1String(
"\\_" ) );
3348 if ( oprValue.startsWith( singleChar ) )
3350 oprValue.replace( 0, 1, QStringLiteral(
"_" ) );
3353 QRegularExpressionMatch match = rx.match( oprValue );
3355 while ( match.hasMatch() )
3357 pos = match.capturedStart();
3358 oprValue.replace( pos + 1, 1, QStringLiteral(
"_" ) );
3360 match = rx.match( oprValue, pos );
3362 oprValue.replace( escape + singleChar, singleChar );
3364 if ( !escape.isEmpty() && escape != QLatin1String(
"\\" ) )
3366 oprValue.replace( escape + escape, escape );
3374 if ( expr == leftOp )
3376 mErrorMessage = QObject::tr(
"only one operand for '%1' binary operator" ).arg( element.tagName() );
3390 QDomElement childElem = element.firstChildElement();
3392 while ( !childElem.isNull() && gml2Str.isEmpty() )
3394 if ( childElem.tagName() != mPropertyName )
3396 QTextStream gml2Stream( &gml2Str );
3397 childElem.save( gml2Stream, 0 );
3399 childElem = childElem.nextSiblingElement();
3401 if ( !gml2Str.isEmpty() )
3407 mErrorMessage = QObject::tr(
"No OGC Geometry found" );
3420 if ( element.isNull() || element.tagName() != mPropertyName )
3422 mErrorMessage = QObject::tr(
"%1:PropertyName expected, got %2" ).arg( mPrefix, element.tagName() );
3431 if ( element.isNull() || element.tagName() != QLatin1String(
"Literal" ) )
3433 mErrorMessage = QObject::tr(
"%1:Literal expected, got %2" ).arg( mPrefix, element.tagName() );
3437 std::unique_ptr<QgsExpressionNode> root;
3440 QDomNode childNode = element.firstChild();
3441 while ( !childNode.isNull() )
3443 std::unique_ptr<QgsExpressionNode> operand;
3445 if ( childNode.nodeType() == QDomNode::ElementNode )
3448 const QDomElement operandElem = childNode.toElement();
3452 mErrorMessage = QObject::tr(
"'%1' is an invalid or not supported content for %2:Literal" ).arg( operandElem.tagName(), mPrefix );
3459 QVariant value = childNode.nodeValue();
3461 bool converted =
false;
3466 QDomElement propertyNameElement = element.previousSiblingElement( mPropertyName );
3467 if ( propertyNameElement.isNull() || propertyNameElement.tagName() != mPropertyName )
3469 propertyNameElement = element.nextSiblingElement( mPropertyName );
3471 if ( !propertyNameElement.isNull() || propertyNameElement.tagName() == mPropertyName )
3473 const int fieldIndex = mLayer->
fields().
indexOf( propertyNameElement.firstChild().nodeValue() );
3474 if ( fieldIndex != -1 )
3487 const double d = value.toDouble( &ok );
3500 root = std::move( operand );
3507 childNode = childNode.nextSibling();
3511 return root.release();
3518 if ( element.tagName() != QLatin1String(
"Not" ) )
3521 const QDomElement operandElem = element.firstChildElement();
3525 mErrorMessage = QObject::tr(
"invalid operand for '%1' unary operator" ).arg( element.tagName() );
3535 if ( element.tagName() != QLatin1String(
"PropertyIsNull" ) )
3540 const QDomElement operandElem = element.firstChildElement();
3551 if ( element.isNull() || element.tagName() != QLatin1String(
"Function" ) )
3553 mErrorMessage = QObject::tr(
"%1:Function expected, got %2" ).arg( mPrefix, element.tagName() );
3561 if ( element.attribute( QStringLiteral(
"name" ) ) != funcDef->
name() )
3566 QDomElement operandElem = element.firstChildElement();
3567 while ( !operandElem.isNull() )
3574 args->append( op.release() );
3576 operandElem = operandElem.nextSiblingElement();
3588 std::unique_ptr<QgsExpressionNode> operand;
3589 std::unique_ptr<QgsExpressionNode> lowerBound;
3590 std::unique_ptr<QgsExpressionNode> upperBound;
3592 QDomElement operandElem = element.firstChildElement();
3593 while ( !operandElem.isNull() )
3595 if ( operandElem.tagName() == QLatin1String(
"LowerBoundary" ) )
3597 const QDomElement lowerBoundElem = operandElem.firstChildElement();
3600 else if ( operandElem.tagName() == QLatin1String(
"UpperBoundary" ) )
3602 const QDomElement upperBoundElem = operandElem.firstChildElement();
3611 if ( operand && lowerBound && upperBound )
3614 operandElem = operandElem.nextSiblingElement();
3617 if ( !operand || !lowerBound || !upperBound )
3619 mErrorMessage = QObject::tr(
"missing some required sub-elements in %1:PropertyIsBetween" ).arg( mPrefix );
3630 return mErrorMessage;
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.
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.)
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
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[]
static QString qRegExpEscape(const QString &string)
Returns an escaped string matching the behavior of QRegExp::escape.
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)
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