28 #include <QStringList> 29 #include <QTextStream> 33 #include <netinet/in.h> 39 static const QString
GML_NAMESPACE = QStringLiteral(
"http://www.opengis.net/gml" );
40 static const QString GML32_NAMESPACE = QStringLiteral(
"http://www.opengis.net/gml/3.2" );
41 static const QString OGC_NAMESPACE = QStringLiteral(
"http://www.opengis.net/ogc" );
42 static const QString FES_NAMESPACE = QStringLiteral(
"http://www.opengis.net/fes/2.0" );
48 const QString &srsName,
49 bool honourAxisOrientation,
50 bool invertAxisOrientation )
53 , mGMLVersion( gmlVersion )
54 , mFilterVersion( filterVersion )
55 , mGeometryName( geometryName )
57 , mInvertAxisOrientation( invertAxisOrientation )
58 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
59 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
63 if ( !mSrsName.isEmpty() )
69 mInvertAxisOrientation = !mInvertAxisOrientation;
76 QDomElement geometryTypeElement = geometryNode.toElement();
77 QString geomType = geometryTypeElement.tagName();
79 if ( !( geomType == QLatin1String(
"Point" ) || geomType == QLatin1String(
"LineString" ) || geomType == QLatin1String(
"Polygon" ) ||
80 geomType == QLatin1String(
"MultiPoint" ) || geomType == QLatin1String(
"MultiLineString" ) || geomType == QLatin1String(
"MultiPolygon" ) ||
81 geomType == QLatin1String(
"Box" ) || geomType == QLatin1String(
"Envelope" ) ) )
83 QDomNode geometryChild = geometryNode.firstChild();
84 if ( geometryChild.isNull() )
88 geometryTypeElement = geometryChild.toElement();
89 geomType = geometryTypeElement.tagName();
92 if ( !( geomType == QLatin1String(
"Point" ) || geomType == QLatin1String(
"LineString" ) || geomType == QLatin1String(
"Polygon" ) ||
93 geomType == QLatin1String(
"MultiPoint" ) || geomType == QLatin1String(
"MultiLineString" ) || geomType == QLatin1String(
"MultiPolygon" ) ||
94 geomType == QLatin1String(
"Box" ) || geomType == QLatin1String(
"Envelope" ) ) )
97 if ( geomType == QLatin1String(
"Point" ) )
99 return geometryFromGMLPoint( geometryTypeElement );
101 else if ( geomType == QLatin1String(
"LineString" ) )
103 return geometryFromGMLLineString( geometryTypeElement );
105 else if ( geomType == QLatin1String(
"Polygon" ) )
107 return geometryFromGMLPolygon( geometryTypeElement );
109 else if ( geomType == QLatin1String(
"MultiPoint" ) )
111 return geometryFromGMLMultiPoint( geometryTypeElement );
113 else if ( geomType == QLatin1String(
"MultiLineString" ) )
115 return geometryFromGMLMultiLineString( geometryTypeElement );
117 else if ( geomType == QLatin1String(
"MultiPolygon" ) )
119 return geometryFromGMLMultiPolygon( geometryTypeElement );
121 else if ( geomType == QLatin1String(
"Box" ) )
125 else if ( geomType == QLatin1String(
"Envelope" ) )
138 QString xml = QStringLiteral(
"<tmp xmlns=\"%1\" xmlns:gml=\"%1\">%2</tmp>" ).arg(
GML_NAMESPACE, xmlString );
140 if ( !doc.setContent( xml,
true ) )
143 return geometryFromGML( doc.documentElement().firstChildElement() );
147 QgsGeometry QgsOgcUtils::geometryFromGMLPoint(
const QDomElement &geometryElement )
151 QDomNodeList coordList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
152 if ( !coordList.isEmpty() )
154 QDomElement coordElement = coordList.at( 0 ).toElement();
155 if ( readGMLCoordinates( pointCoordinate, coordElement ) != 0 )
162 QDomNodeList posList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pos" ) );
163 if ( posList.size() < 1 )
167 QDomElement posElement = posList.at( 0 ).toElement();
168 if ( readGMLPositions( pointCoordinate, posElement ) != 0 )
174 if ( pointCoordinate.empty() )
179 QgsPolylineXY::const_iterator point_it = pointCoordinate.constBegin();
180 char e = htonl( 1 ) != 1;
181 double x = point_it->x();
182 double y = point_it->y();
183 int size = 1 +
sizeof( int ) + 2 *
sizeof(
double );
186 unsigned char *wkb =
new unsigned char[size];
189 memcpy( &( wkb )[wkbPosition], &e, 1 );
191 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
192 wkbPosition +=
sizeof( int );
193 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
194 wkbPosition +=
sizeof( double );
195 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
202 QgsGeometry QgsOgcUtils::geometryFromGMLLineString(
const QDomElement &geometryElement )
206 QDomNodeList coordList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
207 if ( !coordList.isEmpty() )
209 QDomElement coordElement = coordList.at( 0 ).toElement();
210 if ( readGMLCoordinates( lineCoordinates, coordElement ) != 0 )
217 QDomNodeList posList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
218 if ( posList.size() < 1 )
222 QDomElement posElement = posList.at( 0 ).toElement();
223 if ( readGMLPositions( lineCoordinates, posElement ) != 0 )
229 char e = htonl( 1 ) != 1;
230 int size = 1 + 2 *
sizeof( int ) + lineCoordinates.size() * 2 *
sizeof( double );
233 unsigned char *wkb =
new unsigned char[size];
237 int nPoints = lineCoordinates.size();
240 memcpy( &( wkb )[wkbPosition], &e, 1 );
242 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
243 wkbPosition +=
sizeof( int );
244 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
245 wkbPosition +=
sizeof( int );
247 QgsPolylineXY::const_iterator iter;
248 for ( iter = lineCoordinates.constBegin(); iter != lineCoordinates.constEnd(); ++iter )
252 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
253 wkbPosition +=
sizeof( double );
254 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
255 wkbPosition +=
sizeof( double );
263 QgsGeometry QgsOgcUtils::geometryFromGMLPolygon(
const QDomElement &geometryElement )
270 QDomNodeList outerBoundaryList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"outerBoundaryIs" ) );
271 if ( !outerBoundaryList.isEmpty() )
273 QDomElement coordinatesElement = outerBoundaryList.at( 0 ).firstChild().firstChild().toElement();
274 if ( coordinatesElement.isNull() )
278 if ( readGMLCoordinates( exteriorPointList, coordinatesElement ) != 0 )
282 ringCoordinates.push_back( exteriorPointList );
285 QDomNodeList innerBoundaryList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"innerBoundaryIs" ) );
286 for (
int i = 0; i < innerBoundaryList.size(); ++i )
289 coordinatesElement = innerBoundaryList.at( i ).firstChild().firstChild().toElement();
290 if ( coordinatesElement.isNull() )
294 if ( readGMLCoordinates( interiorPointList, coordinatesElement ) != 0 )
298 ringCoordinates.push_back( interiorPointList );
304 QDomNodeList exteriorList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"exterior" ) );
305 if ( exteriorList.size() < 1 )
309 QDomElement posElement = exteriorList.at( 0 ).firstChild().firstChild().toElement();
310 if ( posElement.isNull() )
314 if ( readGMLPositions( exteriorPointList, posElement ) != 0 )
318 ringCoordinates.push_back( exteriorPointList );
321 QDomNodeList interiorList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"interior" ) );
322 for (
int i = 0; i < interiorList.size(); ++i )
325 QDomElement posElement = interiorList.at( i ).firstChild().firstChild().toElement();
326 if ( posElement.isNull() )
330 if ( readGMLPositions( interiorPointList, posElement ) != 0 )
334 ringCoordinates.push_back( interiorPointList );
339 int nrings = ringCoordinates.size();
344 for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
346 npoints += it->size();
348 int size = 1 + 2 *
sizeof( int ) + nrings *
sizeof(
int ) + 2 * npoints *
sizeof( double );
351 unsigned char *wkb =
new unsigned char[size];
354 char e = htonl( 1 ) != 1;
356 int nPointsInRing = 0;
360 memcpy( &( wkb )[wkbPosition], &e, 1 );
362 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
363 wkbPosition +=
sizeof( int );
364 memcpy( &( wkb )[wkbPosition], &nrings,
sizeof(
int ) );
365 wkbPosition +=
sizeof( int );
366 for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
368 nPointsInRing = it->size();
369 memcpy( &( wkb )[wkbPosition], &nPointsInRing,
sizeof(
int ) );
370 wkbPosition +=
sizeof( int );
372 QgsPolylineXY::const_iterator iter;
373 for ( iter = it->begin(); iter != it->end(); ++iter )
378 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
379 wkbPosition +=
sizeof( double );
380 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
381 wkbPosition +=
sizeof( double );
390 QgsGeometry QgsOgcUtils::geometryFromGMLMultiPoint(
const QDomElement &geometryElement )
394 QDomNodeList pointMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pointMember" ) );
395 if ( pointMemberList.size() < 1 )
399 QDomNodeList pointNodeList;
401 QDomNodeList coordinatesList;
402 QDomNodeList posList;
403 for (
int i = 0; i < pointMemberList.size(); ++i )
406 pointNodeList = pointMemberList.at( i ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"Point" ) );
407 if ( pointNodeList.size() < 1 )
412 coordinatesList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
413 if ( !coordinatesList.isEmpty() )
415 currentPoint.clear();
416 if ( readGMLCoordinates( currentPoint, coordinatesList.at( 0 ).toElement() ) != 0 )
420 if ( currentPoint.empty() )
424 pointList.push_back( ( *currentPoint.begin() ) );
430 posList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pos" ) );
431 if ( posList.size() < 1 )
435 currentPoint.clear();
436 if ( readGMLPositions( currentPoint, posList.at( 0 ).toElement() ) != 0 )
440 if ( currentPoint.empty() )
444 pointList.push_back( ( *currentPoint.begin() ) );
448 int nPoints = pointList.size();
453 int size = 1 + 2 *
sizeof( int ) + pointList.size() * ( 2 *
sizeof( double ) + 1 +
sizeof(
int ) );
456 unsigned char *wkb =
new unsigned char[size];
459 char e = htonl( 1 ) != 1;
462 memcpy( &( wkb )[wkbPosition], &e, 1 );
464 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
465 wkbPosition +=
sizeof( int );
466 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
467 wkbPosition +=
sizeof( int );
469 for ( QgsPolylineXY::const_iterator it = pointList.constBegin(); it != pointList.constEnd(); ++it )
471 memcpy( &( wkb )[wkbPosition], &e, 1 );
473 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
474 wkbPosition +=
sizeof( int );
476 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
477 wkbPosition +=
sizeof( double );
479 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
480 wkbPosition +=
sizeof( double );
488 QgsGeometry QgsOgcUtils::geometryFromGMLMultiLineString(
const QDomElement &geometryElement )
499 QList< QgsPolylineXY > lineCoordinates;
500 QDomElement currentLineStringElement;
501 QDomNodeList currentCoordList;
502 QDomNodeList currentPosList;
504 QDomNodeList lineStringMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"lineStringMember" ) );
505 if ( !lineStringMemberList.isEmpty() )
507 for (
int i = 0; i < lineStringMemberList.size(); ++i )
509 QDomNodeList lineStringNodeList = lineStringMemberList.at( i ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LineString" ) );
510 if ( lineStringNodeList.size() < 1 )
514 currentLineStringElement = lineStringNodeList.at( 0 ).toElement();
515 currentCoordList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
516 if ( !currentCoordList.isEmpty() )
519 if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
523 lineCoordinates.push_back( currentPointList );
527 currentPosList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
528 if ( currentPosList.size() < 1 )
533 if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
537 lineCoordinates.push_back( currentPointList );
543 QDomNodeList lineStringList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LineString" ) );
544 if ( !lineStringList.isEmpty() )
546 for (
int i = 0; i < lineStringList.size(); ++i )
548 currentLineStringElement = lineStringList.at( i ).toElement();
549 currentCoordList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
550 if ( !currentCoordList.isEmpty() )
553 if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
557 lineCoordinates.push_back( currentPointList );
562 currentPosList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
563 if ( currentPosList.size() < 1 )
568 if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
572 lineCoordinates.push_back( currentPointList );
582 int nLines = lineCoordinates.size();
587 int size = ( lineCoordinates.size() + 1 ) * ( 1 + 2 *
sizeof(
int ) );
588 for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
590 size += it->size() * 2 *
sizeof( double );
594 unsigned char *wkb =
new unsigned char[size];
597 char e = htonl( 1 ) != 1;
601 memcpy( &( wkb )[wkbPosition], &e, 1 );
603 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
604 wkbPosition +=
sizeof( int );
605 memcpy( &( wkb )[wkbPosition], &nLines,
sizeof(
int ) );
606 wkbPosition +=
sizeof( int );
608 for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
610 memcpy( &( wkb )[wkbPosition], &e, 1 );
612 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
613 wkbPosition +=
sizeof( int );
614 nPoints = it->size();
615 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
616 wkbPosition +=
sizeof( int );
617 for ( QgsPolylineXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
622 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
623 wkbPosition +=
sizeof( double );
624 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
625 wkbPosition +=
sizeof( double );
634 QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon(
const QDomElement &geometryElement )
638 QDomElement currentPolygonMemberElement;
639 QDomNodeList polygonList;
640 QDomElement currentPolygonElement;
642 QDomNodeList outerBoundaryList;
643 QDomElement currentOuterBoundaryElement;
644 QDomNodeList innerBoundaryList;
645 QDomElement currentInnerBoundaryElement;
647 QDomNodeList exteriorList;
648 QDomElement currentExteriorElement;
649 QDomElement currentInteriorElement;
650 QDomNodeList interiorList;
652 QDomNodeList linearRingNodeList;
653 QDomElement currentLinearRingElement;
655 QDomNodeList currentCoordinateList;
656 QDomNodeList currentPosList;
658 QDomNodeList polygonMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"polygonMember" ) );
660 for (
int i = 0; i < polygonMemberList.size(); ++i )
662 currentPolygonList.resize( 0 );
663 currentPolygonMemberElement = polygonMemberList.at( i ).toElement();
664 polygonList = currentPolygonMemberElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"Polygon" ) );
665 if ( polygonList.size() < 1 )
669 currentPolygonElement = polygonList.at( 0 ).toElement();
672 outerBoundaryList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"outerBoundaryIs" ) );
673 if ( !outerBoundaryList.isEmpty() )
675 currentOuterBoundaryElement = outerBoundaryList.at( 0 ).toElement();
678 linearRingNodeList = currentOuterBoundaryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
679 if ( linearRingNodeList.size() < 1 )
683 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
684 currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
685 if ( currentCoordinateList.size() < 1 )
689 if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
693 currentPolygonList.push_back( ringCoordinates );
696 QDomNodeList innerBoundaryList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"innerBoundaryIs" ) );
697 for (
int j = 0; j < innerBoundaryList.size(); ++j )
700 currentInnerBoundaryElement = innerBoundaryList.at( j ).toElement();
701 linearRingNodeList = currentInnerBoundaryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
702 if ( linearRingNodeList.size() < 1 )
706 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
707 currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
708 if ( currentCoordinateList.size() < 1 )
712 if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
716 currentPolygonList.push_back( ringCoordinates );
722 exteriorList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"exterior" ) );
723 if ( exteriorList.size() < 1 )
728 currentExteriorElement = exteriorList.at( 0 ).toElement();
731 linearRingNodeList = currentExteriorElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
732 if ( linearRingNodeList.size() < 1 )
736 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
737 currentPosList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
738 if ( currentPosList.size() < 1 )
742 if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
746 currentPolygonList.push_back( ringPositions );
749 QDomNodeList interiorList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"interior" ) );
750 for (
int j = 0; j < interiorList.size(); ++j )
753 currentInteriorElement = interiorList.at( j ).toElement();
754 linearRingNodeList = currentInteriorElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
755 if ( linearRingNodeList.size() < 1 )
759 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
760 currentPosList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
761 if ( currentPosList.size() < 1 )
765 if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
769 currentPolygonList.push_back( ringPositions );
772 multiPolygonPoints.push_back( currentPolygonList );
775 int nPolygons = multiPolygonPoints.size();
779 int size = 1 + 2 *
sizeof( int );
781 for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
783 size += 1 + 2 *
sizeof( int );
784 for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
786 size +=
sizeof( int ) + 2 * iter->size() *
sizeof( double );
791 unsigned char *wkb =
new unsigned char[size];
793 char e = htonl( 1 ) != 1;
800 memcpy( &( wkb )[wkbPosition], &e, 1 );
802 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
803 wkbPosition +=
sizeof( int );
804 memcpy( &( wkb )[wkbPosition], &nPolygons,
sizeof(
int ) );
805 wkbPosition +=
sizeof( int );
809 for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
811 memcpy( &( wkb )[wkbPosition], &e, 1 );
813 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
814 wkbPosition +=
sizeof( int );
816 memcpy( &( wkb )[wkbPosition], &nRings,
sizeof(
int ) );
817 wkbPosition +=
sizeof( int );
818 for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
820 nPointsInRing = iter->size();
821 memcpy( &( wkb )[wkbPosition], &nPointsInRing,
sizeof(
int ) );
822 wkbPosition +=
sizeof( int );
823 for ( QgsPolylineXY::const_iterator iterator = iter->begin(); iterator != iter->end(); ++iterator )
827 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
828 wkbPosition +=
sizeof( double );
829 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
830 wkbPosition +=
sizeof( double );
840 bool QgsOgcUtils::readGMLCoordinates(
QgsPolylineXY &coords,
const QDomElement &elem )
842 QString coordSeparator = QStringLiteral(
"," );
843 QString tupelSeparator = QStringLiteral(
" " );
848 if ( elem.hasAttribute( QStringLiteral(
"cs" ) ) )
850 coordSeparator = elem.attribute( QStringLiteral(
"cs" ) );
852 if ( elem.hasAttribute( QStringLiteral(
"ts" ) ) )
854 tupelSeparator = elem.attribute( QStringLiteral(
"ts" ) );
857 QStringList tupels = elem.text().split( tupelSeparator, QString::SkipEmptyParts );
858 QStringList tupel_coords;
860 bool conversionSuccess;
862 QStringList::const_iterator it;
863 for ( it = tupels.constBegin(); it != tupels.constEnd(); ++it )
865 tupel_coords = ( *it ).split( coordSeparator, QString::SkipEmptyParts );
866 if ( tupel_coords.size() < 2 )
870 x = tupel_coords.at( 0 ).toDouble( &conversionSuccess );
871 if ( !conversionSuccess )
875 y = tupel_coords.at( 1 ).toDouble( &conversionSuccess );
876 if ( !conversionSuccess )
889 QDomElement boxElem = boxNode.toElement();
890 if ( boxElem.tagName() != QLatin1String(
"Box" ) )
893 QDomElement bElem = boxElem.firstChild().toElement();
894 QString coordSeparator = QStringLiteral(
"," );
895 QString tupelSeparator = QStringLiteral(
" " );
896 if ( bElem.hasAttribute( QStringLiteral(
"cs" ) ) )
898 coordSeparator = bElem.attribute( QStringLiteral(
"cs" ) );
900 if ( bElem.hasAttribute( QStringLiteral(
"ts" ) ) )
902 tupelSeparator = bElem.attribute( QStringLiteral(
"ts" ) );
905 QString bString = bElem.text();
906 bool ok1, ok2, ok3, ok4;
907 double xmin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 0, 0 ).toDouble( &ok1 );
908 double ymin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 1, 1 ).toDouble( &ok2 );
909 double xmax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 0, 0 ).toDouble( &ok3 );
910 double ymax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 1, 1 ).toDouble( &ok4 );
912 if ( ok1 && ok2 && ok3 && ok4 )
921 bool QgsOgcUtils::readGMLPositions(
QgsPolylineXY &coords,
const QDomElement &elem )
925 QStringList pos = elem.text().split(
' ', QString::SkipEmptyParts );
927 bool conversionSuccess;
928 int posSize = pos.size();
930 int srsDimension = 2;
931 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
933 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
934 if ( !conversionSuccess )
939 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
941 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
942 if ( !conversionSuccess )
948 for (
int i = 0; i < posSize / srsDimension; i++ )
950 x = pos.at( i * srsDimension ).toDouble( &conversionSuccess );
951 if ( !conversionSuccess )
955 y = pos.at( i * srsDimension + 1 ).toDouble( &conversionSuccess );
956 if ( !conversionSuccess )
970 QDomElement envelopeElem = envelopeNode.toElement();
971 if ( envelopeElem.tagName() != QLatin1String(
"Envelope" ) )
974 QDomNodeList lowerCornerList = envelopeElem.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"lowerCorner" ) );
975 if ( lowerCornerList.size() < 1 )
978 QDomNodeList upperCornerList = envelopeElem.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"upperCorner" ) );
979 if ( upperCornerList.size() < 1 )
982 bool conversionSuccess;
983 int srsDimension = 2;
985 QDomElement elem = lowerCornerList.at( 0 ).toElement();
986 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
988 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
989 if ( !conversionSuccess )
994 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
996 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
997 if ( !conversionSuccess )
1002 QString bString = elem.text();
1004 double xmin = bString.section(
' ', 0, 0 ).toDouble( &conversionSuccess );
1005 if ( !conversionSuccess )
1007 double ymin = bString.section(
' ', 1, 1 ).toDouble( &conversionSuccess );
1008 if ( !conversionSuccess )
1011 elem = upperCornerList.at( 0 ).toElement();
1012 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
1014 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
1015 if ( !conversionSuccess )
1020 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1022 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1023 if ( !conversionSuccess )
1029 Q_UNUSED( srsDimension );
1031 bString = elem.text();
1032 double xmax = bString.section(
' ', 0, 0 ).toDouble( &conversionSuccess );
1033 if ( !conversionSuccess )
1035 double ymax = bString.section(
' ', 1, 1 ).toDouble( &conversionSuccess );
1036 if ( !conversionSuccess )
1047 return rectangleToGMLBox( box, doc, QString(),
false, precision );
1051 const QString &srsName,
1052 bool invertAxisOrientation,
1057 return QDomElement();
1060 QDomElement boxElem = doc.createElement( QStringLiteral(
"gml:Box" ) );
1061 if ( !srsName.isEmpty() )
1063 boxElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1065 QDomElement coordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1066 coordElem.setAttribute( QStringLiteral(
"cs" ), QStringLiteral(
"," ) );
1067 coordElem.setAttribute( QStringLiteral(
"ts" ), QStringLiteral(
" " ) );
1069 QString coordString;
1078 QDomText coordText = doc.createTextNode( coordString );
1079 coordElem.appendChild( coordText );
1080 boxElem.appendChild( coordElem );
1087 return rectangleToGMLEnvelope( env, doc, QString(),
false, precision );
1091 const QString &srsName,
1092 bool invertAxisOrientation,
1097 return QDomElement();
1100 QDomElement envElem = doc.createElement( QStringLiteral(
"gml:Envelope" ) );
1101 if ( !srsName.isEmpty() )
1103 envElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1107 QDomElement lowerCornerElem = doc.createElement( QStringLiteral(
"gml:lowerCorner" ) );
1111 QDomText lowerCornerText = doc.createTextNode( posList );
1112 lowerCornerElem.appendChild( lowerCornerText );
1113 envElem.appendChild( lowerCornerElem );
1115 QDomElement upperCornerElem = doc.createElement( QStringLiteral(
"gml:upperCorner" ) );
1119 QDomText upperCornerText = doc.createTextNode( posList );
1120 upperCornerElem.appendChild( upperCornerText );
1121 envElem.appendChild( upperCornerElem );
1128 return geometryToGML( geometry, doc, ( format == QLatin1String(
"GML2" ) ) ? GML_2_1_2 : GML_3_2_1, QString(),
false, QString(), precision );
1133 const QString &srsName,
1134 bool invertAxisOrientation,
1135 const QString &gmlIdBase,
1139 return QDomElement();
1142 QString cs = QStringLiteral(
"," );
1144 QString ts = QStringLiteral(
" " );
1146 QDomElement baseCoordElem;
1148 bool hasZValue =
false;
1150 QByteArray wkb( geometry.
asWkb() );
1154 wkbPtr.readHeader();
1160 return QDomElement();
1163 if ( gmlVersion != GML_2_1_2 )
1171 baseCoordElem = doc.createElement( QStringLiteral(
"gml:pos" ) );
1174 baseCoordElem = doc.createElement( QStringLiteral(
"gml:posList" ) );
1177 baseCoordElem.setAttribute( QStringLiteral(
"srsDimension" ), QStringLiteral(
"2" ) );
1182 baseCoordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1183 baseCoordElem.setAttribute( QStringLiteral(
"cs" ), cs );
1184 baseCoordElem.setAttribute( QStringLiteral(
"ts" ), ts );
1194 QDomElement pointElem = doc.createElement( QStringLiteral(
"gml:Point" ) );
1195 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1196 pointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1197 if ( !srsName.isEmpty() )
1198 pointElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1199 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1203 if ( invertAxisOrientation )
1209 coordElem.appendChild( coordText );
1210 pointElem.appendChild( coordElem );
1219 QDomElement multiPointElem = doc.createElement( QStringLiteral(
"gml:MultiPoint" ) );
1220 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1221 multiPointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1222 if ( !srsName.isEmpty() )
1223 multiPointElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1228 for (
int idx = 0; idx < nPoints; ++idx )
1230 QDomElement pointMemberElem = doc.createElement( QStringLiteral(
"gml:pointMember" ) );
1231 QDomElement pointElem = doc.createElement( QStringLiteral(
"gml:Point" ) );
1232 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1233 pointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( idx + 1 ) );
1234 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1236 wkbPtr.readHeader();
1239 if ( invertAxisOrientation )
1245 coordElem.appendChild( coordText );
1246 pointElem.appendChild( coordElem );
1250 wkbPtr +=
sizeof( double );
1252 pointMemberElem.appendChild( pointElem );
1253 multiPointElem.appendChild( pointMemberElem );
1255 return multiPointElem;
1263 QDomElement lineStringElem = doc.createElement( QStringLiteral(
"gml:LineString" ) );
1264 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1265 lineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1266 if ( !srsName.isEmpty() )
1267 lineStringElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1273 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1274 QString coordString;
1275 for (
int idx = 0; idx < nPoints; ++idx )
1283 if ( invertAxisOrientation )
1291 wkbPtr +=
sizeof( double );
1294 QDomText coordText = doc.createTextNode( coordString );
1295 coordElem.appendChild( coordText );
1296 lineStringElem.appendChild( coordElem );
1297 return lineStringElem;
1305 QDomElement multiLineStringElem = doc.createElement( QStringLiteral(
"gml:MultiLineString" ) );
1306 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1307 multiLineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1308 if ( !srsName.isEmpty() )
1309 multiLineStringElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1314 for (
int jdx = 0; jdx < nLines; jdx++ )
1316 QDomElement lineStringMemberElem = doc.createElement( QStringLiteral(
"gml:lineStringMember" ) );
1317 QDomElement lineStringElem = doc.createElement( QStringLiteral(
"gml:LineString" ) );
1318 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1319 lineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( jdx + 1 ) );
1321 wkbPtr.readHeader();
1326 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1327 QString coordString;
1328 for (
int idx = 0; idx < nPoints; idx++ )
1336 if ( invertAxisOrientation )
1345 wkbPtr +=
sizeof( double );
1348 QDomText coordText = doc.createTextNode( coordString );
1349 coordElem.appendChild( coordText );
1350 lineStringElem.appendChild( coordElem );
1351 lineStringMemberElem.appendChild( lineStringElem );
1352 multiLineStringElem.appendChild( lineStringMemberElem );
1354 return multiLineStringElem;
1362 QDomElement polygonElem = doc.createElement( QStringLiteral(
"gml:Polygon" ) );
1363 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1364 polygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1365 if ( !srsName.isEmpty() )
1366 polygonElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1372 if ( numRings == 0 )
1373 return QDomElement();
1375 int *ringNumPoints =
new int[numRings];
1377 for (
int idx = 0; idx < numRings; idx++ )
1379 QString boundaryName = ( gmlVersion == GML_2_1_2 ) ?
"gml:outerBoundaryIs" :
"gml:exterior";
1382 boundaryName = ( gmlVersion == GML_2_1_2 ) ?
"gml:innerBoundaryIs" :
"gml:interior";
1384 QDomElement boundaryElem = doc.createElement( boundaryName );
1385 QDomElement ringElem = doc.createElement( QStringLiteral(
"gml:LinearRing" ) );
1389 ringNumPoints[idx] = nPoints;
1391 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1392 QString coordString;
1393 for (
int jdx = 0; jdx < nPoints; jdx++ )
1401 if ( invertAxisOrientation )
1409 wkbPtr +=
sizeof( double );
1412 QDomText coordText = doc.createTextNode( coordString );
1413 coordElem.appendChild( coordText );
1414 ringElem.appendChild( coordElem );
1415 boundaryElem.appendChild( ringElem );
1416 polygonElem.appendChild( boundaryElem );
1418 delete [] ringNumPoints;
1427 QDomElement multiPolygonElem = doc.createElement( QStringLiteral(
"gml:MultiPolygon" ) );
1428 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1429 multiPolygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1430 if ( !srsName.isEmpty() )
1431 multiPolygonElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1434 wkbPtr >> numPolygons;
1436 for (
int kdx = 0; kdx < numPolygons; kdx++ )
1438 QDomElement polygonMemberElem = doc.createElement( QStringLiteral(
"gml:polygonMember" ) );
1439 QDomElement polygonElem = doc.createElement( QStringLiteral(
"gml:Polygon" ) );
1440 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1441 polygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( kdx + 1 ) );
1443 wkbPtr.readHeader();
1448 for (
int idx = 0; idx < numRings; idx++ )
1450 QString boundaryName = ( gmlVersion == GML_2_1_2 ) ?
"gml:outerBoundaryIs" :
"gml:exterior";
1453 boundaryName = ( gmlVersion == GML_2_1_2 ) ?
"gml:innerBoundaryIs" :
"gml:interior";
1455 QDomElement boundaryElem = doc.createElement( boundaryName );
1456 QDomElement ringElem = doc.createElement( QStringLiteral(
"gml:LinearRing" ) );
1461 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1462 QString coordString;
1463 for (
int jdx = 0; jdx < nPoints; jdx++ )
1471 if ( invertAxisOrientation )
1480 wkbPtr +=
sizeof( double );
1483 QDomText coordText = doc.createTextNode( coordString );
1484 coordElem.appendChild( coordText );
1485 ringElem.appendChild( coordElem );
1486 boundaryElem.appendChild( ringElem );
1487 polygonElem.appendChild( boundaryElem );
1488 polygonMemberElem.appendChild( polygonElem );
1489 multiPolygonElem.appendChild( polygonMemberElem );
1492 return multiPolygonElem;
1495 return QDomElement();
1501 return QDomElement();
1507 return geometryToGML( geometry, doc, QStringLiteral(
"GML2" ), precision );
1510 QDomElement QgsOgcUtils::createGMLCoordinates(
const QgsPolylineXY &points, QDomDocument &doc )
1512 QDomElement coordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1513 coordElem.setAttribute( QStringLiteral(
"cs" ), QStringLiteral(
"," ) );
1514 coordElem.setAttribute( QStringLiteral(
"ts" ), QStringLiteral(
" " ) );
1516 QString coordString;
1517 QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
1518 for ( ; pointIt != points.constEnd(); ++pointIt )
1520 if ( pointIt != points.constBegin() )
1529 QDomText coordText = doc.createTextNode( coordString );
1530 coordElem.appendChild( coordText );
1534 QDomElement QgsOgcUtils::createGMLPositions(
const QgsPolylineXY &points, QDomDocument &doc )
1536 QDomElement posElem = doc.createElement( QStringLiteral(
"gml:pos" ) );
1537 if ( points.size() > 1 )
1538 posElem = doc.createElement( QStringLiteral(
"gml:posList" ) );
1539 posElem.setAttribute( QStringLiteral(
"srsDimension" ), QStringLiteral(
"2" ) );
1541 QString coordString;
1542 QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
1543 for ( ; pointIt != points.constEnd(); ++pointIt )
1545 if ( pointIt != points.constBegin() )
1554 QDomText coordText = doc.createTextNode( coordString );
1555 posElem.appendChild( coordText );
1565 if ( fillElement.isNull() || !fillElement.hasChildNodes() )
1573 QDomElement cssElem = fillElement.firstChildElement( QStringLiteral(
"CssParameter" ) );
1574 while ( !cssElem.isNull() )
1576 cssName = cssElem.attribute( QStringLiteral(
"name" ), QStringLiteral(
"not_found" ) );
1577 if ( cssName != QLatin1String(
"not_found" ) )
1579 elemText = cssElem.text();
1580 if ( cssName == QLatin1String(
"fill" ) )
1582 color.setNamedColor( elemText );
1584 else if ( cssName == QLatin1String(
"fill-opacity" ) )
1587 double opacity = elemText.toDouble( &ok );
1590 color.setAlphaF( opacity );
1595 cssElem = cssElem.nextSiblingElement( QStringLiteral(
"CssParameter" ) );
1609 if ( element.isNull() || !element.hasChildNodes() )
1616 if ( element.firstChild().nodeType() == QDomNode::TextNode )
1626 QDomElement childElem = element.firstChildElement();
1627 while ( !childElem.isNull() )
1639 if ( !expr->d->mRootNode )
1641 expr->d->mRootNode = node;
1648 childElem = childElem.nextSiblingElement();
1652 expr->d->mExp = expr->
dump();
1657 static const QMap<QString, int> BINARY_OPERATORS_TAG_NAMES_MAP
1677 static int binaryOperatorFromTagName(
const QString &tagName )
1680 return BINARY_OPERATORS_TAG_NAMES_MAP.value( tagName, -1 );
1687 return QStringLiteral(
"PropertyIsLike" );
1689 return BINARY_OPERATORS_TAG_NAMES_MAP.key( op, QString() );
1692 static bool isBinaryOperator(
const QString &tagName )
1694 return binaryOperatorFromTagName( tagName ) >= 0;
1698 static bool isSpatialOperator(
const QString &tagName )
1700 static QStringList spatialOps;
1701 if ( spatialOps.isEmpty() )
1703 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
1704 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
1707 return spatialOps.contains( tagName );
1788 return expressionToOgcFilter( exp, doc, GML_2_1_2, FILTER_OGC_1_0,
1789 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage );
1794 return expressionToOgcExpression( exp, doc, GML_2_1_2, FILTER_OGC_1_0,
1795 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage );
1803 const QString &srsName,
1804 bool honourAxisOrientation,
1805 bool invertAxisOrientation,
1809 return QDomElement();
1815 QgsOgcUtilsExprToFilter utils( doc, gmlVersion, filterVersion, geometryName, srsName, honourAxisOrientation, invertAxisOrientation );
1819 if ( exprRootElem.isNull() )
1820 return QDomElement();
1822 QDomElement filterElem =
1823 ( filterVersion == FILTER_FES_2_0 ) ?
1824 doc.createElementNS( FES_NAMESPACE, QStringLiteral(
"fes:Filter" ) ) :
1825 doc.createElementNS( OGC_NAMESPACE, QStringLiteral(
"ogc:Filter" ) );
1828 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:gml" ) );
1829 if ( gmlVersion == GML_3_2_1 )
1830 attr.setValue( GML32_NAMESPACE );
1833 filterElem.setAttributeNode( attr );
1835 filterElem.appendChild( exprRootElem );
1844 const QString &srsName,
1845 bool honourAxisOrientation,
1846 bool invertAxisOrientation,
1856 return QDomElement();
1864 QgsOgcUtilsExprToFilter utils( doc, gmlVersion, filterVersion, geometryName, srsName, honourAxisOrientation, invertAxisOrientation );
1870 if ( !exprRootElem.isNull() )
1872 return exprRootElem;
1879 *errorMessage = QObject::tr(
"Node type not supported in expression translation: %1" ).arg( node->
nodeType() );
1883 return QDomElement();
1890 const QList<LayerProperties> &layerProperties,
1891 bool honourAxisOrientation,
1892 bool invertAxisOrientation,
1893 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename,
1897 return QDomElement();
1900 layerProperties, honourAxisOrientation, invertAxisOrientation,
1901 mapUnprefixedTypenameToPrefixedTypename );
1905 if ( exprRootElem.isNull() )
1906 return QDomElement();
1908 QDomElement filterElem =
1909 ( filterVersion == FILTER_FES_2_0 ) ?
1910 doc.createElementNS( FES_NAMESPACE, QStringLiteral(
"fes:Filter" ) ) :
1911 doc.createElementNS( OGC_NAMESPACE, QStringLiteral(
"ogc:Filter" ) );
1914 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:gml" ) );
1915 if ( gmlVersion == GML_3_2_1 )
1916 attr.setValue( GML32_NAMESPACE );
1919 filterElem.setAttributeNode( attr );
1921 filterElem.appendChild( exprRootElem );
1933 return expressionUnaryOperatorToOgcFilter( static_cast<const QgsExpressionNodeUnaryOperator *>( node ), expression, context );
1935 return expressionBinaryOperatorToOgcFilter( static_cast<const QgsExpressionNodeBinaryOperator *>( node ), expression, context );
1937 return expressionInOperatorToOgcFilter( static_cast<const QgsExpressionNodeInOperator *>( node ), expression, context );
1939 return expressionFunctionToOgcFilter( static_cast<const QgsExpressionNodeFunction *>( node ), expression, context );
1941 return expressionLiteralToOgcFilter( static_cast<const QgsExpressionNodeLiteral *>( node ), expression, context );
1943 return expressionColumnRefToOgcFilter( static_cast<const QgsExpressionNodeColumnRef *>( node ), expression, context );
1946 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
1947 return QDomElement();
1954 if ( !mErrorMessage.isEmpty() )
1955 return QDomElement();
1958 switch ( node->
op() )
1961 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
1966 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
1967 mDoc.removeChild( operandElem );
1971 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
1972 return QDomElement();
1976 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
1977 uoElem.appendChild( operandElem );
1981 mErrorMessage = QObject::tr(
"Unary operator '%1' not implemented yet" ).arg( node->
text() );
1982 return QDomElement();
1992 if ( !mErrorMessage.isEmpty() )
1993 return QDomElement();
2003 if ( rightLit->
value().isNull() )
2006 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2007 elem.appendChild( leftElem );
2011 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2012 notElem.appendChild( elem );
2026 if ( !mErrorMessage.isEmpty() )
2027 return QDomElement();
2030 QString opText = binaryOperatorToTagName( op );
2031 if ( opText.isEmpty() )
2035 mErrorMessage = QObject::tr(
"Binary operator %1 not implemented yet" ).arg( node->
text() );
2036 return QDomElement();
2039 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2044 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2047 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2048 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2050 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2052 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2055 boElem.appendChild( leftElem );
2056 boElem.appendChild( rightElem );
2063 Q_UNUSED( expression )
2066 switch ( node->
value().type() )
2069 value = QString::number( node->
value().toInt() );
2071 case QVariant::Double:
2074 case QVariant::String:
2075 value = node->
value().toString();
2077 case QVariant::Date:
2078 value = node->
value().toDate().toString( Qt::ISODate );
2080 case QVariant::DateTime:
2081 value = node->
value().toDateTime().toString( Qt::ISODate );
2085 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2086 return QDomElement();
2089 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2090 litElem.appendChild( mDoc.createTextNode( value ) );
2097 Q_UNUSED( expression )
2099 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2100 propElem.appendChild( mDoc.createTextNode( node->
name() ) );
2108 if ( node->
list()->
list().size() == 1 )
2111 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2117 if ( !mErrorMessage.isEmpty() )
2118 return QDomElement();
2120 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2121 eqElem.appendChild( leftNode.cloneNode() );
2122 eqElem.appendChild( listNode );
2124 orElem.appendChild( eqElem );
2129 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2130 notElem.appendChild( orElem );
2137 static const QMap<QString, QString> BINARY_SPATIAL_OPS_MAP
2139 { QStringLiteral(
"disjoint" ), QStringLiteral(
"Disjoint" ) },
2140 { QStringLiteral(
"intersects" ), QStringLiteral(
"Intersects" )},
2141 { QStringLiteral(
"touches" ), QStringLiteral(
"Touches" ) },
2142 { QStringLiteral(
"crosses" ), QStringLiteral(
"Crosses" ) },
2143 { QStringLiteral(
"contains" ), QStringLiteral(
"Contains" ) },
2144 { QStringLiteral(
"overlaps" ), QStringLiteral(
"Overlaps" ) },
2145 { QStringLiteral(
"within" ), QStringLiteral(
"Within" ) }
2148 static bool isBinarySpatialOperator(
const QString &fnName )
2150 return BINARY_SPATIAL_OPS_MAP.contains( fnName );
2153 static QString tagNameForSpatialOperator(
const QString &fnName )
2155 return BINARY_SPATIAL_OPS_MAP.value( fnName );
2165 return fd->
name() == QLatin1String(
"$geometry" );
2177 if ( fnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2179 const QList<QgsExpressionNode *> &args = fnNode->
args()->
list();
2195 if ( fd->
name() == QLatin1String(
"intersects_bbox" ) )
2197 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2198 Q_ASSERT( argNodes.count() == 2 );
2200 QgsGeometry geom = geometryFromConstExpr( argNodes[1] );
2201 if ( !geom.isNull() && isGeometryColumn( argNodes[0] ) )
2211 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2212 geomProperty.appendChild( mDoc.createTextNode( mGeometryName ) );
2214 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":BBOX" );
2215 funcElem.appendChild( geomProperty );
2216 funcElem.appendChild( elemBox );
2221 mErrorMessage = QObject::tr(
"<BBOX> is currently supported only in form: bbox($geometry, geomFromWKT('…'))" );
2222 return QDomElement();
2226 if ( isBinarySpatialOperator( fd->
name() ) )
2228 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2229 Q_ASSERT( argNodes.count() == 2 );
2232 if ( isGeometryColumn( argNodes[0] ) )
2233 otherNode = argNodes[1];
2234 else if ( isGeometryColumn( argNodes[1] ) )
2235 otherNode = argNodes[0];
2238 mErrorMessage = QObject::tr(
"Unable to translate spatial operator: at least one must refer to geometry." );
2239 return QDomElement();
2242 QDomElement otherGeomElem;
2247 mErrorMessage = QObject::tr(
"spatial operator: the other operator must be a geometry constructor function" );
2248 return QDomElement();
2253 if ( otherFnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2258 mErrorMessage = QObject::tr(
"geom_from_wkt: argument must be string literal" );
2259 return QDomElement();
2264 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2267 else if ( otherFnDef->
name() == QLatin1String(
"geom_from_gml" ) )
2272 mErrorMessage = QObject::tr(
"geom_from_gml: argument must be string literal" );
2273 return QDomElement();
2276 QDomDocument geomDoc;
2278 if ( !geomDoc.setContent( gml,
true ) )
2280 mErrorMessage = QObject::tr(
"geom_from_gml: unable to parse XML" );
2281 return QDomElement();
2284 QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(), true );
2285 otherGeomElem = geomNode.toElement();
2289 mErrorMessage = QObject::tr(
"spatial operator: unknown geometry constructor function" );
2290 return QDomElement();
2295 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + tagNameForSpatialOperator( fd->
name() ) );
2296 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2297 geomProperty.appendChild( mDoc.createTextNode( mGeometryName ) );
2298 funcElem.appendChild( geomProperty );
2299 funcElem.appendChild( otherGeomElem );
2303 if ( fd->
isStatic( node, expression, context ) )
2305 QVariant result = fd->
run( node->
args(), context, expression, node );
2307 return expressionLiteralToOgcFilter( &literal, expression, context );
2312 mErrorMessage = QObject::tr(
"Special columns/constants are not supported." );
2313 return QDomElement();
2317 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
2318 funcElem.setAttribute( QStringLiteral(
"name" ), fd->
name() );
2322 if ( !mErrorMessage.isEmpty() )
2323 return QDomElement();
2325 funcElem.appendChild( childElem );
2336 const QList<QgsOgcUtils::LayerProperties> &layerProperties,
2337 bool honourAxisOrientation,
2338 bool invertAxisOrientation,
2339 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename )
2342 , mGMLVersion( gmlVersion )
2343 , mFilterVersion( filterVersion )
2344 , mLayerProperties( layerProperties )
2345 , mHonourAxisOrientation( honourAxisOrientation )
2346 , mInvertAxisOrientation( invertAxisOrientation )
2347 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
2348 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
2350 , mMapUnprefixedTypenameToPrefixedTypename( mapUnprefixedTypenameToPrefixedTypename )
2359 return toOgcFilter( static_cast<const QgsSQLStatement::NodeUnaryOperator *>( node ) );
2361 return toOgcFilter( static_cast<const QgsSQLStatement::NodeBinaryOperator *>( node ) );
2363 return toOgcFilter( static_cast<const QgsSQLStatement::NodeInOperator *>( node ) );
2365 return toOgcFilter( static_cast<const QgsSQLStatement::NodeBetweenOperator *>( node ) );
2367 return toOgcFilter( static_cast<const QgsSQLStatement::NodeFunction *>( node ) );
2369 return toOgcFilter( static_cast<const QgsSQLStatement::NodeLiteral *>( node ) );
2371 return toOgcFilter( static_cast<const QgsSQLStatement::NodeColumnRef *>( node ) );
2373 return toOgcFilter( static_cast<const QgsSQLStatement::NodeSelect *>( node ) );
2376 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
2377 return QDomElement();
2386 if ( !mErrorMessage.isEmpty() )
2387 return QDomElement();
2390 switch ( node->
op() )
2393 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2398 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
2399 mDoc.removeChild( operandElem );
2403 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
2404 return QDomElement();
2408 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
2409 uoElem.appendChild( operandElem );
2414 return QDomElement();
2424 if ( !mErrorMessage.isEmpty() )
2425 return QDomElement();
2435 if ( rightLit->
value().isNull() )
2438 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2439 elem.appendChild( leftElem );
2443 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2444 notElem.appendChild( elem );
2458 if ( !mErrorMessage.isEmpty() )
2459 return QDomElement();
2464 opText = QStringLiteral(
"Or" );
2466 opText = QStringLiteral(
"And" );
2468 opText = QStringLiteral(
"PropertyIsEqualTo" );
2470 opText = QStringLiteral(
"PropertyIsNotEqualTo" );
2472 opText = QStringLiteral(
"PropertyIsLessThanOrEqualTo" );
2474 opText = QStringLiteral(
"PropertyIsGreaterThanOrEqualTo" );
2476 opText = QStringLiteral(
"PropertyIsLessThan" );
2478 opText = QStringLiteral(
"PropertyIsGreaterThan" );
2480 opText = QStringLiteral(
"PropertyIsLike" );
2482 opText = QStringLiteral(
"PropertyIsLike" );
2484 if ( opText.isEmpty() )
2488 return QDomElement();
2491 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2496 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2499 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2500 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2502 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2504 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2507 boElem.appendChild( leftElem );
2508 boElem.appendChild( rightElem );
2516 switch ( node->
value().type() )
2519 value = QString::number( node->
value().toInt() );
2521 case QVariant::LongLong:
2522 value = QString::number( node->
value().toLongLong() );
2524 case QVariant::Double:
2527 case QVariant::String:
2528 value = node->
value().toString();
2532 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2533 return QDomElement();
2536 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2537 litElem.appendChild( mDoc.createTextNode( value ) );
2544 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2545 if ( node->
tableName().isEmpty() || mLayerProperties.size() == 1 )
2546 propElem.appendChild( mDoc.createTextNode( node->
name() ) );
2549 QString tableName( mMapTableAliasToNames[node->
tableName()] );
2550 if ( mMapUnprefixedTypenameToPrefixedTypename.contains( tableName ) )
2551 tableName = mMapUnprefixedTypenameToPrefixedTypename[tableName];
2552 propElem.appendChild( mDoc.createTextNode( tableName +
"/" + node->
name() ) );
2559 if ( node->
list()->
list().size() == 1 )
2562 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2568 if ( !mErrorMessage.isEmpty() )
2569 return QDomElement();
2571 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2572 eqElem.appendChild( leftNode.cloneNode() );
2573 eqElem.appendChild( listNode );
2575 orElem.appendChild( eqElem );
2580 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2581 notElem.appendChild( orElem );
2590 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsBetween" );
2592 QDomElement lowerBoundary = mDoc.createElement( mFilterPrefix +
":LowerBoundary" );
2594 elem.appendChild( lowerBoundary );
2595 QDomElement upperBoundary = mDoc.createElement( mFilterPrefix +
":UpperBoundary" );
2597 elem.appendChild( upperBoundary );
2601 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2602 notElem.appendChild( elem );
2609 static QString mapBinarySpatialToOgc(
const QString &name )
2611 QString nameCompare( name );
2612 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2613 nameCompare = name.mid( 3 );
2614 QStringList spatialOps;
2615 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
2616 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
2617 Q_FOREACH ( QString op, spatialOps )
2619 if ( nameCompare.compare( op, Qt::CaseInsensitive ) == 0 )
2625 static QString mapTernarySpatialToOgc(
const QString &name )
2627 QString nameCompare( name );
2628 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2629 nameCompare = name.mid( 3 );
2630 if ( nameCompare.compare( QLatin1String(
"DWithin" ), Qt::CaseInsensitive ) == 0 )
2631 return QStringLiteral(
"DWithin" );
2632 if ( nameCompare.compare( QLatin1String(
"Beyond" ), Qt::CaseInsensitive ) == 0 )
2633 return QStringLiteral(
"Beyond" );
2637 QString QgsOgcUtilsSQLStatementToFilter::getGeometryColumnSRSName(
const QgsSQLStatement::Node *node )
2647 if ( prop.
mName.compare( mMapTableAliasToNames[col->
tableName()], Qt::CaseInsensitive ) == 0 &&
2654 if ( !mLayerProperties.empty() &&
2655 mLayerProperties.at( 0 ).mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2657 return mLayerProperties.at( 0 ).mSRSName;
2663 QList<QgsSQLStatement::Node *> args,
2664 bool lastArgIsSRSName,
2666 bool &axisInversion )
2668 srsName = mCurrentSRSName;
2669 axisInversion = mInvertAxisOrientation;
2671 if ( lastArgIsSRSName )
2676 mErrorMessage = QObject::tr(
"%1: Last argument must be string or integer literal" ).arg( mainNode->
name() );
2680 if ( lit->
value().type() == QVariant::Int )
2684 srsName =
"EPSG:" + QString::number( lit->
value().toInt() );
2688 srsName =
"urn:ogc:def:crs:EPSG::" + QString::number( lit->
value().toInt() );
2693 srsName = lit->
value().toString();
2694 if ( srsName.startsWith( QLatin1String(
"EPSG:" ), Qt::CaseInsensitive ) )
2700 if ( !srsName.isEmpty() )
2706 axisInversion = !axisInversion;
2716 if ( node->
name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 )
2718 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2719 if ( args.size() != 1 && args.size() != 2 )
2721 mErrorMessage = QObject::tr(
"Function %1 should have 1 or 2 arguments" ).arg( node->
name() );
2722 return QDomElement();
2728 mErrorMessage = QObject::tr(
"%1: First argument must be string literal" ).arg( node->
name() );
2729 return QDomElement();
2734 if ( ! processSRSName( node, args, args.size() == 2, srsName, axisInversion ) )
2736 return QDomElement();
2742 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2744 if ( geomElem.isNull() )
2746 mErrorMessage = QObject::tr(
"%1: invalid WKT" ).arg( node->
name() );
2747 return QDomElement();
2754 if ( node->
name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 )
2756 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2757 if ( args.size() != 4 && args.size() != 5 )
2759 mErrorMessage = QObject::tr(
"Function %1 should have 4 or 5 arguments" ).arg( node->
name() );
2760 return QDomElement();
2765 for (
int i = 0; i < 4; i++ )
2770 mErrorMessage = QObject::tr(
"%1: Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2771 return QDomElement();
2775 if ( lit->
value().type() == QVariant::Int )
2776 val = lit->
value().toInt();
2777 else if ( lit->
value().type() == QVariant::LongLong )
2778 val = lit->
value().toLongLong();
2779 else if ( lit->
value().type() == QVariant::Double )
2780 val = lit->
value().toDouble();
2783 mErrorMessage = QObject::tr(
"%1 Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2784 return QDomElement();
2798 if ( ! processSRSName( node, args, args.size() == 5, srsName, axisInversion ) )
2800 return QDomElement();
2811 if ( node->
name().compare( QLatin1String(
"ST_GeomFromGML" ), Qt::CaseInsensitive ) == 0 )
2813 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2814 if ( args.size() != 1 )
2816 mErrorMessage = QObject::tr(
"Function %1 should have 1 argument" ).arg( node->
name() );
2817 return QDomElement();
2823 mErrorMessage = QObject::tr(
"%1: Argument must be string literal" ).arg( node->
name() );
2824 return QDomElement();
2827 QDomDocument geomDoc;
2829 if ( !geomDoc.setContent( gml,
true ) )
2831 mErrorMessage = QObject::tr(
"ST_GeomFromGML: unable to parse XML" );
2832 return QDomElement();
2835 QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(), true );
2837 return geomNode.toElement();
2841 QString ogcName( mapBinarySpatialToOgc( node->
name() ) );
2842 if ( !ogcName.isEmpty() )
2844 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2845 if ( args.size() != 2 )
2847 mErrorMessage = QObject::tr(
"Function %1 should have 2 arguments" ).arg( node->
name() );
2848 return QDomElement();
2851 for (
int i = 0; i < 2; i ++ )
2854 ( static_cast<const QgsSQLStatement::NodeFunction *>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
2855 static_cast<const QgsSQLStatement::NodeFunction *>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
2857 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
2864 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + ogcName );
2868 if ( !mErrorMessage.isEmpty() )
2870 mCurrentSRSName.clear();
2871 return QDomElement();
2874 funcElem.appendChild( childElem );
2877 mCurrentSRSName.clear();
2881 ogcName = mapTernarySpatialToOgc( node->
name() );
2882 if ( !ogcName.isEmpty() )
2884 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2885 if ( args.size() != 3 )
2887 mErrorMessage = QObject::tr(
"Function %1 should have 3 arguments" ).arg( node->
name() );
2888 return QDomElement();
2891 for (
int i = 0; i < 2; i ++ )
2894 ( static_cast<const QgsSQLStatement::NodeFunction *>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
2895 static_cast<const QgsSQLStatement::NodeFunction *>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
2897 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
2902 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + node->
name().mid( 3 ) );
2903 for (
int i = 0; i < 2; i++ )
2906 if ( !mErrorMessage.isEmpty() )
2908 mCurrentSRSName.clear();
2909 return QDomElement();
2912 funcElem.appendChild( childElem );
2914 mCurrentSRSName.clear();
2919 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() );
2920 return QDomElement();
2923 if ( lit->
value().isNull() )
2925 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() );
2926 return QDomElement();
2929 QString unit( QStringLiteral(
"m" ) );
2930 switch ( lit->
value().type() )
2933 distance = QString::number( lit->
value().toInt() );
2935 case QVariant::LongLong:
2936 distance = QString::number( lit->
value().toLongLong() );
2938 case QVariant::Double:
2941 case QVariant::String:
2943 distance = lit->
value().toString();
2944 for (
int i = 0; i < distance.size(); i++ )
2946 if ( !( ( distance[i] >=
'0' && distance[i] <=
'9' ) || distance[i] ==
'-' || distance[i] ==
'.' || distance[i] ==
'e' || distance[i] ==
'E' ) )
2948 unit = distance.mid( i ).trimmed();
2949 distance = distance.mid( 0, i );
2957 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( lit->
value().type() );
2958 return QDomElement();
2961 QDomElement distanceElem = mDoc.createElement( mFilterPrefix +
":Distance" );
2963 distanceElem.setAttribute( QStringLiteral(
"uom" ), unit );
2965 distanceElem.setAttribute( QStringLiteral(
"unit" ), unit );
2966 distanceElem.appendChild( mDoc.createTextNode( distance ) );
2967 funcElem.appendChild( distanceElem );
2972 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
2973 funcElem.setAttribute( QStringLiteral(
"name" ), node->
name() );
2977 if ( !mErrorMessage.isEmpty() )
2978 return QDomElement();
2980 funcElem.appendChild( childElem );
2986 const QString &leftTable )
2994 QList<QDomElement> listElem;
2995 Q_FOREACH (
const QString &columnName, node->
usingColumns() )
2997 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2998 QDomElement propElem1 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2999 propElem1.appendChild( mDoc.createTextNode( leftTable +
"/" + columnName ) );
3000 eqElem.appendChild( propElem1 );
3001 QDomElement propElem2 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3002 propElem2.appendChild( mDoc.createTextNode( node->
tableDef()->
name() +
"/" + columnName ) );
3003 eqElem.appendChild( propElem2 );
3004 listElem.append( eqElem );
3007 if ( listElem.size() == 1 )
3011 else if ( listElem.size() > 1 )
3013 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3014 Q_FOREACH (
const QDomElement &elem, listElem )
3016 andElem.appendChild( elem );
3021 return QDomElement();
3026 if ( node->
alias().isEmpty() )
3028 mMapTableAliasToNames[ node->
name()] = node->
name();
3032 mMapTableAliasToNames[ node->
alias()] = node->
name();
3038 QList<QDomElement> listElem;
3041 ( node->
tables().size() != 1 || !node->
joins().empty() ) )
3043 mErrorMessage = QObject::tr(
"Joins are only supported with WFS 2.0" );
3044 return QDomElement();
3058 QList< QgsSQLStatement::NodeTableDef *> nodeTables = node->
tables();
3059 QString leftTable = nodeTables.at( nodeTables.length() - 1 )->name();
3062 QDomElement joinElem =
toOgcFilter( join, leftTable );
3063 if ( !mErrorMessage.isEmpty() )
3064 return QDomElement();
3065 listElem.append( joinElem );
3070 if ( node->
where() )
3073 if ( !mErrorMessage.isEmpty() )
3074 return QDomElement();
3075 listElem.append( whereElem );
3079 if ( listElem.size() == 1 )
3083 else if ( listElem.size() > 1 )
3085 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3086 Q_FOREACH (
const QDomElement &elem, listElem )
3088 andElem.appendChild( elem );
3093 return QDomElement();
3099 mPropertyName = QStringLiteral(
"PropertyName" );
3100 mPrefix = QStringLiteral(
"ogc" );
3104 mPropertyName = QStringLiteral(
"ValueReference" );
3105 mPrefix = QStringLiteral(
"fes" );
3111 if ( element.isNull() )
3115 if ( isBinaryOperator( element.tagName() ) )
3121 if ( isSpatialOperator( element.tagName() ) )
3127 if ( element.tagName() == QLatin1String(
"Not" ) )
3131 else if ( element.tagName() == QLatin1String(
"PropertyIsNull" ) )
3135 else if ( element.tagName() == QLatin1String(
"Literal" ) )
3139 else if ( element.tagName() == QLatin1String(
"Function" ) )
3143 else if ( element.tagName() == mPropertyName )
3147 else if ( element.tagName() == QLatin1String(
"PropertyIsBetween" ) )
3152 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() );
3158 if ( element.isNull() )
3161 int op = binaryOperatorFromTagName( element.tagName() );
3164 mErrorMessage = QObject::tr(
"'%1' binary operator not supported." ).arg( element.tagName() );
3168 if ( op ==
QgsExpressionNodeBinaryOperator::boLike && element.hasAttribute( QStringLiteral(
"matchCase" ) ) && element.attribute( QStringLiteral(
"matchCase" ) ) == QLatin1String(
"false" ) )
3173 QDomElement operandElem = element.firstChildElement();
3178 mErrorMessage = QObject::tr(
"invalid left operand for '%1' binary operator" ).arg( element.tagName() );
3182 std::unique_ptr<QgsExpressionNode> leftOp( expr->clone() );
3183 for ( operandElem = operandElem.nextSiblingElement(); !operandElem.isNull(); operandElem = operandElem.nextSiblingElement() )
3188 mErrorMessage = QObject::tr(
"invalid right operand for '%1' binary operator" ).arg( element.tagName() );
3195 if ( element.hasAttribute( QStringLiteral(
"wildCard" ) ) )
3197 wildCard = element.attribute( QStringLiteral(
"wildCard" ) );
3200 if ( element.hasAttribute( QStringLiteral(
"singleChar" ) ) )
3202 singleChar = element.attribute( QStringLiteral(
"singleChar" ) );
3204 QString escape = QStringLiteral(
"\\" );
3205 if ( element.hasAttribute( QStringLiteral(
"escape" ) ) )
3207 escape = element.attribute( QStringLiteral(
"escape" ) );
3209 if ( element.hasAttribute( QStringLiteral(
"escapeChar" ) ) )
3211 escape = element.attribute( QStringLiteral(
"escapeChar" ) );
3215 if ( !wildCard.isEmpty() && wildCard != QLatin1String(
"%" ) )
3217 oprValue.replace(
'%', QLatin1String(
"\\%" ) );
3218 if ( oprValue.startsWith( wildCard ) )
3220 oprValue.replace( 0, 1, QStringLiteral(
"%" ) );
3222 QRegExp rx(
"[^" + QRegExp::escape( escape ) +
"](" + QRegExp::escape( wildCard ) +
")" );
3224 while ( ( pos = rx.indexIn( oprValue, pos ) ) != -1 )
3226 oprValue.replace( pos + 1, 1, QStringLiteral(
"%" ) );
3229 oprValue.replace( escape + wildCard, wildCard );
3231 if ( !singleChar.isEmpty() && singleChar != QLatin1String(
"_" ) )
3233 oprValue.replace(
'_', QLatin1String(
"\\_" ) );
3234 if ( oprValue.startsWith( singleChar ) )
3236 oprValue.replace( 0, 1, QStringLiteral(
"_" ) );
3238 QRegExp rx(
"[^" + QRegExp::escape( escape ) +
"](" + QRegExp::escape( singleChar ) +
")" );
3240 while ( ( pos = rx.indexIn( oprValue, pos ) ) != -1 )
3242 oprValue.replace( pos + 1, 1, QStringLiteral(
"_" ) );
3245 oprValue.replace( escape + singleChar, singleChar );
3247 if ( !escape.isEmpty() && escape != QLatin1String(
"\\" ) )
3249 oprValue.replace( escape + escape, escape );
3254 expr.reset(
new QgsExpressionNodeBinaryOperator( static_cast< QgsExpressionNodeBinaryOperator::BinaryOperator >( op ), expr.release(), opRight.release() ) );
3257 if ( expr == leftOp )
3259 mErrorMessage = QObject::tr(
"only one operand for '%1' binary operator" ).arg( element.tagName() );
3273 QDomElement childElem = element.firstChildElement();
3275 while ( !childElem.isNull() && gml2Str.isEmpty() )
3277 if ( childElem.tagName() != mPropertyName )
3279 QTextStream gml2Stream( &gml2Str );
3280 childElem.save( gml2Stream, 0 );
3282 childElem = childElem.nextSiblingElement();
3284 if ( !gml2Str.isEmpty() )
3290 mErrorMessage = QObject::tr(
"No OGC Geometry found" );
3303 if ( element.isNull() || element.tagName() != mPropertyName )
3305 mErrorMessage = QObject::tr(
"%1:PropertyName expected, got %2" ).arg( mPrefix, element.tagName() );
3314 if ( element.isNull() || element.tagName() != QLatin1String(
"Literal" ) )
3316 mErrorMessage = QObject::tr(
"%1:Literal expected, got %2" ).arg( mPrefix, element.tagName() );
3320 std::unique_ptr<QgsExpressionNode> root;
3323 QDomNode childNode = element.firstChild();
3324 while ( !childNode.isNull() )
3326 std::unique_ptr<QgsExpressionNode> operand;
3328 if ( childNode.nodeType() == QDomNode::ElementNode )
3331 const QDomElement operandElem = childNode.toElement();
3335 mErrorMessage = QObject::tr(
"'%1' is an invalid or not supported content for %2:Literal" ).arg( operandElem.tagName(), mPrefix );
3342 QVariant value = childNode.nodeValue();
3344 bool converted =
false;
3349 QDomElement propertyNameElement = element.previousSiblingElement( mPropertyName );
3350 if ( propertyNameElement.isNull() || propertyNameElement.tagName() != mPropertyName )
3352 propertyNameElement = element.nextSiblingElement( mPropertyName );
3354 if ( !propertyNameElement.isNull() || propertyNameElement.tagName() == mPropertyName )
3356 const int fieldIndex = mLayer->
fields().
indexOf( propertyNameElement.firstChild().nodeValue() );
3357 if ( fieldIndex != -1 )
3370 const double d = value.toDouble( &ok );
3383 root = std::move( operand );
3390 childNode = childNode.nextSibling();
3394 return root.release();
3401 if ( element.tagName() != QLatin1String(
"Not" ) )
3404 const QDomElement operandElem = element.firstChildElement();
3408 mErrorMessage = QObject::tr(
"invalid operand for '%1' unary operator" ).arg( element.tagName() );
3418 if ( element.tagName() != QLatin1String(
"PropertyIsNull" ) )
3423 const QDomElement operandElem = element.firstChildElement();
3434 if ( element.isNull() || element.tagName() != QLatin1String(
"Function" ) )
3436 mErrorMessage = QObject::tr(
"%1:Function expected, got %2" ).arg( mPrefix, element.tagName() );
3444 if ( element.attribute( QStringLiteral(
"name" ) ) != funcDef->
name() )
3449 QDomElement operandElem = element.firstChildElement();
3450 while ( !operandElem.isNull() )
3457 args->append( op.release() );
3459 operandElem = operandElem.nextSiblingElement();
3471 std::unique_ptr<QgsExpressionNode> operand;
3472 std::unique_ptr<QgsExpressionNode> lowerBound;
3473 std::unique_ptr<QgsExpressionNode> upperBound;
3475 QDomElement operandElem = element.firstChildElement();
3476 while ( !operandElem.isNull() )
3478 if ( operandElem.tagName() == QLatin1String(
"LowerBoundary" ) )
3480 QDomElement lowerBoundElem = operandElem.firstChildElement();
3483 else if ( operandElem.tagName() == QLatin1String(
"UpperBoundary" ) )
3485 QDomElement upperBoundElem = operandElem.firstChildElement();
3494 if ( operand && lowerBound && upperBound )
3497 operandElem = operandElem.nextSiblingElement();
3500 if ( !operand || !lowerBound || !upperBound )
3502 mErrorMessage = QObject::tr(
"missing some required sub-elements in %1:PropertyIsBetween" ).arg( mPrefix );
3513 return mErrorMessage;
Class for parsing and evaluation of expressions (formerly called "search strings").
QgsExpressionNodeBinaryOperator::BinaryOperator op() const
Returns the binary operator.
QString name() const
The name of the column.
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 rectangle specified with double values.
Internal use by QgsOgcUtils.
QgsSQLStatement::Node * minVal() const
Minimum bound.
QString errorMessage() const
Returns the error message.
QDomElement expressionNodeToOgcFilter(const QgsExpressionNode *node, QgsExpression *expression, const QgsExpressionContext *context)
Convert an expression to a OGC filter.
QString alias() const
Table alias.
QgsExpressionNode * nodeLiteralFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with literal tag.
bool isNull() const
Returns true if the geometry is null (ie, contains no underlying geometry accessible via geometry() )...
void setXMaximum(double x)
Set the maximum x value.
Function with a name and arguments node.
QgsOgcUtilsExprToFilter(QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, QgsOgcUtils::FilterVersion filterVersion, const QString &geometryName, const QString &srsName, bool honourAxisOrientation, bool invertAxisOrientation)
Constructor.
QString text() const
Returns a the name of this operator without the operands.
void setExpression(const QString &expression)
Set the expression string, will reset the whole internal structure.
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length...
QgsSQLStatement::NodeList * args() const
Returns arguments.
double yMaximum() const
Returns the y maximum value (top side of rectangle).
QgsExpressionNode * nodeFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document element.
QgsExpressionNodeFunction * nodeFunctionFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with functions.
int fnIndex() const
Returns the index of the node's function.
A class to represent a 2D point.
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item...
static const char * BINARY_OPERATOR_TEXT[]
bool isNotIn() const
Returns true if this node is a "NOT IN" operator, or false if the node is a normal "IN" operator...
QString name() const
Returns function name.
A geometry is the spatial representation of a feature.
QgsExpressionNodeUnaryOperator * nodeNotFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with Not operator.
static QDomElement rectangleToGMLBox(QgsRectangle *box, QDomDocument &doc, int precision=17)
Exports the rectangle to GML2 Box.
QString name() const
The name of the column.
QString dump() const
Returns an expression string, constructed from the internal abstract syntax tree. ...
QDomElement toOgcFilter(const QgsSQLStatement::Node *node)
Convert a SQL statement to a OGC filter.
const QgsSQLStatement::Node * rootNode() const
Returns root node of the statement. Root node is null is parsing has failed.
QString name() const
The name of the function.
QgsExpressionNode * node() const
Returns the expression node.
const QgsCoordinateReferenceSystem & crs
Binary logical/arithmetical operator (AND, OR, =, +, ...)
QgsSQLStatement::Node * opLeft() const
Left operand.
QgsSQLStatement::NodeTableDef * tableDef() const
Table definition.
QgsExpressionNode::NodeList * list() const
Returns the list of nodes to search for matching values within.
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
QgsOgcUtilsSQLStatementToFilter(QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, QgsOgcUtils::FilterVersion filterVersion, const QList< QgsOgcUtils::LayerProperties > &layerProperties, bool honourAxisOrientation, bool invertAxisOrientation, const QMap< QString, QString > &mapUnprefixedTypenameToPrefixedTypename)
Constructor.
QgsExpressionNodeBinaryOperator * nodeBinaryOperatorFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with binary operators.
bool GMLNamespaceUsed() const
Returns whether the gml: namespace is used.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
static QgsRectangle rectangleFromGMLBox(const QDomNode &boxNode)
Read rectangle from GML2 Box.
QString text() const
Returns a the name of this operator without the operands.
const QString GML_NAMESPACE
static QgsRectangle rectangleFromGMLEnvelope(const QDomNode &envelopeNode)
Read rectangle from GML3 Envelope.
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
Internal use by QgsOgcUtils.
bool isNotIn() const
Whether this is a NOT IN operator.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
Class for parsing SQL statements.
Type
The WKB type describes the number of dimensions a geometry has.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
QgsFields fields() const FINAL
Returns the list of fields of this layer.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
static int functionIndex(const QString &name)
Returns index of the function in Functions array.
double xMaximum() const
Returns the x maximum value (right side of rectangle).
const QString & geometryName
QgsExpressionNodeFunction * nodeSpatialOperatorFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with spatial operators.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
void setYMinimum(double y)
Set the minimum y value.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsSQLStatement::UnaryOperator op() const
Operator.
QVariant value() const
The value of the literal.
BinaryOperator
list of binary operators
An expression node for value IN or NOT IN clauses.
Literal value (integer, integer64, double, string)
Internal use by QgsOgcUtils.
An expression node which takes it value from a feature's field.
QgsExpressionNode * nodeIsBetweenFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with boudnaries operator...
Unary logicial/arithmetical operator ( NOT, - )
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.
BinaryOperator
list of binary operators
QString mSRSName
SRS name.
Abstract base class for all nodes that can appear in an expression.
Encapsulate a field in an attribute table or data source.
An expression node for expression functions.
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
QgsField field(int fieldIdx) const
Gets field at particular index (must be in range 0..N-1)
QgsExpressionNode * operand() const
Returns the node the operator will operate upon.
static const QList< QgsExpressionFunction * > & Functions()
int params() const
The number of parameters this function takes.
FilterVersion
OGC filter version.
'X BETWEEN y and z' operator
QString errorMessage() const
Returns the underlying error message, or an empty string in case of no error.
Custom exception class for Wkb related exceptions.
QList< QgsSQLStatement::NodeJoin * > joins() const
Returns the list of joins.
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
QList< QString > usingColumns() const
Columns referenced by USING.
A abstract base class for defining QgsExpression functions.
A list of expression nodes.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QVariant value() const
The value of the literal.
static QgsGeometry geometryFromGML(const QString &xmlString)
Static method that creates geometry from GML.
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
bool isNotBetween() const
Whether this is a NOT BETWEEN operator.
QByteArray asWkb() const
Export the geometry to WKB.
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
An expression node for literal values.
bool convertCompatible(QVariant &v) const
Converts the provided variant to a compatible format.
void setYMaximum(double y)
Set the maximum y value.
static QDomElement expressionToOgcFilter(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates OGC filter XML element.
QList< QgsSQLStatement::Node * > list()
Returns list.
A unary node is either negative as in boolean (not) or as in numbers (minus).
static QDomElement expressionToOgcExpression(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates an OGC expression XML element.
QgsExpressionNodeColumnRef * nodeColumnRefFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with column references.
QgsExpressionNode * opLeft() const
Returns the node to the left of the operator.
A binary expression operator, which operates on two values.
This class represents a coordinate reference system (CRS).
QgsSQLStatement::NodeList * list() const
Values list.
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.
const QgsExpressionNode * rootNode() const
Returns root node of the expression. Root node is null is parsing has failed.
static QDomElement rectangleToGMLEnvelope(QgsRectangle *env, QDomDocument &doc, int precision=17)
Exports the rectangle to GML3 Envelope.
static const char * UNARY_OPERATOR_TEXT[]
QString mGeometryAttribute
Geometry attribute name.
static QColor colorFromOgcFill(const QDomElement &fillElement)
Parse XML with OGC fill into QColor.
QgsSQLStatement::Node * where() const
Returns the where clause.
QgsSQLStatement::Node * operand() const
Operand.
QgsOgcUtilsExpressionFromFilter(QgsOgcUtils::FilterVersion version=QgsOgcUtils::FILTER_OGC_1_0, const QgsVectorLayer *layer=nullptr)
Constructor for QgsOgcUtilsExpressionFromFilter.
QString name() const
Table name.
QList< QgsSQLStatement::NodeTableDef * > tables() const
Returns the list of tables.
QgsExpressionNode * opRight() const
Returns the node to the right of the operator.
void normalize()
Normalize the rectangle so it has non-negative width/height.
QgsSQLStatement::Node * onExpr() const
On expression. Will be nullptr if usingColumns() is not empty.
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
QString errorMessage() const
Returns the error message.
QgsSQLStatement::Node * node() const
Variable at the left of BETWEEN.
QgsSQLStatement::Node * node() const
Variable at the left of IN.
Represents a vector layer which manages a vector based data sets.
'x IN (y, z)' operator
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
QgsExpressionNodeUnaryOperator::UnaryOperator op() const
Returns the unary operator.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
QgsSQLStatement::Node * maxVal() const
Maximum bound.
QgsSQLStatement::Node * opRight() const
Right operand.
The QgsOgcUtils class provides various utility functions for conversion between OGC (Open Geospatial ...
QgsWkbTypes::Type wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
bool GMLNamespaceUsed() const
Returns whether the gml: namespace is used.
QgsExpressionNodeBinaryOperator * nodePropertyIsNullFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with IsNull operator.
virtual bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
Will be called during prepare to determine if the function is static.
void setXMinimum(double x)
Set the minimum x value.
bool hasAxisInverted() const
Returns whether axis is inverted (e.g., for WMS 1.3) for the CRS.
QString tableName() const
The name of the table. May be empty.
virtual QgsSQLStatement::NodeType nodeType() const =0
Abstract virtual that returns the type of this node.
QgsSQLStatement::BinaryOperator op() const
Operator.