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 )
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 axis is inverted (e.g., for WMS 1.3) for the CRS.
Custom exception class for Coordinate Reference System related exceptions.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
A abstract base class for defining QgsExpression functions.
int params() const
The number of parameters this function takes.
virtual bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
Will be called during prepare to determine if the function is static.
QString name() const
The name of the function.
virtual QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
Evaluates the function, first evaluating all required arguments before passing them to the function's...
A binary expression operator, which operates on two values.
QgsExpressionNode * opLeft() const
Returns the node to the left of the operator.
QgsExpressionNode * opRight() const
Returns the node to the right of the operator.
QgsExpressionNodeBinaryOperator::BinaryOperator op() const
Returns the binary operator.
QString text() const
Returns a the name of this operator without the operands.
BinaryOperator
list of binary operators
An expression node which takes it value from a feature's field.
QString name() const
The name of the column.
An expression node for expression functions.
int fnIndex() const
Returns the index of the node's function.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
An expression node for value IN or NOT IN clauses.
QgsExpressionNode * node() const
Returns the expression node.
QgsExpressionNode::NodeList * list() const
Returns the list of nodes to search for matching values within.
bool isNotIn() const
Returns true if this node is a "NOT IN" operator, or false if the node is a normal "IN" operator.
An expression node for literal values.
QVariant value() const
The value of the literal.
A unary node is either negative as in boolean (not) or as in numbers (minus).
QgsExpressionNodeUnaryOperator::UnaryOperator op() const
Returns the unary operator.
QString text() const
Returns a the name of this operator without the operands.
QgsExpressionNode * operand() const
Returns the node the operator will operate upon.
A list of expression nodes.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
Abstract base class for all nodes that can appear in an expression.
bool hasCachedStaticValue() const
Returns true if the node can be replaced by a static cached value.
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
QVariant cachedStaticValue() const
Returns the node's static cached value.
Class for parsing and evaluation of expressions (formerly called "search strings").
static const QList< QgsExpressionFunction * > & Functions()
void setExpression(const QString &expression)
Set the expression string, will reset the whole internal structure.
static int functionIndex(const QString &name)
Returns index of the function in Functions array.
QString dump() const
Returns an expression string, constructed from the internal abstract syntax tree.
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
Encapsulate a field in an attribute table or data source.
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
A geometry is the spatial representation of a feature.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
Qgis::WkbType wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const
Export the geometry to WKB.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
QgsCoordinateReferenceSystem crs
@ HTTP_EPSG_DOT_XML
e.g EPSG:4326
@ OGC_HTTP_URI
e.g. urn:x-ogc:def:crs:EPSG::4326
@ X_OGC_URN
e.g. urn:ogc:def:crs:EPSG::4326
@ OGC_URN
e.g. http://www.opengis.net/gml/srs/epsg.xml#4326 (called "OGC HTTP URL" in GeoServer WFS configurati...
@ AUTH_CODE
unknown/unhandled flavor
static CRSFlavor parseCrsName(const QString &crsName, QString &authority, QString &code)
Parse a CRS name in one of the flavors of OGC services, and decompose it as authority and code.
Internal use by QgsOgcUtils.
bool GMLNamespaceUsed() const
Returns whether the gml: namespace is used.
QgsOgcUtilsExprToFilter(QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, QgsOgcUtils::FilterVersion filterVersion, const QString &namespacePrefix, const QString &namespaceURI, const QString &geometryName, const QString &srsName, bool honourAxisOrientation, bool invertAxisOrientation)
Constructor.
QDomElement expressionNodeToOgcFilter(const QgsExpressionNode *node, QgsExpression *expression, const QgsExpressionContext *context)
Convert an expression to a OGC filter.
QString errorMessage() const
Returns the error message.
Internal use by QgsOgcUtils.
QgsExpressionNodeFunction * nodeSpatialOperatorFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with spatial operators.
QgsExpressionNodeUnaryOperator * nodeNotFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with Not operator.
QgsExpressionNodeColumnRef * nodeColumnRefFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with column references.
QgsExpressionNode * nodeIsBetweenFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with boudnaries operator.
QgsOgcUtilsExpressionFromFilter(QgsOgcUtils::FilterVersion version=QgsOgcUtils::FILTER_OGC_1_0, const QgsVectorLayer *layer=nullptr)
Constructor for QgsOgcUtilsExpressionFromFilter.
QgsExpressionNodeBinaryOperator * nodeBinaryOperatorFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with binary operators.
QgsExpressionNodeFunction * nodeFunctionFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with functions.
QgsExpressionNode * nodeFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document element.
QgsExpressionNodeBinaryOperator * nodePropertyIsNullFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with IsNull operator.
QString errorMessage() const
Returns the underlying error message, or an empty string in case of no error.
QgsExpressionNode * nodeLiteralFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with literal tag.
Internal use by QgsOgcUtils.
QgsOgcUtilsSQLStatementToFilter(QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, QgsOgcUtils::FilterVersion filterVersion, const QList< QgsOgcUtils::LayerProperties > &layerProperties, bool honourAxisOrientation, bool invertAxisOrientation, const QMap< QString, QString > &mapUnprefixedTypenameToPrefixedTypename)
Constructor.
QDomElement toOgcFilter(const QgsSQLStatement::Node *node)
Convert a SQL statement to a OGC filter.
bool GMLNamespaceUsed() const
Returns whether the gml: namespace is used.
QString errorMessage() const
Returns the error message.
The QgsOgcUtils class provides various utility functions for conversion between OGC (Open Geospatial ...
static QDomElement elseFilterExpression(QDomDocument &doc)
Creates an ElseFilter from doc.
static QgsRectangle rectangleFromGMLBox(const QDomNode &boxNode)
Read rectangle from GML2 Box.
static QDomElement expressionToOgcExpression(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr, bool requiresFilterElement=false)
Creates an OGC expression XML element from the exp expression with default values for the geometry na...
static QColor colorFromOgcFill(const QDomElement &fillElement)
Parse XML with OGC fill into QColor.
static QDomElement expressionToOgcFilter(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates OGC filter XML element.
FilterVersion
OGC filter version.
static QDomElement SQLStatementToOgcFilter(const QgsSQLStatement &statement, QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, FilterVersion filterVersion, const QList< LayerProperties > &layerProperties, bool honourAxisOrientation, bool invertAxisOrientation, const QMap< QString, QString > &mapUnprefixedTypenameToPrefixedTypename, QString *errorMessage=nullptr)
Creates OGC filter XML element from the WHERE and JOIN clauses of a SQL statement.
static QgsRectangle rectangleFromGMLEnvelope(const QDomNode &envelopeNode)
Read rectangle from GML3 Envelope.
static QDomElement geometryToGML(const QgsGeometry &geometry, QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, const QString &srsName, bool invertAxisOrientation, const QString &gmlIdBase, int precision=17)
Exports the geometry to GML.
static QgsGeometry geometryFromGML(const QString &xmlString, const QgsOgcUtils::Context &context=QgsOgcUtils::Context())
Static method that creates geometry from GML.
static QDomElement rectangleToGMLEnvelope(QgsRectangle *env, QDomDocument &doc, int precision=17)
Exports the rectangle to GML3 Envelope.
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
static QDomElement rectangleToGMLBox(QgsRectangle *box, QDomDocument &doc, int precision=17)
Exports the rectangle to GML2 Box.
A class to represent a 2D point.
A rectangle specified with double values.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
void setYMinimum(double y) SIP_HOLDGIL
Set the minimum y value.
void setXMaximum(double x) SIP_HOLDGIL
Set the maximum x value.
void setXMinimum(double x) SIP_HOLDGIL
Set the minimum x value.
void setYMaximum(double y) SIP_HOLDGIL
Set the maximum y value.
void normalize()
Normalize the rectangle so it has non-negative width/height.
'X BETWEEN y and z' operator
QgsSQLStatement::Node * node() const
Variable at the left of BETWEEN.
QgsSQLStatement::Node * minVal() const
Minimum bound.
bool isNotBetween() const
Whether this is a NOT BETWEEN operator.
QgsSQLStatement::Node * maxVal() const
Maximum bound.
Binary logical/arithmetical operator (AND, OR, =, +, ...)
QgsSQLStatement::Node * opLeft() const
Left operand.
QgsSQLStatement::BinaryOperator op() const
Operator.
QgsSQLStatement::Node * opRight() const
Right operand.
QString name() const
The name of the column.
QString tableName() const
The name of the table. May be empty.
Function with a name and arguments node.
QgsSQLStatement::NodeList * args() const
Returns arguments.
QString name() const
Returns function name.
bool isNotIn() const
Whether this is a NOT IN operator.
QgsSQLStatement::Node * node() const
Variable at the left of IN.
QgsSQLStatement::NodeList * list() const
Values list.
QgsSQLStatement::NodeTableDef * tableDef() const
Table definition.
QgsSQLStatement::Node * onExpr() const
On expression. Will be nullptr if usingColumns() is not empty.
QList< QString > usingColumns() const
Columns referenced by USING.
QList< QgsSQLStatement::Node * > list()
Returns list.
Literal value (integer, integer64, double, string)
QVariant value() const
The value of the literal.
QList< QgsSQLStatement::NodeJoin * > joins() const
Returns the list of joins.
QgsSQLStatement::Node * where() const
Returns the where clause.
QList< QgsSQLStatement::NodeTableDef * > tables() const
Returns the list of tables.
QString name() const
Table name.
QString alias() const
Table alias.
Unary logicial/arithmetical operator ( NOT, - )
QgsSQLStatement::UnaryOperator op() const
Operator.
QgsSQLStatement::Node * operand() const
Operand.
virtual QgsSQLStatement::NodeType nodeType() const =0
Abstract virtual that returns the type of this node.
Class for parsing SQL statements.
BinaryOperator
list of binary operators
static const char * BINARY_OPERATOR_TEXT[]
const QgsSQLStatement::Node * rootNode() const
Returns the root node of the statement.
static const char * UNARY_OPERATOR_TEXT[]
static QString qRegExpEscape(const QString &string)
Returns an escaped string matching the behavior of QRegExp::escape.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
Represents a vector layer which manages a vector based data sets.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Custom exception class for Wkb related exceptions.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
QMap< QString, QString > QgsStringMap
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item.
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
#define QgsDebugMsgLevel(str, level)
Q_GLOBAL_STATIC_WITH_ARGS(IntMap, BINARY_OPERATORS_TAG_NAMES_MAP,({ { QLatin1String("Or"), QgsExpressionNodeBinaryOperator::boOr }, { QLatin1String("And"), QgsExpressionNodeBinaryOperator::boAnd }, { QLatin1String("PropertyIsEqualTo"), QgsExpressionNodeBinaryOperator::boEQ }, { QLatin1String("PropertyIsNotEqualTo"), QgsExpressionNodeBinaryOperator::boNE }, { QLatin1String("PropertyIsLessThanOrEqualTo"), QgsExpressionNodeBinaryOperator::boLE }, { QLatin1String("PropertyIsGreaterThanOrEqualTo"), QgsExpressionNodeBinaryOperator::boGE }, { QLatin1String("PropertyIsLessThan"), QgsExpressionNodeBinaryOperator::boLT }, { QLatin1String("PropertyIsGreaterThan"), QgsExpressionNodeBinaryOperator::boGT }, { QLatin1String("PropertyIsLike"), QgsExpressionNodeBinaryOperator::boLike }, { QLatin1String("Add"), QgsExpressionNodeBinaryOperator::boPlus }, { QLatin1String("Sub"), QgsExpressionNodeBinaryOperator::boMinus }, { QLatin1String("Mul"), QgsExpressionNodeBinaryOperator::boMul }, { QLatin1String("Div"), QgsExpressionNodeBinaryOperator::boDiv }, })) static int binaryOperatorFromTagName(const QString &tagName)
QMap< QString, int > IntMap
const QString & geometryName
const QgsCoordinateReferenceSystem & crs
The Context struct stores the current layer and coordinate transform context.
const QgsMapLayer * layer
QgsCoordinateTransformContext transformContext