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 )
2222 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2223 eqElem.appendChild( leftNode );
2224 eqElem.appendChild( firstListNode );
2227 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2228 notElem.appendChild( eqElem );
2234 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2237 const auto constList = node->
list()->
list();
2241 if ( !mErrorMessage.isEmpty() )
2242 return QDomElement();
2244 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2245 eqElem.appendChild( leftNode.cloneNode() );
2246 eqElem.appendChild( listNode );
2248 orElem.appendChild( eqElem );
2253 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2254 notElem.appendChild( orElem );
2263 { QLatin1String(
"disjoint" ), QLatin1String(
"Disjoint" ) },
2264 { QLatin1String(
"intersects" ), QLatin1String(
"Intersects" )},
2265 { QLatin1String(
"touches" ), QLatin1String(
"Touches" ) },
2266 { QLatin1String(
"crosses" ), QLatin1String(
"Crosses" ) },
2267 { QLatin1String(
"contains" ), QLatin1String(
"Contains" ) },
2268 { QLatin1String(
"overlaps" ), QLatin1String(
"Overlaps" ) },
2269 { QLatin1String(
"within" ), QLatin1String(
"Within" ) }
2272static
bool isBinarySpatialOperator( const QString &fnName )
2274 return BINARY_SPATIAL_OPS_MAP()->contains( fnName );
2277static QString tagNameForSpatialOperator(
const QString &fnName )
2279 return BINARY_SPATIAL_OPS_MAP()->value( fnName );
2289 return fd->
name() == QLatin1String(
"$geometry" );
2301 if ( fnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2303 const QList<QgsExpressionNode *> &args = fnNode->
args()->
list();
2319 if ( fd->
name() == QLatin1String(
"intersects_bbox" ) )
2321 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2322 Q_ASSERT( argNodes.count() == 2 );
2324 const QgsGeometry geom = geometryFromConstExpr( argNodes[1] );
2325 if ( !geom.
isNull() && isGeometryColumn( argNodes[0] ) )
2335 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":BBOX" );
2337 if ( !mGeometryName.isEmpty() )
2340 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2341 QString columnRef( mGeometryName );
2342 if ( !mNamespacePrefix.isEmpty() && !mNamespaceURI.isEmpty() )
2343 columnRef = mNamespacePrefix + QStringLiteral(
":" ) + columnRef;
2344 geomProperty.appendChild( mDoc.createTextNode( columnRef ) );
2346 funcElem.appendChild( geomProperty );
2348 funcElem.appendChild( elemBox );
2353 mErrorMessage = QObject::tr(
"<BBOX> is currently supported only in form: bbox($geometry, geomFromWKT('…'))" );
2354 return QDomElement();
2358 if ( isBinarySpatialOperator( fd->
name() ) )
2360 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2361 Q_ASSERT( argNodes.count() == 2 );
2364 if ( isGeometryColumn( argNodes[0] ) )
2365 otherNode = argNodes[1];
2366 else if ( isGeometryColumn( argNodes[1] ) )
2367 otherNode = argNodes[0];
2370 mErrorMessage = QObject::tr(
"Unable to translate spatial operator: at least one must refer to geometry." );
2371 return QDomElement();
2374 QDomElement otherGeomElem;
2379 mErrorMessage = QObject::tr(
"spatial operator: the other operator must be a geometry constructor function" );
2380 return QDomElement();
2385 if ( otherFnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2390 mErrorMessage = QObject::tr(
"geom_from_wkt: argument must be string literal" );
2391 return QDomElement();
2396 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2397 if ( otherGeomElem.isNull() )
2399 mErrorMessage = QObject::tr(
"geom_from_wkt: unable to generate GML from wkt geometry" );
2400 return QDomElement();
2404 else if ( otherFnDef->
name() == QLatin1String(
"geom_from_gml" ) )
2409 mErrorMessage = QObject::tr(
"geom_from_gml: argument must be string literal" );
2410 return QDomElement();
2413 QDomDocument geomDoc;
2415 if ( !geomDoc.setContent( gml,
true ) )
2417 mErrorMessage = QObject::tr(
"geom_from_gml: unable to parse XML" );
2418 return QDomElement();
2421 const QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(),
true );
2422 otherGeomElem = geomNode.toElement();
2428 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2429 if ( otherGeomElem.
isNull() )
2431 mErrorMessage = QObject::tr(
"geom from static value: unable to generate GML from static variable" );
2432 return QDomElement();
2438 mErrorMessage = QObject::tr(
"spatial operator: unknown geometry constructor function" );
2439 return QDomElement();
2444 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + tagNameForSpatialOperator( fd->
name() ) );
2445 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2446 QString columnRef( mGeometryName );
2447 if ( !mNamespacePrefix.isEmpty() && !mNamespaceURI.isEmpty() )
2448 columnRef = mNamespacePrefix + QStringLiteral(
":" ) + columnRef;
2449 geomProperty.appendChild( mDoc.createTextNode( columnRef ) );
2450 funcElem.appendChild( geomProperty );
2451 funcElem.appendChild( otherGeomElem );
2455 if ( fd->
isStatic( node, expression, context ) )
2457 const QVariant result = fd->
run( node->
args(), context, expression, node );
2459 return expressionLiteralToOgcFilter( &literal, expression, context );
2464 mErrorMessage = QObject::tr(
"Special columns/constants are not supported." );
2465 return QDomElement();
2469 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
2470 funcElem.setAttribute( QStringLiteral(
"name" ), fd->
name() );
2471 const auto constList = node->
args()->
list();
2475 if ( !mErrorMessage.isEmpty() )
2476 return QDomElement();
2478 funcElem.appendChild( childElem );
2489 const QList<QgsOgcUtils::LayerProperties> &layerProperties,
2490 bool honourAxisOrientation,
2491 bool invertAxisOrientation,
2492 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename )
2495 , mGMLVersion( gmlVersion )
2496 , mFilterVersion( filterVersion )
2497 , mLayerProperties( layerProperties )
2498 , mHonourAxisOrientation( honourAxisOrientation )
2499 , mInvertAxisOrientation( invertAxisOrientation )
2500 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
2501 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
2503 , mMapUnprefixedTypenameToPrefixedTypename( mapUnprefixedTypenameToPrefixedTypename )
2529 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
2530 return QDomElement();
2539 if ( !mErrorMessage.isEmpty() )
2540 return QDomElement();
2543 switch ( node->
op() )
2546 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2551 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
2552 mDoc.removeChild( operandElem );
2556 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
2557 return QDomElement();
2561 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
2562 uoElem.appendChild( operandElem );
2567 return QDomElement();
2577 if ( !mErrorMessage.isEmpty() )
2578 return QDomElement();
2591 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2592 elem.appendChild( leftElem );
2596 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2597 notElem.appendChild( elem );
2611 if ( !mErrorMessage.isEmpty() )
2612 return QDomElement();
2617 opText = QStringLiteral(
"Or" );
2619 opText = QStringLiteral(
"And" );
2621 opText = QStringLiteral(
"PropertyIsEqualTo" );
2623 opText = QStringLiteral(
"PropertyIsNotEqualTo" );
2625 opText = QStringLiteral(
"PropertyIsLessThanOrEqualTo" );
2627 opText = QStringLiteral(
"PropertyIsGreaterThanOrEqualTo" );
2629 opText = QStringLiteral(
"PropertyIsLessThan" );
2631 opText = QStringLiteral(
"PropertyIsGreaterThan" );
2633 opText = QStringLiteral(
"PropertyIsLike" );
2635 opText = QStringLiteral(
"PropertyIsLike" );
2637 if ( opText.isEmpty() )
2641 return QDomElement();
2644 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2649 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2652 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2653 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2655 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2657 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2660 boElem.appendChild( leftElem );
2661 boElem.appendChild( rightElem );
2669 switch ( node->
value().type() )
2672 value = QString::number( node->
value().toInt() );
2674 case QVariant::LongLong:
2675 value = QString::number( node->
value().toLongLong() );
2677 case QVariant::Double:
2680 case QVariant::String:
2681 value = node->
value().toString();
2685 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2686 return QDomElement();
2689 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2690 litElem.appendChild( mDoc.createTextNode( value ) );
2697 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2698 if ( node->
tableName().isEmpty() || mLayerProperties.size() == 1 )
2700 if ( mLayerProperties.size() == 1 && !mLayerProperties[0].mNamespacePrefix.isEmpty() && !mLayerProperties[0].mNamespaceURI.isEmpty() )
2701 propElem.appendChild( mDoc.createTextNode(
2702 mLayerProperties[0].mNamespacePrefix + QStringLiteral(
":" ) + node->
name() ) );
2704 propElem.appendChild( mDoc.createTextNode( node->
name() ) );
2708 QString tableName( mMapTableAliasToNames[node->
tableName()] );
2709 if ( mMapUnprefixedTypenameToPrefixedTypename.contains( tableName ) )
2710 tableName = mMapUnprefixedTypenameToPrefixedTypename[tableName];
2711 propElem.appendChild( mDoc.createTextNode( tableName +
"/" + node->
name() ) );
2718 if ( node->
list()->
list().size() == 1 )
2722 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2723 eqElem.appendChild( leftNode );
2724 eqElem.appendChild( firstListNode );
2727 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2728 notElem.appendChild( eqElem );
2734 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2737 const auto constList = node->
list()->
list();
2741 if ( !mErrorMessage.isEmpty() )
2742 return QDomElement();
2744 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2745 eqElem.appendChild( leftNode.cloneNode() );
2746 eqElem.appendChild( listNode );
2748 orElem.appendChild( eqElem );
2753 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2754 notElem.appendChild( orElem );
2763 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsBetween" );
2765 QDomElement lowerBoundary = mDoc.createElement( mFilterPrefix +
":LowerBoundary" );
2767 elem.appendChild( lowerBoundary );
2768 QDomElement upperBoundary = mDoc.createElement( mFilterPrefix +
":UpperBoundary" );
2770 elem.appendChild( upperBoundary );
2774 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2775 notElem.appendChild( elem );
2782static QString mapBinarySpatialToOgc(
const QString &name )
2784 QString nameCompare( name );
2785#if QT_VERSION < QT_VERSION_CHECK(5, 15, 2)
2786 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2787 nameCompare = name.mid( 3 );
2789 if ( name.size() > 3 && QStringView {name}.mid( 0, 3 ).toString().compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2790 nameCompare = name.mid( 3 );
2792 QStringList spatialOps;
2793 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
2794 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
2795 const auto constSpatialOps = spatialOps;
2796 for ( QString op : constSpatialOps )
2798 if ( nameCompare.compare( op, Qt::CaseInsensitive ) == 0 )
2804static QString mapTernarySpatialToOgc(
const QString &name )
2806 QString nameCompare( name );
2807#if QT_VERSION < QT_VERSION_CHECK(5, 15, 2)
2808 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2809 nameCompare = name.mid( 3 );
2811 if ( name.size() > 3 && QStringView {name}.mid( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2812 nameCompare = name.mid( 3 );
2814 if ( nameCompare.compare( QLatin1String(
"DWithin" ), Qt::CaseInsensitive ) == 0 )
2815 return QStringLiteral(
"DWithin" );
2816 if ( nameCompare.compare( QLatin1String(
"Beyond" ), Qt::CaseInsensitive ) == 0 )
2817 return QStringLiteral(
"Beyond" );
2821QString QgsOgcUtilsSQLStatementToFilter::getGeometryColumnSRSName(
const QgsSQLStatement::Node *node )
2829 const auto constMLayerProperties = mLayerProperties;
2832 if ( prop.mName.compare( mMapTableAliasToNames[col->
tableName()], Qt::CaseInsensitive ) == 0 &&
2833 prop.mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2835 return prop.mSRSName;
2839 if ( !mLayerProperties.empty() &&
2840 mLayerProperties.at( 0 ).mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2842 return mLayerProperties.at( 0 ).mSRSName;
2848 QList<QgsSQLStatement::Node *> args,
2849 bool lastArgIsSRSName,
2851 bool &axisInversion )
2854 axisInversion = mInvertAxisOrientation;
2856 if ( lastArgIsSRSName )
2861 mErrorMessage = QObject::tr(
"%1: Last argument must be string or integer literal" ).arg( mainNode->
name() );
2865 if ( lit->
value().type() == QVariant::Int )
2869 srsName =
"EPSG:" + QString::number( lit->
value().toInt() );
2873 srsName =
"urn:ogc:def:crs:EPSG::" + QString::number( lit->
value().toInt() );
2879 if (
srsName.startsWith( QLatin1String(
"EPSG:" ), Qt::CaseInsensitive ) )
2891 axisInversion = !axisInversion;
2901 if ( node->
name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 )
2903 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2904 if ( args.size() != 1 && args.size() != 2 )
2906 mErrorMessage = QObject::tr(
"Function %1 should have 1 or 2 arguments" ).arg( node->
name() );
2907 return QDomElement();
2913 mErrorMessage = QObject::tr(
"%1: First argument must be string literal" ).arg( node->
name() );
2914 return QDomElement();
2919 if ( ! processSRSName( node, args, args.size() == 2,
srsName, axisInversion ) )
2921 return QDomElement();
2927 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2929 if ( geomElem.isNull() )
2931 mErrorMessage = QObject::tr(
"%1: invalid WKT" ).arg( node->
name() );
2932 return QDomElement();
2939 if ( node->
name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 )
2941 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2942 if ( args.size() != 4 && args.size() != 5 )
2944 mErrorMessage = QObject::tr(
"Function %1 should have 4 or 5 arguments" ).arg( node->
name() );
2945 return QDomElement();
2950 for (
int i = 0; i < 4; i++ )
2955 mErrorMessage = QObject::tr(
"%1: Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2956 return QDomElement();
2960 if ( lit->
value().type() == QVariant::Int )
2961 val = lit->
value().toInt();
2962 else if ( lit->
value().type() == QVariant::LongLong )
2963 val = lit->
value().toLongLong();
2964 else if ( lit->
value().type() == QVariant::Double )
2965 val = lit->
value().toDouble();
2968 mErrorMessage = QObject::tr(
"%1 Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2969 return QDomElement();
2983 if ( ! processSRSName( node, args, args.size() == 5,
srsName, axisInversion ) )
2985 return QDomElement();
2996 if ( node->
name().compare( QLatin1String(
"ST_GeomFromGML" ), Qt::CaseInsensitive ) == 0 )
2998 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2999 if ( args.size() != 1 )
3001 mErrorMessage = QObject::tr(
"Function %1 should have 1 argument" ).arg( node->
name() );
3002 return QDomElement();
3008 mErrorMessage = QObject::tr(
"%1: Argument must be string literal" ).arg( node->
name() );
3009 return QDomElement();
3012 QDomDocument geomDoc;
3014 if ( !geomDoc.setContent( gml,
true ) )
3016 mErrorMessage = QObject::tr(
"ST_GeomFromGML: unable to parse XML" );
3017 return QDomElement();
3020 const QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(),
true );
3022 return geomNode.toElement();
3026 QString ogcName( mapBinarySpatialToOgc( node->
name() ) );
3027 if ( !ogcName.isEmpty() )
3029 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
3030 if ( args.size() != 2 )
3032 mErrorMessage = QObject::tr(
"Function %1 should have 2 arguments" ).arg( node->
name() );
3033 return QDomElement();
3036 for (
int i = 0; i < 2; i ++ )
3039 (
static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
3040 static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
3042 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
3049 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + ogcName );
3050 const auto constArgs = args;
3054 if ( !mErrorMessage.isEmpty() )
3056 mCurrentSRSName.clear();
3057 return QDomElement();
3060 funcElem.appendChild( childElem );
3063 mCurrentSRSName.clear();
3067 ogcName = mapTernarySpatialToOgc( node->
name() );
3068 if ( !ogcName.isEmpty() )
3070 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
3071 if ( args.size() != 3 )
3073 mErrorMessage = QObject::tr(
"Function %1 should have 3 arguments" ).arg( node->
name() );
3074 return QDomElement();
3077 for (
int i = 0; i < 2; i ++ )
3080 (
static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
3081 static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
3083 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
3088 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + node->
name().mid( 3 ) );
3089 for (
int i = 0; i < 2; i++ )
3091 const QDomElement childElem =
toOgcFilter( args[i] );
3092 if ( !mErrorMessage.isEmpty() )
3094 mCurrentSRSName.clear();
3095 return QDomElement();
3098 funcElem.appendChild( childElem );
3100 mCurrentSRSName.clear();
3105 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() );
3106 return QDomElement();
3111 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() );
3112 return QDomElement();
3115 QString unit( QStringLiteral(
"m" ) );
3116 switch ( lit->
value().type() )
3119 distance = QString::number( lit->
value().toInt() );
3121 case QVariant::LongLong:
3122 distance = QString::number( lit->
value().toLongLong() );
3124 case QVariant::Double:
3127 case QVariant::String:
3129 distance = lit->
value().toString();
3130 for (
int i = 0; i < distance.size(); i++ )
3132 if ( !( ( distance[i] >=
'0' && distance[i] <=
'9' ) || distance[i] ==
'-' || distance[i] ==
'.' || distance[i] ==
'e' || distance[i] ==
'E' ) )
3134 unit = distance.mid( i ).trimmed();
3135 distance = distance.mid( 0, i );
3143 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( lit->
value().type() );
3144 return QDomElement();
3147 QDomElement distanceElem = mDoc.createElement( mFilterPrefix +
":Distance" );
3149 distanceElem.setAttribute( QStringLiteral(
"uom" ), unit );
3151 distanceElem.setAttribute( QStringLiteral(
"unit" ), unit );
3152 distanceElem.appendChild( mDoc.createTextNode( distance ) );
3153 funcElem.appendChild( distanceElem );
3158 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
3159 funcElem.setAttribute( QStringLiteral(
"name" ), node->
name() );
3160 const auto constList = node->
args()->
list();
3164 if ( !mErrorMessage.isEmpty() )
3165 return QDomElement();
3167 funcElem.appendChild( childElem );
3173 const QString &leftTable )
3181 QList<QDomElement> listElem;
3183 for (
const QString &columnName : constUsingColumns )
3185 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
3186 QDomElement propElem1 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3187 propElem1.appendChild( mDoc.createTextNode( leftTable +
"/" + columnName ) );
3188 eqElem.appendChild( propElem1 );
3189 QDomElement propElem2 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3190 propElem2.appendChild( mDoc.createTextNode( node->
tableDef()->
name() +
"/" + columnName ) );
3191 eqElem.appendChild( propElem2 );
3192 listElem.append( eqElem );
3195 if ( listElem.size() == 1 )
3199 else if ( listElem.size() > 1 )
3201 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3202 const auto constListElem = listElem;
3203 for (
const QDomElement &elem : constListElem )
3205 andElem.appendChild( elem );
3210 return QDomElement();
3215 if ( node->
alias().isEmpty() )
3217 mMapTableAliasToNames[ node->
name()] = node->
name();
3221 mMapTableAliasToNames[ node->
alias()] = node->
name();
3227 QList<QDomElement> listElem;
3230 ( node->
tables().size() != 1 || !node->
joins().empty() ) )
3232 mErrorMessage = QObject::tr(
"Joins are only supported with WFS 2.0" );
3233 return QDomElement();
3237 const auto constTables = node->
tables();
3242 const auto constJoins = node->
joins();
3245 visit( join->tableDef() );
3249 const QList< QgsSQLStatement::NodeTableDef *> nodeTables = node->
tables();
3250 QString leftTable = nodeTables.at( nodeTables.length() - 1 )->name();
3253 const QDomElement joinElem =
toOgcFilter( join, leftTable );
3254 if ( !mErrorMessage.isEmpty() )
3255 return QDomElement();
3256 listElem.append( joinElem );
3257 leftTable = join->tableDef()->name();
3261 if ( node->
where() )
3264 if ( !mErrorMessage.isEmpty() )
3265 return QDomElement();
3266 listElem.append( whereElem );
3270 if ( listElem.size() == 1 )
3274 else if ( listElem.size() > 1 )
3276 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3277 const auto constListElem = listElem;
3278 for (
const QDomElement &elem : constListElem )
3280 andElem.appendChild( elem );
3285 return QDomElement();
3291 mPropertyName = QStringLiteral(
"PropertyName" );
3292 mPrefix = QStringLiteral(
"ogc" );
3296 mPropertyName = QStringLiteral(
"ValueReference" );
3297 mPrefix = QStringLiteral(
"fes" );
3303 if ( element.isNull() )
3307 if ( isBinaryOperator( element.tagName() ) )
3313 if ( isSpatialOperator( element.tagName() ) )
3319 if ( element.tagName() == QLatin1String(
"Not" ) )
3323 else if ( element.tagName() == QLatin1String(
"PropertyIsNull" ) )
3327 else if ( element.tagName() == QLatin1String(
"Literal" ) )
3331 else if ( element.tagName() == QLatin1String(
"Function" ) )
3335 else if ( element.tagName() == mPropertyName )
3339 else if ( element.tagName() == QLatin1String(
"PropertyIsBetween" ) )
3344 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() );
3350 if ( element.isNull() )
3353 int op = binaryOperatorFromTagName( element.tagName() );
3356 mErrorMessage = QObject::tr(
"'%1' binary operator not supported." ).arg( element.tagName() );
3360 if ( op ==
QgsExpressionNodeBinaryOperator::boLike && element.hasAttribute( QStringLiteral(
"matchCase" ) ) && element.attribute( QStringLiteral(
"matchCase" ) ) == QLatin1String(
"false" ) )
3365 QDomElement operandElem = element.firstChildElement();
3370 mErrorMessage = QObject::tr(
"invalid left operand for '%1' binary operator" ).arg( element.tagName() );
3374 const std::unique_ptr<QgsExpressionNode> leftOp( expr->clone() );
3375 for ( operandElem = operandElem.nextSiblingElement(); !operandElem.isNull(); operandElem = operandElem.nextSiblingElement() )
3380 mErrorMessage = QObject::tr(
"invalid right operand for '%1' binary operator" ).arg( element.tagName() );
3387 if ( element.hasAttribute( QStringLiteral(
"wildCard" ) ) )
3389 wildCard = element.attribute( QStringLiteral(
"wildCard" ) );
3392 if ( element.hasAttribute( QStringLiteral(
"singleChar" ) ) )
3394 singleChar = element.attribute( QStringLiteral(
"singleChar" ) );
3396 QString escape = QStringLiteral(
"\\" );
3397 if ( element.hasAttribute( QStringLiteral(
"escape" ) ) )
3399 escape = element.attribute( QStringLiteral(
"escape" ) );
3401 if ( element.hasAttribute( QStringLiteral(
"escapeChar" ) ) )
3403 escape = element.attribute( QStringLiteral(
"escapeChar" ) );
3407 if ( !wildCard.isEmpty() && wildCard != QLatin1String(
"%" ) )
3409 oprValue.replace(
'%', QLatin1String(
"\\%" ) );
3410 if ( oprValue.startsWith( wildCard ) )
3412 oprValue.replace( 0, 1, QStringLiteral(
"%" ) );
3415 QRegularExpressionMatch match = rx.match( oprValue );
3417 while ( match.hasMatch() )
3419 pos = match.capturedStart();
3420 oprValue.replace( pos + 1, 1, QStringLiteral(
"%" ) );
3422 match = rx.match( oprValue, pos );
3424 oprValue.replace( escape + wildCard, wildCard );
3426 if ( !singleChar.isEmpty() && singleChar != QLatin1String(
"_" ) )
3428 oprValue.replace(
'_', QLatin1String(
"\\_" ) );
3429 if ( oprValue.startsWith( singleChar ) )
3431 oprValue.replace( 0, 1, QStringLiteral(
"_" ) );
3434 QRegularExpressionMatch match = rx.match( oprValue );
3436 while ( match.hasMatch() )
3438 pos = match.capturedStart();
3439 oprValue.replace( pos + 1, 1, QStringLiteral(
"_" ) );
3441 match = rx.match( oprValue, pos );
3443 oprValue.replace( escape + singleChar, singleChar );
3445 if ( !escape.isEmpty() && escape != QLatin1String(
"\\" ) )
3447 oprValue.replace( escape + escape, escape );
3455 if ( expr == leftOp )
3457 mErrorMessage = QObject::tr(
"only one operand for '%1' binary operator" ).arg( element.tagName() );
3471 QDomElement childElem = element.firstChildElement();
3473 while ( !childElem.isNull() && gml2Str.isEmpty() )
3475 if ( childElem.tagName() != mPropertyName )
3477 QTextStream gml2Stream( &gml2Str );
3478 childElem.save( gml2Stream, 0 );
3480 childElem = childElem.nextSiblingElement();
3482 if ( !gml2Str.isEmpty() )
3488 mErrorMessage = QObject::tr(
"No OGC Geometry found" );
3501 if ( element.isNull() || element.tagName() != mPropertyName )
3503 mErrorMessage = QObject::tr(
"%1:PropertyName expected, got %2" ).arg( mPrefix, element.tagName() );
3512 if ( element.isNull() || element.tagName() != QLatin1String(
"Literal" ) )
3514 mErrorMessage = QObject::tr(
"%1:Literal expected, got %2" ).arg( mPrefix, element.tagName() );
3518 std::unique_ptr<QgsExpressionNode> root;
3519 if ( !element.hasChildNodes() )
3522 return root.release();
3526 QDomNode childNode = element.firstChild();
3527 while ( !childNode.isNull() )
3529 std::unique_ptr<QgsExpressionNode> operand;
3531 if ( childNode.nodeType() == QDomNode::ElementNode )
3534 const QDomElement operandElem = childNode.toElement();
3538 mErrorMessage = QObject::tr(
"'%1' is an invalid or not supported content for %2:Literal" ).arg( operandElem.tagName(), mPrefix );
3545 QVariant value = childNode.nodeValue();
3547 bool converted =
false;
3552 QDomElement propertyNameElement = element.previousSiblingElement( mPropertyName );
3553 if ( propertyNameElement.isNull() || propertyNameElement.tagName() != mPropertyName )
3555 propertyNameElement = element.nextSiblingElement( mPropertyName );
3557 if ( !propertyNameElement.isNull() || propertyNameElement.tagName() == mPropertyName )
3559 const int fieldIndex = mLayer->
fields().
indexOf( propertyNameElement.firstChild().nodeValue() );
3560 if ( fieldIndex != -1 )
3562 const QgsField field = mLayer->
fields().
field( propertyNameElement.firstChild().nodeValue() );
3573 const double d = value.toDouble( &ok );
3586 root = std::move( operand );
3593 childNode = childNode.nextSibling();
3597 return root.release();
3604 if ( element.tagName() != QLatin1String(
"Not" ) )
3607 const QDomElement operandElem = element.firstChildElement();
3611 mErrorMessage = QObject::tr(
"invalid operand for '%1' unary operator" ).arg( element.tagName() );
3621 if ( element.tagName() != QLatin1String(
"PropertyIsNull" ) )
3626 const QDomElement operandElem = element.firstChildElement();
3637 if ( element.isNull() || element.tagName() != QLatin1String(
"Function" ) )
3639 mErrorMessage = QObject::tr(
"%1:Function expected, got %2" ).arg( mPrefix, element.tagName() );
3647 if ( element.attribute( QStringLiteral(
"name" ) ) != funcDef->
name() )
3652 QDomElement operandElem = element.firstChildElement();
3653 while ( !operandElem.isNull() )
3660 args->append( op.release() );
3662 operandElem = operandElem.nextSiblingElement();
3674 std::unique_ptr<QgsExpressionNode> operand;
3675 std::unique_ptr<QgsExpressionNode> lowerBound;
3676 std::unique_ptr<QgsExpressionNode> upperBound;
3678 QDomElement operandElem = element.firstChildElement();
3679 while ( !operandElem.isNull() )
3681 if ( operandElem.tagName() == QLatin1String(
"LowerBoundary" ) )
3683 const QDomElement lowerBoundElem = operandElem.firstChildElement();
3686 else if ( operandElem.tagName() == QLatin1String(
"UpperBoundary" ) )
3688 const QDomElement upperBoundElem = operandElem.firstChildElement();
3697 if ( operand && lowerBound && upperBound )
3700 operandElem = operandElem.nextSiblingElement();
3703 if ( !operand || !lowerBound || !upperBound )
3705 mErrorMessage = QObject::tr(
"missing some required sub-elements in %1:PropertyIsBetween" ).arg( mPrefix );
3716 return mErrorMessage;
3721 const thread_local QRegularExpression re_url( QRegularExpression::anchoredPattern( QStringLiteral(
"http://www\\.opengis\\.net/gml/srs/epsg\\.xml#(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
3722 if (
const QRegularExpressionMatch match = re_url.match( crsName ); match.hasMatch() )
3724 authority = QStringLiteral(
"EPSG" );
3725 code = match.captured( 1 );
3729 const thread_local QRegularExpression re_ogc_urn( QRegularExpression::anchoredPattern( QStringLiteral(
"urn:ogc:def:crs:([^:]+).+(?<=:)([^:]+)" ) ), QRegularExpression::CaseInsensitiveOption );
3730 if (
const QRegularExpressionMatch match = re_ogc_urn.match( crsName ); match.hasMatch() )
3732 authority = match.captured( 1 );
3733 code = match.captured( 2 );
3737 const thread_local QRegularExpression re_x_ogc_urn( QRegularExpression::anchoredPattern( QStringLiteral(
"urn:x-ogc:def:crs:([^:]+).+(?<=:)([^:]+)" ) ), QRegularExpression::CaseInsensitiveOption );
3738 if (
const QRegularExpressionMatch match = re_x_ogc_urn.match( crsName ); match.hasMatch() )
3740 authority = match.captured( 1 );
3741 code = match.captured( 2 );
3745 const thread_local QRegularExpression re_http_uri( QRegularExpression::anchoredPattern( QStringLiteral(
"http://www\\.opengis\\.net/def/crs/([^/]+).+/([^/]+)" ) ), QRegularExpression::CaseInsensitiveOption );
3746 if (
const QRegularExpressionMatch match = re_http_uri.match( crsName ); match.hasMatch() )
3748 authority = match.captured( 1 );
3749 code = match.captured( 2 );
3753 const thread_local QRegularExpression re_auth_code( QRegularExpression::anchoredPattern( QStringLiteral(
"([^:]+):(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
3754 if (
const QRegularExpressionMatch match = re_auth_code.match( crsName ); match.hasMatch() )
3756 authority = match.captured( 1 );
3757 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 the axis order is inverted for the CRS compared to the order east/north (longitude/la...
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.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const
Export the geometry to WKB.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
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 xMinimum() const
Returns the x minimum value (left side of rectangle).
void setYMinimum(double y)
Set the minimum y value.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
void setXMinimum(double x)
Set the minimum x value.
double xMaximum() const
Returns the x maximum value (right side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
void setYMaximum(double y)
Set the maximum y value.
void setXMaximum(double x)
Set the maximum x 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