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" )
47#define SE_NAMESPACE QStringLiteral( "http://www.opengis.net/se" )
52 const QString &namespacePrefix,
53 const QString &namespaceURI,
56 bool honourAxisOrientation,
57 bool invertAxisOrientation )
60 , mGMLVersion( gmlVersion )
61 , mFilterVersion( filterVersion )
62 , mNamespacePrefix( namespacePrefix )
63 , mNamespaceURI( namespaceURI )
66 , mInvertAxisOrientation( invertAxisOrientation )
67 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
68 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
72 if ( !mSrsName.isEmpty() )
78 mInvertAxisOrientation = !mInvertAxisOrientation;
85 QDomElement geometryTypeElement = geometryNode.toElement();
86 QString geomType = geometryTypeElement.tagName();
89 if ( !( geomType == QLatin1String(
"Point" ) || geomType == QLatin1String(
"LineString" ) || geomType == QLatin1String(
"Polygon" ) ||
90 geomType == QLatin1String(
"MultiPoint" ) || geomType == QLatin1String(
"MultiLineString" ) || geomType == QLatin1String(
"MultiPolygon" ) ||
91 geomType == QLatin1String(
"Box" ) || geomType == QLatin1String(
"Envelope" ) ) )
93 const QDomNode geometryChild = geometryNode.firstChild();
94 if ( geometryChild.isNull() )
98 geometryTypeElement = geometryChild.toElement();
99 geomType = geometryTypeElement.tagName();
102 if ( !( geomType == QLatin1String(
"Point" ) || geomType == QLatin1String(
"LineString" ) || geomType == QLatin1String(
"Polygon" ) ||
103 geomType == QLatin1String(
"MultiPoint" ) || geomType == QLatin1String(
"MultiLineString" ) || geomType == QLatin1String(
"MultiPolygon" ) ||
104 geomType == QLatin1String(
"Box" ) || geomType == QLatin1String(
"Envelope" ) ) )
107 if ( geomType == QLatin1String(
"Point" ) )
109 geometry = geometryFromGMLPoint( geometryTypeElement );
111 else if ( geomType == QLatin1String(
"LineString" ) )
113 geometry = geometryFromGMLLineString( geometryTypeElement );
115 else if ( geomType == QLatin1String(
"Polygon" ) )
117 geometry = geometryFromGMLPolygon( geometryTypeElement );
119 else if ( geomType == QLatin1String(
"MultiPoint" ) )
121 geometry = geometryFromGMLMultiPoint( geometryTypeElement );
123 else if ( geomType == QLatin1String(
"MultiLineString" ) )
125 geometry = geometryFromGMLMultiLineString( geometryTypeElement );
127 else if ( geomType == QLatin1String(
"MultiPolygon" ) )
129 geometry = geometryFromGMLMultiPolygon( geometryTypeElement );
131 else if ( geomType == QLatin1String(
"Box" ) )
135 else if ( geomType == QLatin1String(
"Envelope" ) )
149 if ( geometryTypeElement.hasAttribute( QStringLiteral(
"srsName" ) ) )
151 QString
srsName { geometryTypeElement.attribute( QStringLiteral(
"srsName" ) ) };
154 const bool ignoreAxisOrientation {
srsName.startsWith( QLatin1String(
"http://www.opengis.net/gml/srs/" ) ) ||
srsName.startsWith( QLatin1String(
"EPSG:" ) ) };
158 if (
srsName.startsWith( QLatin1String(
"http://www.opengis.net/gml/srs/" ) ) )
160 const auto parts {
srsName.split( QRegularExpression( QStringLiteral( R
"raw(/|#|\.)raw" ) ) ) };
161 if ( parts.length() == 10 )
163 srsName = QStringLiteral(
"http://www.opengis.net/def/crs/%1/0/%2" ).arg( parts[ 7 ].toUpper(), parts[ 9 ] );
196 const QString xml = QStringLiteral(
"<tmp xmlns=\"%1\" xmlns:gml=\"%1\">%2</tmp>" ).arg(
GML_NAMESPACE, xmlString );
198 if ( !doc.setContent( xml,
true ) )
201 return geometryFromGML( doc.documentElement().firstChildElement(), context );
205QgsGeometry QgsOgcUtils::geometryFromGMLPoint(
const QDomElement &geometryElement )
209 const QDomNodeList coordList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
210 if ( !coordList.isEmpty() )
212 const QDomElement coordElement = coordList.at( 0 ).toElement();
213 if ( readGMLCoordinates( pointCoordinate, coordElement ) != 0 )
220 const QDomNodeList posList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pos" ) );
221 if ( posList.size() < 1 )
225 const QDomElement posElement = posList.at( 0 ).toElement();
226 if ( readGMLPositions( pointCoordinate, posElement ) != 0 )
232 if ( pointCoordinate.empty() )
237 QgsPolylineXY::const_iterator point_it = pointCoordinate.constBegin();
238 char e = htonl( 1 ) != 1;
239 double x = point_it->x();
240 double y = point_it->y();
241 const int size = 1 +
sizeof( int ) + 2 *
sizeof(
double );
244 unsigned char *wkb =
new unsigned char[size];
247 memcpy( &( wkb )[wkbPosition], &e, 1 );
249 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
250 wkbPosition +=
sizeof( int );
251 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
252 wkbPosition +=
sizeof( double );
253 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
260QgsGeometry QgsOgcUtils::geometryFromGMLLineString(
const QDomElement &geometryElement )
264 const QDomNodeList coordList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
265 if ( !coordList.isEmpty() )
267 const QDomElement coordElement = coordList.at( 0 ).toElement();
268 if ( readGMLCoordinates( lineCoordinates, coordElement ) != 0 )
275 const QDomNodeList posList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
276 if ( posList.size() < 1 )
280 const QDomElement posElement = posList.at( 0 ).toElement();
281 if ( readGMLPositions( lineCoordinates, posElement ) != 0 )
287 char e = htonl( 1 ) != 1;
288 const int size = 1 + 2 *
sizeof( int ) + lineCoordinates.size() * 2 *
sizeof( double );
291 unsigned char *wkb =
new unsigned char[size];
295 int nPoints = lineCoordinates.size();
298 memcpy( &( wkb )[wkbPosition], &e, 1 );
300 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
301 wkbPosition +=
sizeof( int );
302 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
303 wkbPosition +=
sizeof( int );
305 QgsPolylineXY::const_iterator iter;
306 for ( iter = lineCoordinates.constBegin(); iter != lineCoordinates.constEnd(); ++iter )
310 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
311 wkbPosition +=
sizeof( double );
312 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
313 wkbPosition +=
sizeof( double );
321QgsGeometry QgsOgcUtils::geometryFromGMLPolygon(
const QDomElement &geometryElement )
328 const QDomNodeList outerBoundaryList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"outerBoundaryIs" ) );
329 if ( !outerBoundaryList.isEmpty() )
331 QDomElement coordinatesElement = outerBoundaryList.at( 0 ).firstChild().firstChild().toElement();
332 if ( coordinatesElement.isNull() )
336 if ( readGMLCoordinates( exteriorPointList, coordinatesElement ) != 0 )
340 ringCoordinates.push_back( exteriorPointList );
343 const QDomNodeList innerBoundaryList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"innerBoundaryIs" ) );
344 for (
int i = 0; i < innerBoundaryList.size(); ++i )
347 coordinatesElement = innerBoundaryList.at( i ).firstChild().firstChild().toElement();
348 if ( coordinatesElement.isNull() )
352 if ( readGMLCoordinates( interiorPointList, coordinatesElement ) != 0 )
356 ringCoordinates.push_back( interiorPointList );
362 const QDomNodeList exteriorList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"exterior" ) );
363 if ( exteriorList.size() < 1 )
367 const QDomElement posElement = exteriorList.at( 0 ).firstChild().firstChild().toElement();
368 if ( posElement.isNull() )
372 if ( readGMLPositions( exteriorPointList, posElement ) != 0 )
376 ringCoordinates.push_back( exteriorPointList );
379 const QDomNodeList interiorList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"interior" ) );
380 for (
int i = 0; i < interiorList.size(); ++i )
383 const QDomElement posElement = interiorList.at( i ).firstChild().firstChild().toElement();
384 if ( posElement.isNull() )
389 if ( readGMLPositions( interiorPointList, posElement ) )
393 ringCoordinates.push_back( interiorPointList );
398 int nrings = ringCoordinates.size();
403 for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
405 npoints += it->size();
407 const int size = 1 + 2 *
sizeof( int ) + nrings *
sizeof(
int ) + 2 * npoints *
sizeof( double );
410 unsigned char *wkb =
new unsigned char[size];
413 char e = htonl( 1 ) != 1;
415 int nPointsInRing = 0;
419 memcpy( &( wkb )[wkbPosition], &e, 1 );
421 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
422 wkbPosition +=
sizeof( int );
423 memcpy( &( wkb )[wkbPosition], &nrings,
sizeof(
int ) );
424 wkbPosition +=
sizeof( int );
425 for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
427 nPointsInRing = it->size();
428 memcpy( &( wkb )[wkbPosition], &nPointsInRing,
sizeof(
int ) );
429 wkbPosition +=
sizeof( int );
431 QgsPolylineXY::const_iterator iter;
432 for ( iter = it->begin(); iter != it->end(); ++iter )
437 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
438 wkbPosition +=
sizeof( double );
439 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
440 wkbPosition +=
sizeof( double );
449QgsGeometry QgsOgcUtils::geometryFromGMLMultiPoint(
const QDomElement &geometryElement )
453 const QDomNodeList pointMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pointMember" ) );
454 if ( pointMemberList.size() < 1 )
458 QDomNodeList pointNodeList;
460 QDomNodeList coordinatesList;
461 QDomNodeList posList;
462 for (
int i = 0; i < pointMemberList.size(); ++i )
465 pointNodeList = pointMemberList.at( i ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"Point" ) );
466 if ( pointNodeList.size() < 1 )
471 coordinatesList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
472 if ( !coordinatesList.isEmpty() )
474 currentPoint.clear();
475 if ( readGMLCoordinates( currentPoint, coordinatesList.at( 0 ).toElement() ) != 0 )
479 if ( currentPoint.empty() )
483 pointList.push_back( ( *currentPoint.begin() ) );
489 posList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pos" ) );
490 if ( posList.size() < 1 )
494 currentPoint.clear();
495 if ( readGMLPositions( currentPoint, posList.at( 0 ).toElement() ) != 0 )
499 if ( currentPoint.empty() )
503 pointList.push_back( ( *currentPoint.begin() ) );
507 int nPoints = pointList.size();
512 const int size = 1 + 2 *
sizeof( int ) + pointList.size() * ( 2 *
sizeof( double ) + 1 +
sizeof(
int ) );
515 unsigned char *wkb =
new unsigned char[size];
518 char e = htonl( 1 ) != 1;
521 memcpy( &( wkb )[wkbPosition], &e, 1 );
523 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
524 wkbPosition +=
sizeof( int );
525 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
526 wkbPosition +=
sizeof( int );
528 for ( QgsPolylineXY::const_iterator it = pointList.constBegin(); it != pointList.constEnd(); ++it )
530 memcpy( &( wkb )[wkbPosition], &e, 1 );
532 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
533 wkbPosition +=
sizeof( int );
535 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
536 wkbPosition +=
sizeof( double );
538 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
539 wkbPosition +=
sizeof( double );
547QgsGeometry QgsOgcUtils::geometryFromGMLMultiLineString(
const QDomElement &geometryElement )
558 QList< QgsPolylineXY > lineCoordinates;
559 QDomElement currentLineStringElement;
560 QDomNodeList currentCoordList;
561 QDomNodeList currentPosList;
563 const QDomNodeList lineStringMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"lineStringMember" ) );
564 if ( !lineStringMemberList.isEmpty() )
566 for (
int i = 0; i < lineStringMemberList.size(); ++i )
568 const QDomNodeList lineStringNodeList = lineStringMemberList.at( i ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LineString" ) );
569 if ( lineStringNodeList.size() < 1 )
573 currentLineStringElement = lineStringNodeList.at( 0 ).toElement();
574 currentCoordList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
575 if ( !currentCoordList.isEmpty() )
578 if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
582 lineCoordinates.push_back( currentPointList );
586 currentPosList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
587 if ( currentPosList.size() < 1 )
592 if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
596 lineCoordinates.push_back( currentPointList );
602 const QDomNodeList lineStringList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LineString" ) );
603 if ( !lineStringList.isEmpty() )
605 for (
int i = 0; i < lineStringList.size(); ++i )
607 currentLineStringElement = lineStringList.at( i ).toElement();
608 currentCoordList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
609 if ( !currentCoordList.isEmpty() )
612 if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
616 lineCoordinates.push_back( currentPointList );
621 currentPosList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
622 if ( currentPosList.size() < 1 )
627 if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
631 lineCoordinates.push_back( currentPointList );
641 int nLines = lineCoordinates.size();
646 int size = ( lineCoordinates.size() + 1 ) * ( 1 + 2 *
sizeof(
int ) );
647 for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
649 size += it->size() * 2 *
sizeof( double );
653 unsigned char *wkb =
new unsigned char[size];
656 char e = htonl( 1 ) != 1;
660 memcpy( &( wkb )[wkbPosition], &e, 1 );
662 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
663 wkbPosition +=
sizeof( int );
664 memcpy( &( wkb )[wkbPosition], &nLines,
sizeof(
int ) );
665 wkbPosition +=
sizeof( int );
667 for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
669 memcpy( &( wkb )[wkbPosition], &e, 1 );
671 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
672 wkbPosition +=
sizeof( int );
673 nPoints = it->size();
674 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
675 wkbPosition +=
sizeof( int );
676 for ( QgsPolylineXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
681 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
682 wkbPosition +=
sizeof( double );
683 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
684 wkbPosition +=
sizeof( double );
693QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon(
const QDomElement &geometryElement )
697 QDomElement currentPolygonMemberElement;
698 QDomNodeList polygonList;
699 QDomElement currentPolygonElement;
701 QDomNodeList outerBoundaryList;
702 QDomElement currentOuterBoundaryElement;
703 const QDomNodeList innerBoundaryList;
704 QDomElement currentInnerBoundaryElement;
706 QDomNodeList exteriorList;
707 QDomElement currentExteriorElement;
708 QDomElement currentInteriorElement;
709 const QDomNodeList interiorList;
711 QDomNodeList linearRingNodeList;
712 QDomElement currentLinearRingElement;
714 QDomNodeList currentCoordinateList;
715 QDomNodeList currentPosList;
717 const QDomNodeList polygonMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"polygonMember" ) );
719 for (
int i = 0; i < polygonMemberList.size(); ++i )
721 currentPolygonList.resize( 0 );
722 currentPolygonMemberElement = polygonMemberList.at( i ).toElement();
723 polygonList = currentPolygonMemberElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"Polygon" ) );
724 if ( polygonList.size() < 1 )
728 currentPolygonElement = polygonList.at( 0 ).toElement();
731 outerBoundaryList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"outerBoundaryIs" ) );
732 if ( !outerBoundaryList.isEmpty() )
734 currentOuterBoundaryElement = outerBoundaryList.at( 0 ).toElement();
737 linearRingNodeList = currentOuterBoundaryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
738 if ( linearRingNodeList.size() < 1 )
742 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
743 currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
744 if ( currentCoordinateList.size() < 1 )
748 if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
752 currentPolygonList.push_back( ringCoordinates );
755 const QDomNodeList innerBoundaryList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"innerBoundaryIs" ) );
756 for (
int j = 0; j < innerBoundaryList.size(); ++j )
759 currentInnerBoundaryElement = innerBoundaryList.at( j ).toElement();
760 linearRingNodeList = currentInnerBoundaryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
761 if ( linearRingNodeList.size() < 1 )
765 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
766 currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
767 if ( currentCoordinateList.size() < 1 )
771 if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
775 currentPolygonList.push_back( ringCoordinates );
781 exteriorList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"exterior" ) );
782 if ( exteriorList.size() < 1 )
787 currentExteriorElement = exteriorList.at( 0 ).toElement();
790 linearRingNodeList = currentExteriorElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
791 if ( linearRingNodeList.size() < 1 )
795 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
796 currentPosList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
797 if ( currentPosList.size() < 1 )
801 if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
805 currentPolygonList.push_back( ringPositions );
808 const QDomNodeList interiorList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"interior" ) );
809 for (
int j = 0; j < interiorList.size(); ++j )
812 currentInteriorElement = interiorList.at( j ).toElement();
813 linearRingNodeList = currentInteriorElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
814 if ( linearRingNodeList.size() < 1 )
818 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
819 currentPosList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
820 if ( currentPosList.size() < 1 )
824 if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
828 currentPolygonList.push_back( ringPositions );
831 multiPolygonPoints.push_back( currentPolygonList );
834 int nPolygons = multiPolygonPoints.size();
838 int size = 1 + 2 *
sizeof( int );
840 for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
842 size += 1 + 2 *
sizeof( int );
843 for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
845 size +=
sizeof( int ) + 2 * iter->size() *
sizeof( double );
850 unsigned char *wkb =
new unsigned char[size];
852 char e = htonl( 1 ) != 1;
859 memcpy( &( wkb )[wkbPosition], &e, 1 );
861 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
862 wkbPosition +=
sizeof( int );
863 memcpy( &( wkb )[wkbPosition], &nPolygons,
sizeof(
int ) );
864 wkbPosition +=
sizeof( int );
868 for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
870 memcpy( &( wkb )[wkbPosition], &e, 1 );
872 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
873 wkbPosition +=
sizeof( int );
875 memcpy( &( wkb )[wkbPosition], &nRings,
sizeof(
int ) );
876 wkbPosition +=
sizeof( int );
877 for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
879 nPointsInRing = iter->size();
880 memcpy( &( wkb )[wkbPosition], &nPointsInRing,
sizeof(
int ) );
881 wkbPosition +=
sizeof( int );
882 for ( QgsPolylineXY::const_iterator iterator = iter->begin(); iterator != iter->end(); ++iterator )
886 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
887 wkbPosition +=
sizeof( double );
888 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
889 wkbPosition +=
sizeof( double );
899QDomElement QgsOgcUtils::filterElement( QDomDocument &doc, GMLVersion gmlVersion, FilterVersion filterVersion,
bool GMLUsed )
901 QDomElement filterElem =
903 doc.createElementNS(
FES_NAMESPACE, QStringLiteral(
"fes:Filter" ) ) :
904 doc.createElementNS(
OGC_NAMESPACE, QStringLiteral(
"ogc:Filter" ) );
908 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:gml" ) );
913 filterElem.setAttributeNode( attr );
919bool QgsOgcUtils::readGMLCoordinates(
QgsPolylineXY &coords,
const QDomElement &elem )
921 QString coordSeparator = QStringLiteral(
"," );
922 QString tupelSeparator = QStringLiteral(
" " );
927 if ( elem.hasAttribute( QStringLiteral(
"cs" ) ) )
929 coordSeparator = elem.attribute( QStringLiteral(
"cs" ) );
931 if ( elem.hasAttribute( QStringLiteral(
"ts" ) ) )
933 tupelSeparator = elem.attribute( QStringLiteral(
"ts" ) );
936#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
937 QStringList tupels = elem.text().split( tupelSeparator, QString::SkipEmptyParts );
939 const QStringList tupels = elem.text().split( tupelSeparator, Qt::SkipEmptyParts );
941 QStringList tuple_coords;
943 bool conversionSuccess;
945 QStringList::const_iterator it;
946 for ( it = tupels.constBegin(); it != tupels.constEnd(); ++it )
948#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
949 tuple_coords = ( *it ).split( coordSeparator, QString::SkipEmptyParts );
951 tuple_coords = ( *it ).split( coordSeparator, Qt::SkipEmptyParts );
953 if ( tuple_coords.size() < 2 )
957 x = tuple_coords.at( 0 ).toDouble( &conversionSuccess );
958 if ( !conversionSuccess )
962 y = tuple_coords.at( 1 ).toDouble( &conversionSuccess );
963 if ( !conversionSuccess )
976 const QDomElement boxElem = boxNode.toElement();
977 if ( boxElem.tagName() != QLatin1String(
"Box" ) )
980 const QDomElement bElem = boxElem.firstChild().toElement();
981 QString coordSeparator = QStringLiteral(
"," );
982 QString tupelSeparator = QStringLiteral(
" " );
983 if ( bElem.hasAttribute( QStringLiteral(
"cs" ) ) )
985 coordSeparator = bElem.attribute( QStringLiteral(
"cs" ) );
987 if ( bElem.hasAttribute( QStringLiteral(
"ts" ) ) )
989 tupelSeparator = bElem.attribute( QStringLiteral(
"ts" ) );
992 const QString bString = bElem.text();
993 bool ok1, ok2, ok3, ok4;
994 const double xmin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 0, 0 ).toDouble( &ok1 );
995 const double ymin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 1, 1 ).toDouble( &ok2 );
996 const double xmax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 0, 0 ).toDouble( &ok3 );
997 const double ymax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 1, 1 ).toDouble( &ok4 );
999 if ( ok1 && ok2 && ok3 && ok4 )
1008bool QgsOgcUtils::readGMLPositions(
QgsPolylineXY &coords,
const QDomElement &elem )
1012#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1013 QStringList pos = elem.text().split(
' ', QString::SkipEmptyParts );
1015 const QStringList pos = elem.text().split(
' ', Qt::SkipEmptyParts );
1018 bool conversionSuccess;
1019 const int posSize = pos.size();
1021 int srsDimension = 2;
1022 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
1024 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
1025 if ( !conversionSuccess )
1030 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1032 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1033 if ( !conversionSuccess )
1039 for (
int i = 0; i < posSize / srsDimension; i++ )
1041 x = pos.at( i * srsDimension ).toDouble( &conversionSuccess );
1042 if ( !conversionSuccess )
1046 y = pos.at( i * srsDimension + 1 ).toDouble( &conversionSuccess );
1047 if ( !conversionSuccess )
1061 const QDomElement envelopeElem = envelopeNode.toElement();
1062 if ( envelopeElem.tagName() != QLatin1String(
"Envelope" ) )
1065 const QDomNodeList lowerCornerList = envelopeElem.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"lowerCorner" ) );
1066 if ( lowerCornerList.size() < 1 )
1069 const QDomNodeList upperCornerList = envelopeElem.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"upperCorner" ) );
1070 if ( upperCornerList.size() < 1 )
1073 bool conversionSuccess;
1074 int srsDimension = 2;
1076 QDomElement elem = lowerCornerList.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 )
1093 QString bString = elem.text();
1095 const double xmin = bString.section(
' ', 0, 0 ).toDouble( &conversionSuccess );
1096 if ( !conversionSuccess )
1098 const double ymin = bString.section(
' ', 1, 1 ).toDouble( &conversionSuccess );
1099 if ( !conversionSuccess )
1102 elem = upperCornerList.at( 0 ).toElement();
1103 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
1105 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
1106 if ( !conversionSuccess )
1111 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1113 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1114 if ( !conversionSuccess )
1120 Q_UNUSED( srsDimension )
1122 bString = elem.text();
1123 const double xmax = bString.section(
' ', 0, 0 ).toDouble( &conversionSuccess );
1124 if ( !conversionSuccess )
1126 const double ymax = bString.section(
' ', 1, 1 ).toDouble( &conversionSuccess );
1127 if ( !conversionSuccess )
1143 bool invertAxisOrientation,
1148 return QDomElement();
1151 QDomElement boxElem = doc.createElement( QStringLiteral(
"gml:Box" ) );
1154 boxElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1156 QDomElement coordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1157 coordElem.setAttribute( QStringLiteral(
"cs" ), QStringLiteral(
"," ) );
1158 coordElem.setAttribute( QStringLiteral(
"ts" ), QStringLiteral(
" " ) );
1160 QString coordString;
1169 const QDomText coordText = doc.createTextNode( coordString );
1170 coordElem.appendChild( coordText );
1171 boxElem.appendChild( coordElem );
1183 bool invertAxisOrientation,
1188 return QDomElement();
1191 QDomElement envElem = doc.createElement( QStringLiteral(
"gml:Envelope" ) );
1194 envElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1198 QDomElement lowerCornerElem = doc.createElement( QStringLiteral(
"gml:lowerCorner" ) );
1202 const QDomText lowerCornerText = doc.createTextNode( posList );
1203 lowerCornerElem.appendChild( lowerCornerText );
1204 envElem.appendChild( lowerCornerElem );
1206 QDomElement upperCornerElem = doc.createElement( QStringLiteral(
"gml:upperCorner" ) );
1210 const QDomText upperCornerText = doc.createTextNode( posList );
1211 upperCornerElem.appendChild( upperCornerText );
1212 envElem.appendChild( upperCornerElem );
1226 bool invertAxisOrientation,
1227 const QString &gmlIdBase,
1231 return QDomElement();
1234 QString cs = QStringLiteral(
"," );
1236 const QString ts = QStringLiteral(
" " );
1238 QDomElement baseCoordElem;
1240 bool hasZValue =
false;
1242 const QByteArray wkb( geometry.
asWkb() );
1252 return QDomElement();
1263 baseCoordElem = doc.createElement( QStringLiteral(
"gml:pos" ) );
1266 baseCoordElem = doc.createElement( QStringLiteral(
"gml:posList" ) );
1269 baseCoordElem.setAttribute( QStringLiteral(
"srsDimension" ), QStringLiteral(
"2" ) );
1274 baseCoordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1275 baseCoordElem.setAttribute( QStringLiteral(
"cs" ), cs );
1276 baseCoordElem.setAttribute( QStringLiteral(
"ts" ), ts );
1286 QDomElement pointElem = doc.createElement( QStringLiteral(
"gml:Point" ) );
1287 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1288 pointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1290 pointElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1291 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1295 if ( invertAxisOrientation )
1301 coordElem.appendChild( coordText );
1302 pointElem.appendChild( coordElem );
1311 QDomElement multiPointElem = doc.createElement( QStringLiteral(
"gml:MultiPoint" ) );
1312 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1313 multiPointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1315 multiPointElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1320 for (
int idx = 0; idx < nPoints; ++idx )
1322 QDomElement pointMemberElem = doc.createElement( QStringLiteral(
"gml:pointMember" ) );
1323 QDomElement pointElem = doc.createElement( QStringLiteral(
"gml:Point" ) );
1324 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1325 pointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( idx + 1 ) );
1326 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1332 if ( invertAxisOrientation )
1338 coordElem.appendChild( coordText );
1339 pointElem.appendChild( coordElem );
1343 wkbPtr +=
sizeof( double );
1345 pointMemberElem.appendChild( pointElem );
1346 multiPointElem.appendChild( pointMemberElem );
1348 return multiPointElem;
1356 QDomElement lineStringElem = doc.createElement( QStringLiteral(
"gml:LineString" ) );
1357 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1358 lineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1360 lineStringElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1366 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1367 QString coordString;
1368 for (
int idx = 0; idx < nPoints; ++idx )
1377 if ( invertAxisOrientation )
1385 wkbPtr +=
sizeof( double );
1388 const QDomText coordText = doc.createTextNode( coordString );
1389 coordElem.appendChild( coordText );
1390 lineStringElem.appendChild( coordElem );
1391 return lineStringElem;
1399 QDomElement multiLineStringElem = doc.createElement( QStringLiteral(
"gml:MultiLineString" ) );
1400 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1401 multiLineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1403 multiLineStringElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1408 for (
int jdx = 0; jdx < nLines; jdx++ )
1410 QDomElement lineStringMemberElem = doc.createElement( QStringLiteral(
"gml:lineStringMember" ) );
1411 QDomElement lineStringElem = doc.createElement( QStringLiteral(
"gml:LineString" ) );
1412 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1413 lineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( jdx + 1 ) );
1420 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1421 QString coordString;
1422 for (
int idx = 0; idx < nPoints; idx++ )
1431 if ( invertAxisOrientation )
1440 wkbPtr +=
sizeof( double );
1443 const QDomText coordText = doc.createTextNode( coordString );
1444 coordElem.appendChild( coordText );
1445 lineStringElem.appendChild( coordElem );
1446 lineStringMemberElem.appendChild( lineStringElem );
1447 multiLineStringElem.appendChild( lineStringMemberElem );
1449 return multiLineStringElem;
1457 QDomElement polygonElem = doc.createElement( QStringLiteral(
"gml:Polygon" ) );
1458 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1459 polygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1461 polygonElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1467 if ( numRings == 0 )
1468 return QDomElement();
1470 for (
int idx = 0; idx < numRings; idx++ )
1472 QString boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:outerBoundaryIs" :
"gml:exterior";
1475 boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:innerBoundaryIs" :
"gml:interior";
1477 QDomElement boundaryElem = doc.createElement( boundaryName );
1478 QDomElement ringElem = doc.createElement( QStringLiteral(
"gml:LinearRing" ) );
1483 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1484 QString coordString;
1485 for (
int jdx = 0; jdx < nPoints; jdx++ )
1494 if ( invertAxisOrientation )
1502 wkbPtr +=
sizeof( double );
1505 const QDomText coordText = doc.createTextNode( coordString );
1506 coordElem.appendChild( coordText );
1507 ringElem.appendChild( coordElem );
1508 boundaryElem.appendChild( ringElem );
1509 polygonElem.appendChild( boundaryElem );
1519 QDomElement multiPolygonElem = doc.createElement( QStringLiteral(
"gml:MultiPolygon" ) );
1520 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1521 multiPolygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1523 multiPolygonElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1526 wkbPtr >> numPolygons;
1528 for (
int kdx = 0; kdx < numPolygons; kdx++ )
1530 QDomElement polygonMemberElem = doc.createElement( QStringLiteral(
"gml:polygonMember" ) );
1531 QDomElement polygonElem = doc.createElement( QStringLiteral(
"gml:Polygon" ) );
1532 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1533 polygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( kdx + 1 ) );
1540 for (
int idx = 0; idx < numRings; idx++ )
1542 QString boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:outerBoundaryIs" :
"gml:exterior";
1545 boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:innerBoundaryIs" :
"gml:interior";
1547 QDomElement boundaryElem = doc.createElement( boundaryName );
1548 QDomElement ringElem = doc.createElement( QStringLiteral(
"gml:LinearRing" ) );
1553 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1554 QString coordString;
1555 for (
int jdx = 0; jdx < nPoints; jdx++ )
1564 if ( invertAxisOrientation )
1573 wkbPtr +=
sizeof( double );
1576 const QDomText coordText = doc.createTextNode( coordString );
1577 coordElem.appendChild( coordText );
1578 ringElem.appendChild( coordElem );
1579 boundaryElem.appendChild( ringElem );
1580 polygonElem.appendChild( boundaryElem );
1581 polygonMemberElem.appendChild( polygonElem );
1582 multiPolygonElem.appendChild( polygonMemberElem );
1585 return multiPolygonElem;
1588 return QDomElement();
1594 return QDomElement();
1603QDomElement QgsOgcUtils::createGMLCoordinates(
const QgsPolylineXY &points, QDomDocument &doc )
1605 QDomElement coordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1606 coordElem.setAttribute( QStringLiteral(
"cs" ), QStringLiteral(
"," ) );
1607 coordElem.setAttribute( QStringLiteral(
"ts" ), QStringLiteral(
" " ) );
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 coordElem.appendChild( coordText );
1627QDomElement QgsOgcUtils::createGMLPositions(
const QgsPolylineXY &points, QDomDocument &doc )
1629 QDomElement posElem = doc.createElement( QStringLiteral(
"gml:pos" ) );
1630 if ( points.size() > 1 )
1631 posElem = doc.createElement( QStringLiteral(
"gml:posList" ) );
1632 posElem.setAttribute( QStringLiteral(
"srsDimension" ), QStringLiteral(
"2" ) );
1634 QString coordString;
1635 QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
1636 for ( ; pointIt != points.constEnd(); ++pointIt )
1638 if ( pointIt != points.constBegin() )
1647 const QDomText coordText = doc.createTextNode( coordString );
1648 posElem.appendChild( coordText );
1658 if ( fillElement.isNull() || !fillElement.hasChildNodes() )
1666 QDomElement cssElem = fillElement.firstChildElement( QStringLiteral(
"CssParameter" ) );
1667 while ( !cssElem.isNull() )
1669 cssName = cssElem.attribute( QStringLiteral(
"name" ), QStringLiteral(
"not_found" ) );
1670 if ( cssName != QLatin1String(
"not_found" ) )
1672 elemText = cssElem.text();
1673 if ( cssName == QLatin1String(
"fill" ) )
1675 color.setNamedColor( elemText );
1677 else if ( cssName == QLatin1String(
"fill-opacity" ) )
1680 const double opacity = elemText.toDouble( &ok );
1683 color.setAlphaF( opacity );
1688 cssElem = cssElem.nextSiblingElement( QStringLiteral(
"CssParameter" ) );
1702 if ( element.isNull() || !element.hasChildNodes() )
1709 if ( element.firstChild().nodeType() == QDomNode::TextNode )
1719 QDomElement childElem = element.firstChildElement();
1720 while ( !childElem.isNull() )
1732 if ( !expr->d->mRootNode )
1734 expr->d->mRootNode = node;
1741 childElem = childElem.nextSiblingElement();
1745 expr->d->mExp = expr->
dump();
1771static
int binaryOperatorFromTagName( const QString &tagName )
1774 return BINARY_OPERATORS_TAG_NAMES_MAP()->value( tagName, -1 );
1781 return QStringLiteral(
"PropertyIsLike" );
1783 return BINARY_OPERATORS_TAG_NAMES_MAP()->key( op, QString() );
1786static bool isBinaryOperator(
const QString &tagName )
1788 return binaryOperatorFromTagName( tagName ) >= 0;
1792static bool isSpatialOperator(
const QString &tagName )
1794 static QStringList spatialOps;
1795 if ( spatialOps.isEmpty() )
1797 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
1798 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
1801 return spatialOps.contains( tagName );
1808 errorMessage = utils.errorMessage();
1816 errorMessage = utils.errorMessage();
1824 errorMessage = utils.errorMessage();
1832 errorMessage = utils.errorMessage();
1840 errorMessage = utils.errorMessage();
1848 errorMessage = utils.errorMessage();
1856 errorMessage = utils.errorMessage();
1860QgsExpressionNode *QgsOgcUtils::nodeIsBetweenFromOgcFilter( QDomElement &element, QString &errorMessage )
1864 errorMessage = utils.errorMessage();
1872 errorMessage = utils.errorMessage();
1883 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage );
1889 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage, requiresFilterElement );
1894 return doc.createElementNS(
SE_NAMESPACE, QStringLiteral(
"se:ElseFilter" ) );
1902 const QString &namespacePrefix,
1903 const QString &namespaceURI,
1906 bool honourAxisOrientation,
1907 bool invertAxisOrientation,
1908 QString *errorMessage )
1911 return QDomElement();
1921 if ( exprRootElem.isNull() )
1922 return QDomElement();
1924 QDomElement filterElem = filterElement( doc, gmlVersion, filterVersion, utils.
GMLNamespaceUsed() );
1926 if ( !namespacePrefix.isEmpty() && !namespaceURI.isEmpty() )
1928 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:" ) + namespacePrefix );
1929 attr.setValue( namespaceURI );
1930 filterElem.setAttributeNode( attr );
1933 filterElem.appendChild( exprRootElem );
1943 bool honourAxisOrientation,
1944 bool invertAxisOrientation,
1945 QString *errorMessage,
1946 bool requiresFilterElement )
1955 return QDomElement();
1969 if ( !exprRootElem.isNull() )
1971 if ( requiresFilterElement )
1973 QDomElement filterElem = filterElement( doc, gmlVersion, filterVersion, utils.
GMLNamespaceUsed() );
1975 filterElem.appendChild( exprRootElem );
1978 return exprRootElem;
1985 *errorMessage = QObject::tr(
"Node type not supported in expression translation: %1" ).arg( node->
nodeType() );
1989 return QDomElement();
1996 const QList<LayerProperties> &layerProperties,
1997 bool honourAxisOrientation,
1998 bool invertAxisOrientation,
1999 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename,
2000 QString *errorMessage )
2003 return QDomElement();
2006 layerProperties, honourAxisOrientation, invertAxisOrientation,
2007 mapUnprefixedTypenameToPrefixedTypename );
2011 if ( exprRootElem.isNull() )
2012 return QDomElement();
2014 QDomElement filterElem = filterElement( doc, gmlVersion, filterVersion, utils.
GMLNamespaceUsed() );
2016 QSet<QString> setNamespaceURI;
2019 if ( !props.mNamespacePrefix.isEmpty() && !props.mNamespaceURI.isEmpty() &&
2020 !setNamespaceURI.contains( props.mNamespaceURI ) )
2022 setNamespaceURI.insert( props.mNamespaceURI );
2023 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:" ) + props.mNamespacePrefix );
2024 attr.setValue( props.mNamespaceURI );
2025 filterElem.setAttributeNode( attr );
2028 filterElem.appendChild( exprRootElem );
2053 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
2054 return QDomElement();
2061 if ( !mErrorMessage.isEmpty() )
2062 return QDomElement();
2065 switch ( node->
op() )
2068 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2073 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
2074 mDoc.removeChild( operandElem );
2078 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
2079 return QDomElement();
2083 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
2084 uoElem.appendChild( operandElem );
2088 mErrorMessage = QObject::tr(
"Unary operator '%1' not implemented yet" ).arg( node->
text() );
2089 return QDomElement();
2099 if ( !mErrorMessage.isEmpty() )
2100 return QDomElement();
2113 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2114 elem.appendChild( leftElem );
2118 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2119 notElem.appendChild( elem );
2133 if ( !mErrorMessage.isEmpty() )
2134 return QDomElement();
2137 const QString opText = binaryOperatorToTagName( op );
2138 if ( opText.isEmpty() )
2142 mErrorMessage = QObject::tr(
"Binary operator %1 not implemented yet" ).arg( node->
text() );
2143 return QDomElement();
2146 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2151 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2154 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2155 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2157 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2159 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2162 boElem.appendChild( leftElem );
2163 boElem.appendChild( rightElem );
2170 Q_UNUSED( expression )
2173 switch ( node->
value().type() )
2176 value = QString::number( node->
value().toInt() );
2178 case QVariant::Double:
2181 case QVariant::String:
2182 value = node->
value().toString();
2184 case QVariant::Date:
2185 value = node->
value().toDate().toString( Qt::ISODate );
2187 case QVariant::DateTime:
2188 value = node->
value().toDateTime().toString( Qt::ISODate );
2192 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2193 return QDomElement();
2196 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2197 litElem.appendChild( mDoc.createTextNode( value ) );
2204 Q_UNUSED( expression )
2206 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2207 QString columnRef( node->
name() );
2208 if ( !mNamespacePrefix.isEmpty() && !mNamespaceURI.isEmpty() )
2209 columnRef = mNamespacePrefix + QStringLiteral(
":" ) + columnRef;
2210 propElem.appendChild( mDoc.createTextNode( columnRef ) );
2218 if ( node->
list()->
list().size() == 1 )
2221 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2224 const auto constList = node->
list()->
list();
2228 if ( !mErrorMessage.isEmpty() )
2229 return QDomElement();
2231 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2232 eqElem.appendChild( leftNode.cloneNode() );
2233 eqElem.appendChild( listNode );
2235 orElem.appendChild( eqElem );
2240 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2241 notElem.appendChild( orElem );
2250 { QLatin1String(
"disjoint" ), QLatin1String(
"Disjoint" ) },
2251 { QLatin1String(
"intersects" ), QLatin1String(
"Intersects" )},
2252 { QLatin1String(
"touches" ), QLatin1String(
"Touches" ) },
2253 { QLatin1String(
"crosses" ), QLatin1String(
"Crosses" ) },
2254 { QLatin1String(
"contains" ), QLatin1String(
"Contains" ) },
2255 { QLatin1String(
"overlaps" ), QLatin1String(
"Overlaps" ) },
2256 { QLatin1String(
"within" ), QLatin1String(
"Within" ) }
2259static
bool isBinarySpatialOperator( const QString &fnName )
2261 return BINARY_SPATIAL_OPS_MAP()->contains( fnName );
2264static QString tagNameForSpatialOperator(
const QString &fnName )
2266 return BINARY_SPATIAL_OPS_MAP()->value( fnName );
2276 return fd->
name() == QLatin1String(
"$geometry" );
2288 if ( fnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2290 const QList<QgsExpressionNode *> &args = fnNode->
args()->
list();
2306 if ( fd->
name() == QLatin1String(
"intersects_bbox" ) )
2308 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2309 Q_ASSERT( argNodes.count() == 2 );
2311 const QgsGeometry geom = geometryFromConstExpr( argNodes[1] );
2312 if ( !geom.
isNull() && isGeometryColumn( argNodes[0] ) )
2322 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":BBOX" );
2324 if ( !mGeometryName.isEmpty() )
2327 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2328 QString columnRef( mGeometryName );
2329 if ( !mNamespacePrefix.isEmpty() && !mNamespaceURI.isEmpty() )
2330 columnRef = mNamespacePrefix + QStringLiteral(
":" ) + columnRef;
2331 geomProperty.appendChild( mDoc.createTextNode( columnRef ) );
2333 funcElem.appendChild( geomProperty );
2335 funcElem.appendChild( elemBox );
2340 mErrorMessage = QObject::tr(
"<BBOX> is currently supported only in form: bbox($geometry, geomFromWKT('…'))" );
2341 return QDomElement();
2345 if ( isBinarySpatialOperator( fd->
name() ) )
2347 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2348 Q_ASSERT( argNodes.count() == 2 );
2351 if ( isGeometryColumn( argNodes[0] ) )
2352 otherNode = argNodes[1];
2353 else if ( isGeometryColumn( argNodes[1] ) )
2354 otherNode = argNodes[0];
2357 mErrorMessage = QObject::tr(
"Unable to translate spatial operator: at least one must refer to geometry." );
2358 return QDomElement();
2361 QDomElement otherGeomElem;
2366 mErrorMessage = QObject::tr(
"spatial operator: the other operator must be a geometry constructor function" );
2367 return QDomElement();
2372 if ( otherFnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2377 mErrorMessage = QObject::tr(
"geom_from_wkt: argument must be string literal" );
2378 return QDomElement();
2383 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2384 if ( otherGeomElem.isNull() )
2386 mErrorMessage = QObject::tr(
"geom_from_wkt: unable to generate GML from wkt geometry" );
2387 return QDomElement();
2391 else if ( otherFnDef->
name() == QLatin1String(
"geom_from_gml" ) )
2396 mErrorMessage = QObject::tr(
"geom_from_gml: argument must be string literal" );
2397 return QDomElement();
2400 QDomDocument geomDoc;
2402 if ( !geomDoc.setContent( gml,
true ) )
2404 mErrorMessage = QObject::tr(
"geom_from_gml: unable to parse XML" );
2405 return QDomElement();
2408 const QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(),
true );
2409 otherGeomElem = geomNode.toElement();
2415 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2416 if ( otherGeomElem.
isNull() )
2418 mErrorMessage = QObject::tr(
"geom from static value: unable to generate GML from static variable" );
2419 return QDomElement();
2425 mErrorMessage = QObject::tr(
"spatial operator: unknown geometry constructor function" );
2426 return QDomElement();
2431 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + tagNameForSpatialOperator( fd->
name() ) );
2432 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2433 QString columnRef( mGeometryName );
2434 if ( !mNamespacePrefix.isEmpty() && !mNamespaceURI.isEmpty() )
2435 columnRef = mNamespacePrefix + QStringLiteral(
":" ) + columnRef;
2436 geomProperty.appendChild( mDoc.createTextNode( columnRef ) );
2437 funcElem.appendChild( geomProperty );
2438 funcElem.appendChild( otherGeomElem );
2442 if ( fd->
isStatic( node, expression, context ) )
2444 const QVariant result = fd->
run( node->
args(), context, expression, node );
2446 return expressionLiteralToOgcFilter( &literal, expression, context );
2451 mErrorMessage = QObject::tr(
"Special columns/constants are not supported." );
2452 return QDomElement();
2456 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
2457 funcElem.setAttribute( QStringLiteral(
"name" ), fd->
name() );
2458 const auto constList = node->
args()->
list();
2462 if ( !mErrorMessage.isEmpty() )
2463 return QDomElement();
2465 funcElem.appendChild( childElem );
2476 const QList<QgsOgcUtils::LayerProperties> &layerProperties,
2477 bool honourAxisOrientation,
2478 bool invertAxisOrientation,
2479 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename )
2482 , mGMLVersion( gmlVersion )
2483 , mFilterVersion( filterVersion )
2484 , mLayerProperties( layerProperties )
2485 , mHonourAxisOrientation( honourAxisOrientation )
2486 , mInvertAxisOrientation( invertAxisOrientation )
2487 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
2488 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
2490 , mMapUnprefixedTypenameToPrefixedTypename( mapUnprefixedTypenameToPrefixedTypename )
2516 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
2517 return QDomElement();
2526 if ( !mErrorMessage.isEmpty() )
2527 return QDomElement();
2530 switch ( node->
op() )
2533 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2538 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
2539 mDoc.removeChild( operandElem );
2543 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
2544 return QDomElement();
2548 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
2549 uoElem.appendChild( operandElem );
2554 return QDomElement();
2564 if ( !mErrorMessage.isEmpty() )
2565 return QDomElement();
2578 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2579 elem.appendChild( leftElem );
2583 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2584 notElem.appendChild( elem );
2598 if ( !mErrorMessage.isEmpty() )
2599 return QDomElement();
2604 opText = QStringLiteral(
"Or" );
2606 opText = QStringLiteral(
"And" );
2608 opText = QStringLiteral(
"PropertyIsEqualTo" );
2610 opText = QStringLiteral(
"PropertyIsNotEqualTo" );
2612 opText = QStringLiteral(
"PropertyIsLessThanOrEqualTo" );
2614 opText = QStringLiteral(
"PropertyIsGreaterThanOrEqualTo" );
2616 opText = QStringLiteral(
"PropertyIsLessThan" );
2618 opText = QStringLiteral(
"PropertyIsGreaterThan" );
2620 opText = QStringLiteral(
"PropertyIsLike" );
2622 opText = QStringLiteral(
"PropertyIsLike" );
2624 if ( opText.isEmpty() )
2628 return QDomElement();
2631 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2636 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2639 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2640 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2642 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2644 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2647 boElem.appendChild( leftElem );
2648 boElem.appendChild( rightElem );
2656 switch ( node->
value().type() )
2659 value = QString::number( node->
value().toInt() );
2661 case QVariant::LongLong:
2662 value = QString::number( node->
value().toLongLong() );
2664 case QVariant::Double:
2667 case QVariant::String:
2668 value = node->
value().toString();
2672 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2673 return QDomElement();
2676 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2677 litElem.appendChild( mDoc.createTextNode( value ) );
2684 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2685 if ( node->
tableName().isEmpty() || mLayerProperties.size() == 1 )
2687 if ( mLayerProperties.size() == 1 && !mLayerProperties[0].mNamespacePrefix.isEmpty() && !mLayerProperties[0].mNamespaceURI.isEmpty() )
2688 propElem.appendChild( mDoc.createTextNode(
2689 mLayerProperties[0].mNamespacePrefix + QStringLiteral(
":" ) + node->
name() ) );
2691 propElem.appendChild( mDoc.createTextNode( node->
name() ) );
2695 QString tableName( mMapTableAliasToNames[node->
tableName()] );
2696 if ( mMapUnprefixedTypenameToPrefixedTypename.contains( tableName ) )
2697 tableName = mMapUnprefixedTypenameToPrefixedTypename[tableName];
2698 propElem.appendChild( mDoc.createTextNode( tableName +
"/" + node->
name() ) );
2705 if ( node->
list()->
list().size() == 1 )
2708 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2711 const auto constList = node->
list()->
list();
2715 if ( !mErrorMessage.isEmpty() )
2716 return QDomElement();
2718 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2719 eqElem.appendChild( leftNode.cloneNode() );
2720 eqElem.appendChild( listNode );
2722 orElem.appendChild( eqElem );
2727 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2728 notElem.appendChild( orElem );
2737 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsBetween" );
2739 QDomElement lowerBoundary = mDoc.createElement( mFilterPrefix +
":LowerBoundary" );
2741 elem.appendChild( lowerBoundary );
2742 QDomElement upperBoundary = mDoc.createElement( mFilterPrefix +
":UpperBoundary" );
2744 elem.appendChild( upperBoundary );
2748 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2749 notElem.appendChild( elem );
2756static QString mapBinarySpatialToOgc(
const QString &name )
2758 QString nameCompare( name );
2759#if QT_VERSION < QT_VERSION_CHECK(5, 15, 2)
2760 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2761 nameCompare = name.mid( 3 );
2763 if ( name.size() > 3 && QStringView {name}.mid( 0, 3 ).toString().compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2764 nameCompare = name.mid( 3 );
2766 QStringList spatialOps;
2767 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
2768 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
2769 const auto constSpatialOps = spatialOps;
2770 for ( QString op : constSpatialOps )
2772 if ( nameCompare.compare( op, Qt::CaseInsensitive ) == 0 )
2778static QString mapTernarySpatialToOgc(
const QString &name )
2780 QString nameCompare( name );
2781#if QT_VERSION < QT_VERSION_CHECK(5, 15, 2)
2782 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2783 nameCompare = name.mid( 3 );
2785 if ( name.size() > 3 && QStringView {name}.mid( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2786 nameCompare = name.mid( 3 );
2788 if ( nameCompare.compare( QLatin1String(
"DWithin" ), Qt::CaseInsensitive ) == 0 )
2789 return QStringLiteral(
"DWithin" );
2790 if ( nameCompare.compare( QLatin1String(
"Beyond" ), Qt::CaseInsensitive ) == 0 )
2791 return QStringLiteral(
"Beyond" );
2795QString QgsOgcUtilsSQLStatementToFilter::getGeometryColumnSRSName(
const QgsSQLStatement::Node *node )
2803 const auto constMLayerProperties = mLayerProperties;
2806 if ( prop.mName.compare( mMapTableAliasToNames[col->
tableName()], Qt::CaseInsensitive ) == 0 &&
2807 prop.mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2809 return prop.mSRSName;
2813 if ( !mLayerProperties.empty() &&
2814 mLayerProperties.at( 0 ).mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2816 return mLayerProperties.at( 0 ).mSRSName;
2822 QList<QgsSQLStatement::Node *> args,
2823 bool lastArgIsSRSName,
2825 bool &axisInversion )
2828 axisInversion = mInvertAxisOrientation;
2830 if ( lastArgIsSRSName )
2835 mErrorMessage = QObject::tr(
"%1: Last argument must be string or integer literal" ).arg( mainNode->
name() );
2839 if ( lit->
value().type() == QVariant::Int )
2843 srsName =
"EPSG:" + QString::number( lit->
value().toInt() );
2847 srsName =
"urn:ogc:def:crs:EPSG::" + QString::number( lit->
value().toInt() );
2853 if (
srsName.startsWith( QLatin1String(
"EPSG:" ), Qt::CaseInsensitive ) )
2865 axisInversion = !axisInversion;
2875 if ( node->
name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 )
2877 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2878 if ( args.size() != 1 && args.size() != 2 )
2880 mErrorMessage = QObject::tr(
"Function %1 should have 1 or 2 arguments" ).arg( node->
name() );
2881 return QDomElement();
2887 mErrorMessage = QObject::tr(
"%1: First argument must be string literal" ).arg( node->
name() );
2888 return QDomElement();
2893 if ( ! processSRSName( node, args, args.size() == 2,
srsName, axisInversion ) )
2895 return QDomElement();
2901 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2903 if ( geomElem.isNull() )
2905 mErrorMessage = QObject::tr(
"%1: invalid WKT" ).arg( node->
name() );
2906 return QDomElement();
2913 if ( node->
name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 )
2915 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2916 if ( args.size() != 4 && args.size() != 5 )
2918 mErrorMessage = QObject::tr(
"Function %1 should have 4 or 5 arguments" ).arg( node->
name() );
2919 return QDomElement();
2924 for (
int i = 0; i < 4; i++ )
2929 mErrorMessage = QObject::tr(
"%1: Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2930 return QDomElement();
2934 if ( lit->
value().type() == QVariant::Int )
2935 val = lit->
value().toInt();
2936 else if ( lit->
value().type() == QVariant::LongLong )
2937 val = lit->
value().toLongLong();
2938 else if ( lit->
value().type() == QVariant::Double )
2939 val = lit->
value().toDouble();
2942 mErrorMessage = QObject::tr(
"%1 Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2943 return QDomElement();
2957 if ( ! processSRSName( node, args, args.size() == 5,
srsName, axisInversion ) )
2959 return QDomElement();
2970 if ( node->
name().compare( QLatin1String(
"ST_GeomFromGML" ), Qt::CaseInsensitive ) == 0 )
2972 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2973 if ( args.size() != 1 )
2975 mErrorMessage = QObject::tr(
"Function %1 should have 1 argument" ).arg( node->
name() );
2976 return QDomElement();
2982 mErrorMessage = QObject::tr(
"%1: Argument must be string literal" ).arg( node->
name() );
2983 return QDomElement();
2986 QDomDocument geomDoc;
2988 if ( !geomDoc.setContent( gml,
true ) )
2990 mErrorMessage = QObject::tr(
"ST_GeomFromGML: unable to parse XML" );
2991 return QDomElement();
2994 const QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(),
true );
2996 return geomNode.toElement();
3000 QString ogcName( mapBinarySpatialToOgc( node->
name() ) );
3001 if ( !ogcName.isEmpty() )
3003 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
3004 if ( args.size() != 2 )
3006 mErrorMessage = QObject::tr(
"Function %1 should have 2 arguments" ).arg( node->
name() );
3007 return QDomElement();
3010 for (
int i = 0; i < 2; i ++ )
3013 (
static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
3014 static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
3016 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
3023 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + ogcName );
3024 const auto constArgs = args;
3028 if ( !mErrorMessage.isEmpty() )
3030 mCurrentSRSName.clear();
3031 return QDomElement();
3034 funcElem.appendChild( childElem );
3037 mCurrentSRSName.clear();
3041 ogcName = mapTernarySpatialToOgc( node->
name() );
3042 if ( !ogcName.isEmpty() )
3044 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
3045 if ( args.size() != 3 )
3047 mErrorMessage = QObject::tr(
"Function %1 should have 3 arguments" ).arg( node->
name() );
3048 return QDomElement();
3051 for (
int i = 0; i < 2; i ++ )
3054 (
static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
3055 static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
3057 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
3062 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + node->
name().mid( 3 ) );
3063 for (
int i = 0; i < 2; i++ )
3065 const QDomElement childElem =
toOgcFilter( args[i] );
3066 if ( !mErrorMessage.isEmpty() )
3068 mCurrentSRSName.clear();
3069 return QDomElement();
3072 funcElem.appendChild( childElem );
3074 mCurrentSRSName.clear();
3079 mErrorMessage = QObject::tr(
"Function %1 3rd argument should be a numeric value or a string made of a numeric value followed by a string" ).arg( node->
name() );
3080 return QDomElement();
3085 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() );
3086 return QDomElement();
3089 QString unit( QStringLiteral(
"m" ) );
3090 switch ( lit->
value().type() )
3093 distance = QString::number( lit->
value().toInt() );
3095 case QVariant::LongLong:
3096 distance = QString::number( lit->
value().toLongLong() );
3098 case QVariant::Double:
3101 case QVariant::String:
3103 distance = lit->
value().toString();
3104 for (
int i = 0; i < distance.size(); i++ )
3106 if ( !( ( distance[i] >=
'0' && distance[i] <=
'9' ) || distance[i] ==
'-' || distance[i] ==
'.' || distance[i] ==
'e' || distance[i] ==
'E' ) )
3108 unit = distance.mid( i ).trimmed();
3109 distance = distance.mid( 0, i );
3117 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( lit->
value().type() );
3118 return QDomElement();
3121 QDomElement distanceElem = mDoc.createElement( mFilterPrefix +
":Distance" );
3123 distanceElem.setAttribute( QStringLiteral(
"uom" ), unit );
3125 distanceElem.setAttribute( QStringLiteral(
"unit" ), unit );
3126 distanceElem.appendChild( mDoc.createTextNode( distance ) );
3127 funcElem.appendChild( distanceElem );
3132 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
3133 funcElem.setAttribute( QStringLiteral(
"name" ), node->
name() );
3134 const auto constList = node->
args()->
list();
3138 if ( !mErrorMessage.isEmpty() )
3139 return QDomElement();
3141 funcElem.appendChild( childElem );
3147 const QString &leftTable )
3155 QList<QDomElement> listElem;
3157 for (
const QString &columnName : constUsingColumns )
3159 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
3160 QDomElement propElem1 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3161 propElem1.appendChild( mDoc.createTextNode( leftTable +
"/" + columnName ) );
3162 eqElem.appendChild( propElem1 );
3163 QDomElement propElem2 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3164 propElem2.appendChild( mDoc.createTextNode( node->
tableDef()->
name() +
"/" + columnName ) );
3165 eqElem.appendChild( propElem2 );
3166 listElem.append( eqElem );
3169 if ( listElem.size() == 1 )
3173 else if ( listElem.size() > 1 )
3175 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3176 const auto constListElem = listElem;
3177 for (
const QDomElement &elem : constListElem )
3179 andElem.appendChild( elem );
3184 return QDomElement();
3189 if ( node->
alias().isEmpty() )
3191 mMapTableAliasToNames[ node->
name()] = node->
name();
3195 mMapTableAliasToNames[ node->
alias()] = node->
name();
3201 QList<QDomElement> listElem;
3204 ( node->
tables().size() != 1 || !node->
joins().empty() ) )
3206 mErrorMessage = QObject::tr(
"Joins are only supported with WFS 2.0" );
3207 return QDomElement();
3211 const auto constTables = node->
tables();
3216 const auto constJoins = node->
joins();
3219 visit( join->tableDef() );
3223 const QList< QgsSQLStatement::NodeTableDef *> nodeTables = node->
tables();
3224 QString leftTable = nodeTables.at( nodeTables.length() - 1 )->name();
3227 const QDomElement joinElem =
toOgcFilter( join, leftTable );
3228 if ( !mErrorMessage.isEmpty() )
3229 return QDomElement();
3230 listElem.append( joinElem );
3231 leftTable = join->tableDef()->name();
3235 if ( node->
where() )
3238 if ( !mErrorMessage.isEmpty() )
3239 return QDomElement();
3240 listElem.append( whereElem );
3244 if ( listElem.size() == 1 )
3248 else if ( listElem.size() > 1 )
3250 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3251 const auto constListElem = listElem;
3252 for (
const QDomElement &elem : constListElem )
3254 andElem.appendChild( elem );
3259 return QDomElement();
3265 mPropertyName = QStringLiteral(
"PropertyName" );
3266 mPrefix = QStringLiteral(
"ogc" );
3270 mPropertyName = QStringLiteral(
"ValueReference" );
3271 mPrefix = QStringLiteral(
"fes" );
3277 if ( element.isNull() )
3281 if ( isBinaryOperator( element.tagName() ) )
3287 if ( isSpatialOperator( element.tagName() ) )
3293 if ( element.tagName() == QLatin1String(
"Not" ) )
3297 else if ( element.tagName() == QLatin1String(
"PropertyIsNull" ) )
3301 else if ( element.tagName() == QLatin1String(
"Literal" ) )
3305 else if ( element.tagName() == QLatin1String(
"Function" ) )
3309 else if ( element.tagName() == mPropertyName )
3313 else if ( element.tagName() == QLatin1String(
"PropertyIsBetween" ) )
3318 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() );
3324 if ( element.isNull() )
3327 int op = binaryOperatorFromTagName( element.tagName() );
3330 mErrorMessage = QObject::tr(
"'%1' binary operator not supported." ).arg( element.tagName() );
3334 if ( op ==
QgsExpressionNodeBinaryOperator::boLike && element.hasAttribute( QStringLiteral(
"matchCase" ) ) && element.attribute( QStringLiteral(
"matchCase" ) ) == QLatin1String(
"false" ) )
3339 QDomElement operandElem = element.firstChildElement();
3344 mErrorMessage = QObject::tr(
"invalid left operand for '%1' binary operator" ).arg( element.tagName() );
3348 const std::unique_ptr<QgsExpressionNode> leftOp( expr->clone() );
3349 for ( operandElem = operandElem.nextSiblingElement(); !operandElem.isNull(); operandElem = operandElem.nextSiblingElement() )
3354 mErrorMessage = QObject::tr(
"invalid right operand for '%1' binary operator" ).arg( element.tagName() );
3361 if ( element.hasAttribute( QStringLiteral(
"wildCard" ) ) )
3363 wildCard = element.attribute( QStringLiteral(
"wildCard" ) );
3366 if ( element.hasAttribute( QStringLiteral(
"singleChar" ) ) )
3368 singleChar = element.attribute( QStringLiteral(
"singleChar" ) );
3370 QString escape = QStringLiteral(
"\\" );
3371 if ( element.hasAttribute( QStringLiteral(
"escape" ) ) )
3373 escape = element.attribute( QStringLiteral(
"escape" ) );
3375 if ( element.hasAttribute( QStringLiteral(
"escapeChar" ) ) )
3377 escape = element.attribute( QStringLiteral(
"escapeChar" ) );
3381 if ( !wildCard.isEmpty() && wildCard != QLatin1String(
"%" ) )
3383 oprValue.replace(
'%', QLatin1String(
"\\%" ) );
3384 if ( oprValue.startsWith( wildCard ) )
3386 oprValue.replace( 0, 1, QStringLiteral(
"%" ) );
3389 QRegularExpressionMatch match = rx.match( oprValue );
3391 while ( match.hasMatch() )
3393 pos = match.capturedStart();
3394 oprValue.replace( pos + 1, 1, QStringLiteral(
"%" ) );
3396 match = rx.match( oprValue, pos );
3398 oprValue.replace( escape + wildCard, wildCard );
3400 if ( !singleChar.isEmpty() && singleChar != QLatin1String(
"_" ) )
3402 oprValue.replace(
'_', QLatin1String(
"\\_" ) );
3403 if ( oprValue.startsWith( singleChar ) )
3405 oprValue.replace( 0, 1, QStringLiteral(
"_" ) );
3408 QRegularExpressionMatch match = rx.match( oprValue );
3410 while ( match.hasMatch() )
3412 pos = match.capturedStart();
3413 oprValue.replace( pos + 1, 1, QStringLiteral(
"_" ) );
3415 match = rx.match( oprValue, pos );
3417 oprValue.replace( escape + singleChar, singleChar );
3419 if ( !escape.isEmpty() && escape != QLatin1String(
"\\" ) )
3421 oprValue.replace( escape + escape, escape );
3429 if ( expr == leftOp )
3431 mErrorMessage = QObject::tr(
"only one operand for '%1' binary operator" ).arg( element.tagName() );
3445 QDomElement childElem = element.firstChildElement();
3447 while ( !childElem.isNull() && gml2Str.isEmpty() )
3449 if ( childElem.tagName() != mPropertyName )
3451 QTextStream gml2Stream( &gml2Str );
3452 childElem.save( gml2Stream, 0 );
3454 childElem = childElem.nextSiblingElement();
3456 if ( !gml2Str.isEmpty() )
3462 mErrorMessage = QObject::tr(
"No OGC Geometry found" );
3475 if ( element.isNull() || element.tagName() != mPropertyName )
3477 mErrorMessage = QObject::tr(
"%1:PropertyName expected, got %2" ).arg( mPrefix, element.tagName() );
3486 if ( element.isNull() || element.tagName() != QLatin1String(
"Literal" ) )
3488 mErrorMessage = QObject::tr(
"%1:Literal expected, got %2" ).arg( mPrefix, element.tagName() );
3492 std::unique_ptr<QgsExpressionNode> root;
3493 if ( !element.hasChildNodes() )
3496 return root.release();
3500 QDomNode childNode = element.firstChild();
3501 while ( !childNode.isNull() )
3503 std::unique_ptr<QgsExpressionNode> operand;
3505 if ( childNode.nodeType() == QDomNode::ElementNode )
3508 const QDomElement operandElem = childNode.toElement();
3512 mErrorMessage = QObject::tr(
"'%1' is an invalid or not supported content for %2:Literal" ).arg( operandElem.tagName(), mPrefix );
3519 QVariant value = childNode.nodeValue();
3521 bool converted =
false;
3526 QDomElement propertyNameElement = element.previousSiblingElement( mPropertyName );
3527 if ( propertyNameElement.isNull() || propertyNameElement.tagName() != mPropertyName )
3529 propertyNameElement = element.nextSiblingElement( mPropertyName );
3531 if ( !propertyNameElement.isNull() || propertyNameElement.tagName() == mPropertyName )
3533 const int fieldIndex = mLayer->
fields().
indexOf( propertyNameElement.firstChild().nodeValue() );
3534 if ( fieldIndex != -1 )
3547 const double d = value.toDouble( &ok );
3560 root = std::move( operand );
3567 childNode = childNode.nextSibling();
3571 return root.release();
3578 if ( element.tagName() != QLatin1String(
"Not" ) )
3581 const QDomElement operandElem = element.firstChildElement();
3585 mErrorMessage = QObject::tr(
"invalid operand for '%1' unary operator" ).arg( element.tagName() );
3595 if ( element.tagName() != QLatin1String(
"PropertyIsNull" ) )
3600 const QDomElement operandElem = element.firstChildElement();
3611 if ( element.isNull() || element.tagName() != QLatin1String(
"Function" ) )
3613 mErrorMessage = QObject::tr(
"%1:Function expected, got %2" ).arg( mPrefix, element.tagName() );
3621 if ( element.attribute( QStringLiteral(
"name" ) ) != funcDef->
name() )
3626 QDomElement operandElem = element.firstChildElement();
3627 while ( !operandElem.isNull() )
3634 args->append( op.release() );
3636 operandElem = operandElem.nextSiblingElement();
3648 std::unique_ptr<QgsExpressionNode> operand;
3649 std::unique_ptr<QgsExpressionNode> lowerBound;
3650 std::unique_ptr<QgsExpressionNode> upperBound;
3652 QDomElement operandElem = element.firstChildElement();
3653 while ( !operandElem.isNull() )
3655 if ( operandElem.tagName() == QLatin1String(
"LowerBoundary" ) )
3657 const QDomElement lowerBoundElem = operandElem.firstChildElement();
3660 else if ( operandElem.tagName() == QLatin1String(
"UpperBoundary" ) )
3662 const QDomElement upperBoundElem = operandElem.firstChildElement();
3671 if ( operand && lowerBound && upperBound )
3674 operandElem = operandElem.nextSiblingElement();
3677 if ( !operand || !lowerBound || !upperBound )
3679 mErrorMessage = QObject::tr(
"missing some required sub-elements in %1:PropertyIsBetween" ).arg( mPrefix );
3690 return mErrorMessage;
3695 const thread_local QRegularExpression re_url( QRegularExpression::anchoredPattern( QStringLiteral(
"http://www\\.opengis\\.net/gml/srs/epsg\\.xml#(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
3696 if (
const QRegularExpressionMatch match = re_url.match( crsName ); match.hasMatch() )
3698 authority = QStringLiteral(
"EPSG" );
3699 code = match.captured( 1 );
3703 const thread_local QRegularExpression re_ogc_urn( QRegularExpression::anchoredPattern( QStringLiteral(
"urn:ogc:def:crs:([^:]+).+(?<=:)([^:]+)" ) ), QRegularExpression::CaseInsensitiveOption );
3704 if (
const QRegularExpressionMatch match = re_ogc_urn.match( crsName ); match.hasMatch() )
3706 authority = match.captured( 1 );
3707 code = match.captured( 2 );
3711 const thread_local QRegularExpression re_x_ogc_urn( QRegularExpression::anchoredPattern( QStringLiteral(
"urn:x-ogc:def:crs:([^:]+).+(?<=:)([^:]+)" ) ), QRegularExpression::CaseInsensitiveOption );
3712 if (
const QRegularExpressionMatch match = re_x_ogc_urn.match( crsName ); match.hasMatch() )
3714 authority = match.captured( 1 );
3715 code = match.captured( 2 );
3719 const thread_local QRegularExpression re_http_uri( QRegularExpression::anchoredPattern( QStringLiteral(
"http://www\\.opengis\\.net/def/crs/([^/]+).+/([^/]+)" ) ), QRegularExpression::CaseInsensitiveOption );
3720 if (
const QRegularExpressionMatch match = re_http_uri.match( crsName ); match.hasMatch() )
3722 authority = match.captured( 1 );
3723 code = match.captured( 2 );
3727 const thread_local QRegularExpression re_auth_code( QRegularExpression::anchoredPattern( QStringLiteral(
"([^:]+):(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
3728 if (
const QRegularExpressionMatch match = re_auth_code.match( crsName ); match.hasMatch() )
3730 authority = match.captured( 1 );
3731 code = match.captured( 2 );
GeometryOperationResult
Success or failure of a geometry operation.
@ Success
Operation succeeded.
WkbType
The WKB type describes the number of dimensions a geometry has.
@ LineString25D
LineString25D.
@ MultiPolygon25D
MultiPolygon25D.
@ MultiLineString25D
MultiLineString25D.
@ MultiPolygon
MultiPolygon.
@ MultiLineString
MultiLineString.
@ MultiPoint25D
MultiPoint25D.
virtual void swapXy()=0
Swaps the x and y coordinates from the geometry.
Qgis::WkbType readHeader() const
readHeader
This class represents a coordinate reference system (CRS).
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
bool createFromUserInput(const QString &definition)
Set up this CRS from various text formats.
bool hasAxisInverted() const
Returns whether axis is inverted (e.g., for WMS 1.3) for the CRS.
Custom exception class for Coordinate Reference System related exceptions.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
A abstract base class for defining QgsExpression functions.
int params() const
The number of parameters this function takes.
virtual bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
Will be called during prepare to determine if the function is static.
QString name() const
The name of the function.
virtual QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
Evaluates the function, first evaluating all required arguments before passing them to the function's...
A binary expression operator, which operates on two values.
QgsExpressionNode * opLeft() const
Returns the node to the left of the operator.
QgsExpressionNode * opRight() const
Returns the node to the right of the operator.
QgsExpressionNodeBinaryOperator::BinaryOperator op() const
Returns the binary operator.
QString text() const
Returns a the name of this operator without the operands.
BinaryOperator
list of binary operators
An expression node which takes it value from a feature's field.
QString name() const
The name of the column.
An expression node for expression functions.
int fnIndex() const
Returns the index of the node's function.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
An expression node for value IN or NOT IN clauses.
QgsExpressionNode * node() const
Returns the expression node.
QgsExpressionNode::NodeList * list() const
Returns the list of nodes to search for matching values within.
bool isNotIn() const
Returns true if this node is a "NOT IN" operator, or false if the node is a normal "IN" operator.
An expression node for literal values.
QVariant value() const
The value of the literal.
A unary node is either negative as in boolean (not) or as in numbers (minus).
QgsExpressionNodeUnaryOperator::UnaryOperator op() const
Returns the unary operator.
QString text() const
Returns a the name of this operator without the operands.
QgsExpressionNode * operand() const
Returns the node the operator will operate upon.
A list of expression nodes.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
Abstract base class for all nodes that can appear in an expression.
bool hasCachedStaticValue() const
Returns true if the node can be replaced by a static cached value.
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
QVariant cachedStaticValue() const
Returns the node's static cached value.
Class for parsing and evaluation of expressions (formerly called "search strings").
static const QList< QgsExpressionFunction * > & Functions()
void setExpression(const QString &expression)
Set the expression string, will reset the whole internal structure.
static int functionIndex(const QString &name)
Returns index of the function in Functions array.
QString dump() const
Returns an expression string, constructed from the internal abstract syntax tree.
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
Encapsulate a field in an attribute table or data source.
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
A geometry is the spatial representation of a feature.
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.
Qgis::WkbType 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.
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const
Export the geometry to WKB.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
QgsCoordinateReferenceSystem crs
@ HTTP_EPSG_DOT_XML
e.g EPSG:4326
@ OGC_HTTP_URI
e.g. urn:x-ogc:def:crs:EPSG::4326
@ X_OGC_URN
e.g. urn:ogc:def:crs:EPSG::4326
@ OGC_URN
e.g. http://www.opengis.net/gml/srs/epsg.xml#4326 (called "OGC HTTP URL" in GeoServer WFS configurati...
@ AUTH_CODE
unknown/unhandled flavor
static CRSFlavor parseCrsName(const QString &crsName, QString &authority, QString &code)
Parse a CRS name in one of the flavors of OGC services, and decompose it as authority and code.
Internal use by QgsOgcUtils.
bool GMLNamespaceUsed() const
Returns whether the gml: namespace is used.
QgsOgcUtilsExprToFilter(QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, QgsOgcUtils::FilterVersion filterVersion, const QString &namespacePrefix, const QString &namespaceURI, const QString &geometryName, const QString &srsName, bool honourAxisOrientation, bool invertAxisOrientation)
Constructor.
QDomElement expressionNodeToOgcFilter(const QgsExpressionNode *node, QgsExpression *expression, const QgsExpressionContext *context)
Convert an expression to a OGC filter.
QString errorMessage() const
Returns the error message.
Internal use by QgsOgcUtils.
QgsExpressionNodeFunction * nodeSpatialOperatorFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with spatial operators.
QgsExpressionNodeUnaryOperator * nodeNotFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with Not operator.
QgsExpressionNodeColumnRef * nodeColumnRefFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with column references.
QgsExpressionNode * nodeIsBetweenFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with boudnaries operator.
QgsOgcUtilsExpressionFromFilter(QgsOgcUtils::FilterVersion version=QgsOgcUtils::FILTER_OGC_1_0, const QgsVectorLayer *layer=nullptr)
Constructor for QgsOgcUtilsExpressionFromFilter.
QgsExpressionNodeBinaryOperator * nodeBinaryOperatorFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with binary operators.
QgsExpressionNodeFunction * nodeFunctionFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with functions.
QgsExpressionNode * nodeFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document element.
QgsExpressionNodeBinaryOperator * nodePropertyIsNullFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with IsNull operator.
QString errorMessage() const
Returns the underlying error message, or an empty string in case of no error.
QgsExpressionNode * nodeLiteralFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with literal tag.
Internal use by QgsOgcUtils.
QgsOgcUtilsSQLStatementToFilter(QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, QgsOgcUtils::FilterVersion filterVersion, const QList< QgsOgcUtils::LayerProperties > &layerProperties, bool honourAxisOrientation, bool invertAxisOrientation, const QMap< QString, QString > &mapUnprefixedTypenameToPrefixedTypename)
Constructor.
QDomElement toOgcFilter(const QgsSQLStatement::Node *node)
Convert a SQL statement to a OGC filter.
bool GMLNamespaceUsed() const
Returns whether the gml: namespace is used.
QString errorMessage() const
Returns the error message.
The QgsOgcUtils class provides various utility functions for conversion between OGC (Open Geospatial ...
static QDomElement elseFilterExpression(QDomDocument &doc)
Creates an ElseFilter from doc.
static QgsRectangle rectangleFromGMLBox(const QDomNode &boxNode)
Read rectangle from GML2 Box.
static QDomElement expressionToOgcExpression(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr, bool requiresFilterElement=false)
Creates an OGC expression XML element from the exp expression with default values for the geometry na...
static QColor colorFromOgcFill(const QDomElement &fillElement)
Parse XML with OGC fill into QColor.
static QDomElement expressionToOgcFilter(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates OGC filter XML element.
FilterVersion
OGC filter version.
static QDomElement SQLStatementToOgcFilter(const QgsSQLStatement &statement, QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, FilterVersion filterVersion, const QList< LayerProperties > &layerProperties, bool honourAxisOrientation, bool invertAxisOrientation, const QMap< QString, QString > &mapUnprefixedTypenameToPrefixedTypename, QString *errorMessage=nullptr)
Creates OGC filter XML element from the WHERE and JOIN clauses of a SQL statement.
static QgsRectangle rectangleFromGMLEnvelope(const QDomNode &envelopeNode)
Read rectangle from GML3 Envelope.
static QDomElement geometryToGML(const QgsGeometry &geometry, QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, const QString &srsName, bool invertAxisOrientation, const QString &gmlIdBase, int precision=17)
Exports the geometry to GML.
static QgsGeometry geometryFromGML(const QString &xmlString, const QgsOgcUtils::Context &context=QgsOgcUtils::Context())
Static method that creates geometry from GML.
static QDomElement rectangleToGMLEnvelope(QgsRectangle *env, QDomDocument &doc, int precision=17)
Exports the rectangle to GML3 Envelope.
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
static QDomElement rectangleToGMLBox(QgsRectangle *box, QDomDocument &doc, int precision=17)
Exports the rectangle to GML2 Box.
A class to represent a 2D point.
A rectangle specified with double values.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
void setYMinimum(double y) SIP_HOLDGIL
Set the minimum y value.
void setXMaximum(double x) SIP_HOLDGIL
Set the maximum x value.
void setXMinimum(double x) SIP_HOLDGIL
Set the minimum x value.
void setYMaximum(double y) SIP_HOLDGIL
Set the maximum y value.
void normalize()
Normalize the rectangle so it has non-negative width/height.
'X BETWEEN y and z' operator
QgsSQLStatement::Node * node() const
Variable at the left of BETWEEN.
QgsSQLStatement::Node * minVal() const
Minimum bound.
bool isNotBetween() const
Whether this is a NOT BETWEEN operator.
QgsSQLStatement::Node * maxVal() const
Maximum bound.
Binary logical/arithmetical operator (AND, OR, =, +, ...)
QgsSQLStatement::Node * opLeft() const
Left operand.
QgsSQLStatement::BinaryOperator op() const
Operator.
QgsSQLStatement::Node * opRight() const
Right operand.
QString name() const
The name of the column.
QString tableName() const
The name of the table. May be empty.
Function with a name and arguments node.
QgsSQLStatement::NodeList * args() const
Returns arguments.
QString name() const
Returns function name.
bool isNotIn() const
Whether this is a NOT IN operator.
QgsSQLStatement::Node * node() const
Variable at the left of IN.
QgsSQLStatement::NodeList * list() const
Values list.
QgsSQLStatement::NodeTableDef * tableDef() const
Table definition.
QgsSQLStatement::Node * onExpr() const
On expression. Will be nullptr if usingColumns() is not empty.
QList< QString > usingColumns() const
Columns referenced by USING.
QList< QgsSQLStatement::Node * > list()
Returns list.
Literal value (integer, integer64, double, string)
QVariant value() const
The value of the literal.
QList< QgsSQLStatement::NodeJoin * > joins() const
Returns the list of joins.
QgsSQLStatement::Node * where() const
Returns the where clause.
QList< QgsSQLStatement::NodeTableDef * > tables() const
Returns the list of tables.
QString name() const
Table name.
QString alias() const
Table alias.
Unary logicial/arithmetical operator ( NOT, - )
QgsSQLStatement::UnaryOperator op() const
Operator.
QgsSQLStatement::Node * operand() const
Operand.
virtual QgsSQLStatement::NodeType nodeType() const =0
Abstract virtual that returns the type of this node.
Class for parsing SQL statements.
BinaryOperator
list of binary operators
static const char * BINARY_OPERATOR_TEXT[]
const QgsSQLStatement::Node * rootNode() const
Returns the root node of the statement.
static const char * UNARY_OPERATOR_TEXT[]
static QString qRegExpEscape(const QString &string)
Returns an escaped string matching the behavior of QRegExp::escape.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
Represents a vector layer which manages a vector based data sets.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Custom exception class for Wkb related exceptions.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
QMap< QString, QString > QgsStringMap
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item.
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
#define QgsDebugMsgLevel(str, level)
Q_GLOBAL_STATIC_WITH_ARGS(IntMap, BINARY_OPERATORS_TAG_NAMES_MAP,({ { QLatin1String("Or"), QgsExpressionNodeBinaryOperator::boOr }, { QLatin1String("And"), QgsExpressionNodeBinaryOperator::boAnd }, { QLatin1String("PropertyIsEqualTo"), QgsExpressionNodeBinaryOperator::boEQ }, { QLatin1String("PropertyIsNotEqualTo"), QgsExpressionNodeBinaryOperator::boNE }, { QLatin1String("PropertyIsLessThanOrEqualTo"), QgsExpressionNodeBinaryOperator::boLE }, { QLatin1String("PropertyIsGreaterThanOrEqualTo"), QgsExpressionNodeBinaryOperator::boGE }, { QLatin1String("PropertyIsLessThan"), QgsExpressionNodeBinaryOperator::boLT }, { QLatin1String("PropertyIsGreaterThan"), QgsExpressionNodeBinaryOperator::boGT }, { QLatin1String("PropertyIsLike"), QgsExpressionNodeBinaryOperator::boLike }, { QLatin1String("Add"), QgsExpressionNodeBinaryOperator::boPlus }, { QLatin1String("Sub"), QgsExpressionNodeBinaryOperator::boMinus }, { QLatin1String("Mul"), QgsExpressionNodeBinaryOperator::boMul }, { QLatin1String("Div"), QgsExpressionNodeBinaryOperator::boDiv }, })) static int binaryOperatorFromTagName(const QString &tagName)
QMap< QString, int > IntMap
const QString & geometryName
const QgsCoordinateReferenceSystem & crs
The Context struct stores the current layer and coordinate transform context.
const QgsMapLayer * layer
QgsCoordinateTransformContext transformContext