29 #include <QStringList> 30 #include <QTextStream> 34 #include <netinet/in.h> 40 static const QString
GML_NAMESPACE = QStringLiteral(
"http://www.opengis.net/gml" );
41 static const QString GML32_NAMESPACE = QStringLiteral(
"http://www.opengis.net/gml/3.2" );
42 static const QString OGC_NAMESPACE = QStringLiteral(
"http://www.opengis.net/ogc" );
43 static const QString FES_NAMESPACE = QStringLiteral(
"http://www.opengis.net/fes/2.0" );
49 const QString &srsName,
50 bool honourAxisOrientation,
51 bool invertAxisOrientation )
54 , mGMLVersion( gmlVersion )
55 , mFilterVersion( filterVersion )
56 , mGeometryName( geometryName )
58 , mInvertAxisOrientation( invertAxisOrientation )
59 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
60 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
64 if ( !mSrsName.isEmpty() )
70 mInvertAxisOrientation = !mInvertAxisOrientation;
77 QDomElement geometryTypeElement = geometryNode.toElement();
78 QString geomType = geometryTypeElement.tagName();
80 if ( !( geomType == QLatin1String(
"Point" ) || geomType == QLatin1String(
"LineString" ) || geomType == QLatin1String(
"Polygon" ) ||
81 geomType == QLatin1String(
"MultiPoint" ) || geomType == QLatin1String(
"MultiLineString" ) || geomType == QLatin1String(
"MultiPolygon" ) ||
82 geomType == QLatin1String(
"Box" ) || geomType == QLatin1String(
"Envelope" ) ) )
84 QDomNode geometryChild = geometryNode.firstChild();
85 if ( geometryChild.isNull() )
89 geometryTypeElement = geometryChild.toElement();
90 geomType = geometryTypeElement.tagName();
93 if ( !( geomType == QLatin1String(
"Point" ) || geomType == QLatin1String(
"LineString" ) || geomType == QLatin1String(
"Polygon" ) ||
94 geomType == QLatin1String(
"MultiPoint" ) || geomType == QLatin1String(
"MultiLineString" ) || geomType == QLatin1String(
"MultiPolygon" ) ||
95 geomType == QLatin1String(
"Box" ) || geomType == QLatin1String(
"Envelope" ) ) )
98 if ( geomType == QLatin1String(
"Point" ) )
100 return geometryFromGMLPoint( geometryTypeElement );
102 else if ( geomType == QLatin1String(
"LineString" ) )
104 return geometryFromGMLLineString( geometryTypeElement );
106 else if ( geomType == QLatin1String(
"Polygon" ) )
108 return geometryFromGMLPolygon( geometryTypeElement );
110 else if ( geomType == QLatin1String(
"MultiPoint" ) )
112 return geometryFromGMLMultiPoint( geometryTypeElement );
114 else if ( geomType == QLatin1String(
"MultiLineString" ) )
116 return geometryFromGMLMultiLineString( geometryTypeElement );
118 else if ( geomType == QLatin1String(
"MultiPolygon" ) )
120 return geometryFromGMLMultiPolygon( geometryTypeElement );
122 else if ( geomType == QLatin1String(
"Box" ) )
126 else if ( geomType == QLatin1String(
"Envelope" ) )
139 QString xml = QStringLiteral(
"<tmp xmlns=\"%1\" xmlns:gml=\"%1\">%2</tmp>" ).arg(
GML_NAMESPACE, xmlString );
141 if ( !doc.setContent( xml,
true ) )
144 return geometryFromGML( doc.documentElement().firstChildElement() );
148 QgsGeometry QgsOgcUtils::geometryFromGMLPoint(
const QDomElement &geometryElement )
152 QDomNodeList coordList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
153 if ( !coordList.isEmpty() )
155 QDomElement coordElement = coordList.at( 0 ).toElement();
156 if ( readGMLCoordinates( pointCoordinate, coordElement ) != 0 )
163 QDomNodeList posList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pos" ) );
164 if ( posList.size() < 1 )
168 QDomElement posElement = posList.at( 0 ).toElement();
169 if ( readGMLPositions( pointCoordinate, posElement ) != 0 )
175 if ( pointCoordinate.empty() )
180 QgsPolylineXY::const_iterator point_it = pointCoordinate.constBegin();
181 char e = htonl( 1 ) != 1;
182 double x = point_it->x();
183 double y = point_it->y();
184 int size = 1 +
sizeof( int ) + 2 *
sizeof(
double );
187 unsigned char *wkb =
new unsigned char[size];
190 memcpy( &( wkb )[wkbPosition], &e, 1 );
192 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
193 wkbPosition +=
sizeof( int );
194 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
195 wkbPosition +=
sizeof( double );
196 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
203 QgsGeometry QgsOgcUtils::geometryFromGMLLineString(
const QDomElement &geometryElement )
207 QDomNodeList coordList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
208 if ( !coordList.isEmpty() )
210 QDomElement coordElement = coordList.at( 0 ).toElement();
211 if ( readGMLCoordinates( lineCoordinates, coordElement ) != 0 )
218 QDomNodeList posList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
219 if ( posList.size() < 1 )
223 QDomElement posElement = posList.at( 0 ).toElement();
224 if ( readGMLPositions( lineCoordinates, posElement ) != 0 )
230 char e = htonl( 1 ) != 1;
231 int size = 1 + 2 *
sizeof( int ) + lineCoordinates.size() * 2 *
sizeof( double );
234 unsigned char *wkb =
new unsigned char[size];
238 int nPoints = lineCoordinates.size();
241 memcpy( &( wkb )[wkbPosition], &e, 1 );
243 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
244 wkbPosition +=
sizeof( int );
245 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
246 wkbPosition +=
sizeof( int );
248 QgsPolylineXY::const_iterator iter;
249 for ( iter = lineCoordinates.constBegin(); iter != lineCoordinates.constEnd(); ++iter )
253 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
254 wkbPosition +=
sizeof( double );
255 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
256 wkbPosition +=
sizeof( double );
264 QgsGeometry QgsOgcUtils::geometryFromGMLPolygon(
const QDomElement &geometryElement )
271 QDomNodeList outerBoundaryList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"outerBoundaryIs" ) );
272 if ( !outerBoundaryList.isEmpty() )
274 QDomElement coordinatesElement = outerBoundaryList.at( 0 ).firstChild().firstChild().toElement();
275 if ( coordinatesElement.isNull() )
279 if ( readGMLCoordinates( exteriorPointList, coordinatesElement ) != 0 )
283 ringCoordinates.push_back( exteriorPointList );
286 QDomNodeList innerBoundaryList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"innerBoundaryIs" ) );
287 for (
int i = 0; i < innerBoundaryList.size(); ++i )
290 coordinatesElement = innerBoundaryList.at( i ).firstChild().firstChild().toElement();
291 if ( coordinatesElement.isNull() )
295 if ( readGMLCoordinates( interiorPointList, coordinatesElement ) != 0 )
299 ringCoordinates.push_back( interiorPointList );
305 QDomNodeList exteriorList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"exterior" ) );
306 if ( exteriorList.size() < 1 )
310 QDomElement posElement = exteriorList.at( 0 ).firstChild().firstChild().toElement();
311 if ( posElement.isNull() )
315 if ( readGMLPositions( exteriorPointList, posElement ) != 0 )
319 ringCoordinates.push_back( exteriorPointList );
322 QDomNodeList interiorList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"interior" ) );
323 for (
int i = 0; i < interiorList.size(); ++i )
326 QDomElement posElement = interiorList.at( i ).firstChild().firstChild().toElement();
327 if ( posElement.isNull() )
331 if ( readGMLPositions( interiorPointList, posElement ) != 0 )
335 ringCoordinates.push_back( interiorPointList );
340 int nrings = ringCoordinates.size();
345 for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
347 npoints += it->size();
349 int size = 1 + 2 *
sizeof( int ) + nrings *
sizeof(
int ) + 2 * npoints *
sizeof( double );
352 unsigned char *wkb =
new unsigned char[size];
355 char e = htonl( 1 ) != 1;
357 int nPointsInRing = 0;
361 memcpy( &( wkb )[wkbPosition], &e, 1 );
363 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
364 wkbPosition +=
sizeof( int );
365 memcpy( &( wkb )[wkbPosition], &nrings,
sizeof(
int ) );
366 wkbPosition +=
sizeof( int );
367 for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
369 nPointsInRing = it->size();
370 memcpy( &( wkb )[wkbPosition], &nPointsInRing,
sizeof(
int ) );
371 wkbPosition +=
sizeof( int );
373 QgsPolylineXY::const_iterator iter;
374 for ( iter = it->begin(); iter != it->end(); ++iter )
379 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
380 wkbPosition +=
sizeof( double );
381 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
382 wkbPosition +=
sizeof( double );
391 QgsGeometry QgsOgcUtils::geometryFromGMLMultiPoint(
const QDomElement &geometryElement )
395 QDomNodeList pointMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pointMember" ) );
396 if ( pointMemberList.size() < 1 )
400 QDomNodeList pointNodeList;
402 QDomNodeList coordinatesList;
403 QDomNodeList posList;
404 for (
int i = 0; i < pointMemberList.size(); ++i )
407 pointNodeList = pointMemberList.at( i ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"Point" ) );
408 if ( pointNodeList.size() < 1 )
413 coordinatesList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
414 if ( !coordinatesList.isEmpty() )
416 currentPoint.clear();
417 if ( readGMLCoordinates( currentPoint, coordinatesList.at( 0 ).toElement() ) != 0 )
421 if ( currentPoint.empty() )
425 pointList.push_back( ( *currentPoint.begin() ) );
431 posList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pos" ) );
432 if ( posList.size() < 1 )
436 currentPoint.clear();
437 if ( readGMLPositions( currentPoint, posList.at( 0 ).toElement() ) != 0 )
441 if ( currentPoint.empty() )
445 pointList.push_back( ( *currentPoint.begin() ) );
449 int nPoints = pointList.size();
454 int size = 1 + 2 *
sizeof( int ) + pointList.size() * ( 2 *
sizeof( double ) + 1 +
sizeof(
int ) );
457 unsigned char *wkb =
new unsigned char[size];
460 char e = htonl( 1 ) != 1;
463 memcpy( &( wkb )[wkbPosition], &e, 1 );
465 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
466 wkbPosition +=
sizeof( int );
467 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
468 wkbPosition +=
sizeof( int );
470 for ( QgsPolylineXY::const_iterator it = pointList.constBegin(); it != pointList.constEnd(); ++it )
472 memcpy( &( wkb )[wkbPosition], &e, 1 );
474 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
475 wkbPosition +=
sizeof( int );
477 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
478 wkbPosition +=
sizeof( double );
480 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
481 wkbPosition +=
sizeof( double );
489 QgsGeometry QgsOgcUtils::geometryFromGMLMultiLineString(
const QDomElement &geometryElement )
500 QList< QgsPolylineXY > lineCoordinates;
501 QDomElement currentLineStringElement;
502 QDomNodeList currentCoordList;
503 QDomNodeList currentPosList;
505 QDomNodeList lineStringMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"lineStringMember" ) );
506 if ( !lineStringMemberList.isEmpty() )
508 for (
int i = 0; i < lineStringMemberList.size(); ++i )
510 QDomNodeList lineStringNodeList = lineStringMemberList.at( i ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LineString" ) );
511 if ( lineStringNodeList.size() < 1 )
515 currentLineStringElement = lineStringNodeList.at( 0 ).toElement();
516 currentCoordList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
517 if ( !currentCoordList.isEmpty() )
520 if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
524 lineCoordinates.push_back( currentPointList );
528 currentPosList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
529 if ( currentPosList.size() < 1 )
534 if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
538 lineCoordinates.push_back( currentPointList );
544 QDomNodeList lineStringList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LineString" ) );
545 if ( !lineStringList.isEmpty() )
547 for (
int i = 0; i < lineStringList.size(); ++i )
549 currentLineStringElement = lineStringList.at( i ).toElement();
550 currentCoordList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
551 if ( !currentCoordList.isEmpty() )
554 if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
558 lineCoordinates.push_back( currentPointList );
563 currentPosList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
564 if ( currentPosList.size() < 1 )
569 if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
573 lineCoordinates.push_back( currentPointList );
583 int nLines = lineCoordinates.size();
588 int size = ( lineCoordinates.size() + 1 ) * ( 1 + 2 *
sizeof(
int ) );
589 for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
591 size += it->size() * 2 *
sizeof( double );
595 unsigned char *wkb =
new unsigned char[size];
598 char e = htonl( 1 ) != 1;
602 memcpy( &( wkb )[wkbPosition], &e, 1 );
604 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
605 wkbPosition +=
sizeof( int );
606 memcpy( &( wkb )[wkbPosition], &nLines,
sizeof(
int ) );
607 wkbPosition +=
sizeof( int );
609 for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
611 memcpy( &( wkb )[wkbPosition], &e, 1 );
613 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
614 wkbPosition +=
sizeof( int );
615 nPoints = it->size();
616 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
617 wkbPosition +=
sizeof( int );
618 for ( QgsPolylineXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
623 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
624 wkbPosition +=
sizeof( double );
625 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
626 wkbPosition +=
sizeof( double );
635 QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon(
const QDomElement &geometryElement )
639 QDomElement currentPolygonMemberElement;
640 QDomNodeList polygonList;
641 QDomElement currentPolygonElement;
643 QDomNodeList outerBoundaryList;
644 QDomElement currentOuterBoundaryElement;
645 QDomNodeList innerBoundaryList;
646 QDomElement currentInnerBoundaryElement;
648 QDomNodeList exteriorList;
649 QDomElement currentExteriorElement;
650 QDomElement currentInteriorElement;
651 QDomNodeList interiorList;
653 QDomNodeList linearRingNodeList;
654 QDomElement currentLinearRingElement;
656 QDomNodeList currentCoordinateList;
657 QDomNodeList currentPosList;
659 QDomNodeList polygonMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"polygonMember" ) );
661 for (
int i = 0; i < polygonMemberList.size(); ++i )
663 currentPolygonList.resize( 0 );
664 currentPolygonMemberElement = polygonMemberList.at( i ).toElement();
665 polygonList = currentPolygonMemberElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"Polygon" ) );
666 if ( polygonList.size() < 1 )
670 currentPolygonElement = polygonList.at( 0 ).toElement();
673 outerBoundaryList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"outerBoundaryIs" ) );
674 if ( !outerBoundaryList.isEmpty() )
676 currentOuterBoundaryElement = outerBoundaryList.at( 0 ).toElement();
679 linearRingNodeList = currentOuterBoundaryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
680 if ( linearRingNodeList.size() < 1 )
684 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
685 currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
686 if ( currentCoordinateList.size() < 1 )
690 if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
694 currentPolygonList.push_back( ringCoordinates );
697 QDomNodeList innerBoundaryList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"innerBoundaryIs" ) );
698 for (
int j = 0; j < innerBoundaryList.size(); ++j )
701 currentInnerBoundaryElement = innerBoundaryList.at( j ).toElement();
702 linearRingNodeList = currentInnerBoundaryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
703 if ( linearRingNodeList.size() < 1 )
707 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
708 currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
709 if ( currentCoordinateList.size() < 1 )
713 if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
717 currentPolygonList.push_back( ringCoordinates );
723 exteriorList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"exterior" ) );
724 if ( exteriorList.size() < 1 )
729 currentExteriorElement = exteriorList.at( 0 ).toElement();
732 linearRingNodeList = currentExteriorElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
733 if ( linearRingNodeList.size() < 1 )
737 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
738 currentPosList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
739 if ( currentPosList.size() < 1 )
743 if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
747 currentPolygonList.push_back( ringPositions );
750 QDomNodeList interiorList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"interior" ) );
751 for (
int j = 0; j < interiorList.size(); ++j )
754 currentInteriorElement = interiorList.at( j ).toElement();
755 linearRingNodeList = currentInteriorElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
756 if ( linearRingNodeList.size() < 1 )
760 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
761 currentPosList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
762 if ( currentPosList.size() < 1 )
766 if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
770 currentPolygonList.push_back( ringPositions );
773 multiPolygonPoints.push_back( currentPolygonList );
776 int nPolygons = multiPolygonPoints.size();
780 int size = 1 + 2 *
sizeof( int );
782 for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
784 size += 1 + 2 *
sizeof( int );
785 for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
787 size +=
sizeof( int ) + 2 * iter->size() *
sizeof( double );
792 unsigned char *wkb =
new unsigned char[size];
794 char e = htonl( 1 ) != 1;
801 memcpy( &( wkb )[wkbPosition], &e, 1 );
803 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
804 wkbPosition +=
sizeof( int );
805 memcpy( &( wkb )[wkbPosition], &nPolygons,
sizeof(
int ) );
806 wkbPosition +=
sizeof( int );
810 for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
812 memcpy( &( wkb )[wkbPosition], &e, 1 );
814 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
815 wkbPosition +=
sizeof( int );
817 memcpy( &( wkb )[wkbPosition], &nRings,
sizeof(
int ) );
818 wkbPosition +=
sizeof( int );
819 for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
821 nPointsInRing = iter->size();
822 memcpy( &( wkb )[wkbPosition], &nPointsInRing,
sizeof(
int ) );
823 wkbPosition +=
sizeof( int );
824 for ( QgsPolylineXY::const_iterator iterator = iter->begin(); iterator != iter->end(); ++iterator )
828 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
829 wkbPosition +=
sizeof( double );
830 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
831 wkbPosition +=
sizeof( double );
841 bool QgsOgcUtils::readGMLCoordinates(
QgsPolylineXY &coords,
const QDomElement &elem )
843 QString coordSeparator = QStringLiteral(
"," );
844 QString tupelSeparator = QStringLiteral(
" " );
849 if ( elem.hasAttribute( QStringLiteral(
"cs" ) ) )
851 coordSeparator = elem.attribute( QStringLiteral(
"cs" ) );
853 if ( elem.hasAttribute( QStringLiteral(
"ts" ) ) )
855 tupelSeparator = elem.attribute( QStringLiteral(
"ts" ) );
858 QStringList tupels = elem.text().split( tupelSeparator, QString::SkipEmptyParts );
859 QStringList tupel_coords;
861 bool conversionSuccess;
863 QStringList::const_iterator it;
864 for ( it = tupels.constBegin(); it != tupels.constEnd(); ++it )
866 tupel_coords = ( *it ).split( coordSeparator, QString::SkipEmptyParts );
867 if ( tupel_coords.size() < 2 )
871 x = tupel_coords.at( 0 ).toDouble( &conversionSuccess );
872 if ( !conversionSuccess )
876 y = tupel_coords.at( 1 ).toDouble( &conversionSuccess );
877 if ( !conversionSuccess )
890 QDomElement boxElem = boxNode.toElement();
891 if ( boxElem.tagName() != QLatin1String(
"Box" ) )
894 QDomElement bElem = boxElem.firstChild().toElement();
895 QString coordSeparator = QStringLiteral(
"," );
896 QString tupelSeparator = QStringLiteral(
" " );
897 if ( bElem.hasAttribute( QStringLiteral(
"cs" ) ) )
899 coordSeparator = bElem.attribute( QStringLiteral(
"cs" ) );
901 if ( bElem.hasAttribute( QStringLiteral(
"ts" ) ) )
903 tupelSeparator = bElem.attribute( QStringLiteral(
"ts" ) );
906 QString bString = bElem.text();
907 bool ok1, ok2, ok3, ok4;
908 double xmin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 0, 0 ).toDouble( &ok1 );
909 double ymin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 1, 1 ).toDouble( &ok2 );
910 double xmax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 0, 0 ).toDouble( &ok3 );
911 double ymax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 1, 1 ).toDouble( &ok4 );
913 if ( ok1 && ok2 && ok3 && ok4 )
922 bool QgsOgcUtils::readGMLPositions(
QgsPolylineXY &coords,
const QDomElement &elem )
926 QStringList pos = elem.text().split(
' ', QString::SkipEmptyParts );
928 bool conversionSuccess;
929 int posSize = pos.size();
931 int srsDimension = 2;
932 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
934 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
935 if ( !conversionSuccess )
940 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
942 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
943 if ( !conversionSuccess )
949 for (
int i = 0; i < posSize / srsDimension; i++ )
951 x = pos.at( i * srsDimension ).toDouble( &conversionSuccess );
952 if ( !conversionSuccess )
956 y = pos.at( i * srsDimension + 1 ).toDouble( &conversionSuccess );
957 if ( !conversionSuccess )
971 QDomElement envelopeElem = envelopeNode.toElement();
972 if ( envelopeElem.tagName() != QLatin1String(
"Envelope" ) )
975 QDomNodeList lowerCornerList = envelopeElem.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"lowerCorner" ) );
976 if ( lowerCornerList.size() < 1 )
979 QDomNodeList upperCornerList = envelopeElem.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"upperCorner" ) );
980 if ( upperCornerList.size() < 1 )
983 bool conversionSuccess;
984 int srsDimension = 2;
986 QDomElement elem = lowerCornerList.at( 0 ).toElement();
987 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
989 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
990 if ( !conversionSuccess )
995 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
997 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
998 if ( !conversionSuccess )
1003 QString bString = elem.text();
1005 double xmin = bString.section(
' ', 0, 0 ).toDouble( &conversionSuccess );
1006 if ( !conversionSuccess )
1008 double ymin = bString.section(
' ', 1, 1 ).toDouble( &conversionSuccess );
1009 if ( !conversionSuccess )
1012 elem = upperCornerList.at( 0 ).toElement();
1013 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
1015 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
1016 if ( !conversionSuccess )
1021 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1023 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1024 if ( !conversionSuccess )
1030 Q_UNUSED( srsDimension )
1032 bString = elem.text();
1033 double xmax = bString.section(
' ', 0, 0 ).toDouble( &conversionSuccess );
1034 if ( !conversionSuccess )
1036 double ymax = bString.section(
' ', 1, 1 ).toDouble( &conversionSuccess );
1037 if ( !conversionSuccess )
1048 return rectangleToGMLBox( box, doc, QString(),
false, precision );
1052 const QString &srsName,
1053 bool invertAxisOrientation,
1058 return QDomElement();
1061 QDomElement boxElem = doc.createElement( QStringLiteral(
"gml:Box" ) );
1062 if ( !srsName.isEmpty() )
1064 boxElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1066 QDomElement coordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1067 coordElem.setAttribute( QStringLiteral(
"cs" ), QStringLiteral(
"," ) );
1068 coordElem.setAttribute( QStringLiteral(
"ts" ), QStringLiteral(
" " ) );
1070 QString coordString;
1079 QDomText coordText = doc.createTextNode( coordString );
1080 coordElem.appendChild( coordText );
1081 boxElem.appendChild( coordElem );
1088 return rectangleToGMLEnvelope( env, doc, QString(),
false, precision );
1092 const QString &srsName,
1093 bool invertAxisOrientation,
1098 return QDomElement();
1101 QDomElement envElem = doc.createElement( QStringLiteral(
"gml:Envelope" ) );
1102 if ( !srsName.isEmpty() )
1104 envElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1108 QDomElement lowerCornerElem = doc.createElement( QStringLiteral(
"gml:lowerCorner" ) );
1112 QDomText lowerCornerText = doc.createTextNode( posList );
1113 lowerCornerElem.appendChild( lowerCornerText );
1114 envElem.appendChild( lowerCornerElem );
1116 QDomElement upperCornerElem = doc.createElement( QStringLiteral(
"gml:upperCorner" ) );
1120 QDomText upperCornerText = doc.createTextNode( posList );
1121 upperCornerElem.appendChild( upperCornerText );
1122 envElem.appendChild( upperCornerElem );
1129 return geometryToGML( geometry, doc, ( format == QLatin1String(
"GML2" ) ) ? GML_2_1_2 : GML_3_2_1, QString(),
false, QString(), precision );
1134 const QString &srsName,
1135 bool invertAxisOrientation,
1136 const QString &gmlIdBase,
1140 return QDomElement();
1143 QString cs = QStringLiteral(
"," );
1145 QString ts = QStringLiteral(
" " );
1147 QDomElement baseCoordElem;
1149 bool hasZValue =
false;
1151 QByteArray wkb( geometry.
asWkb() );
1155 wkbPtr.readHeader();
1161 return QDomElement();
1164 if ( gmlVersion != GML_2_1_2 )
1172 baseCoordElem = doc.createElement( QStringLiteral(
"gml:pos" ) );
1175 baseCoordElem = doc.createElement( QStringLiteral(
"gml:posList" ) );
1178 baseCoordElem.setAttribute( QStringLiteral(
"srsDimension" ), QStringLiteral(
"2" ) );
1183 baseCoordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1184 baseCoordElem.setAttribute( QStringLiteral(
"cs" ), cs );
1185 baseCoordElem.setAttribute( QStringLiteral(
"ts" ), ts );
1195 QDomElement pointElem = doc.createElement( QStringLiteral(
"gml:Point" ) );
1196 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1197 pointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1198 if ( !srsName.isEmpty() )
1199 pointElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1200 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1204 if ( invertAxisOrientation )
1210 coordElem.appendChild( coordText );
1211 pointElem.appendChild( coordElem );
1220 QDomElement multiPointElem = doc.createElement( QStringLiteral(
"gml:MultiPoint" ) );
1221 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1222 multiPointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1223 if ( !srsName.isEmpty() )
1224 multiPointElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1229 for (
int idx = 0; idx < nPoints; ++idx )
1231 QDomElement pointMemberElem = doc.createElement( QStringLiteral(
"gml:pointMember" ) );
1232 QDomElement pointElem = doc.createElement( QStringLiteral(
"gml:Point" ) );
1233 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1234 pointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( idx + 1 ) );
1235 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1237 wkbPtr.readHeader();
1240 if ( invertAxisOrientation )
1246 coordElem.appendChild( coordText );
1247 pointElem.appendChild( coordElem );
1251 wkbPtr +=
sizeof( double );
1253 pointMemberElem.appendChild( pointElem );
1254 multiPointElem.appendChild( pointMemberElem );
1256 return multiPointElem;
1264 QDomElement lineStringElem = doc.createElement( QStringLiteral(
"gml:LineString" ) );
1265 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1266 lineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1267 if ( !srsName.isEmpty() )
1268 lineStringElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1274 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1275 QString coordString;
1276 for (
int idx = 0; idx < nPoints; ++idx )
1284 if ( invertAxisOrientation )
1292 wkbPtr +=
sizeof( double );
1295 QDomText coordText = doc.createTextNode( coordString );
1296 coordElem.appendChild( coordText );
1297 lineStringElem.appendChild( coordElem );
1298 return lineStringElem;
1306 QDomElement multiLineStringElem = doc.createElement( QStringLiteral(
"gml:MultiLineString" ) );
1307 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1308 multiLineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1309 if ( !srsName.isEmpty() )
1310 multiLineStringElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1315 for (
int jdx = 0; jdx < nLines; jdx++ )
1317 QDomElement lineStringMemberElem = doc.createElement( QStringLiteral(
"gml:lineStringMember" ) );
1318 QDomElement lineStringElem = doc.createElement( QStringLiteral(
"gml:LineString" ) );
1319 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1320 lineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( jdx + 1 ) );
1322 wkbPtr.readHeader();
1327 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1328 QString coordString;
1329 for (
int idx = 0; idx < nPoints; idx++ )
1337 if ( invertAxisOrientation )
1346 wkbPtr +=
sizeof( double );
1349 QDomText coordText = doc.createTextNode( coordString );
1350 coordElem.appendChild( coordText );
1351 lineStringElem.appendChild( coordElem );
1352 lineStringMemberElem.appendChild( lineStringElem );
1353 multiLineStringElem.appendChild( lineStringMemberElem );
1355 return multiLineStringElem;
1363 QDomElement polygonElem = doc.createElement( QStringLiteral(
"gml:Polygon" ) );
1364 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1365 polygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1366 if ( !srsName.isEmpty() )
1367 polygonElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1373 if ( numRings == 0 )
1374 return QDomElement();
1376 int *ringNumPoints =
new int[numRings];
1378 for (
int idx = 0; idx < numRings; idx++ )
1380 QString boundaryName = ( gmlVersion == GML_2_1_2 ) ?
"gml:outerBoundaryIs" :
"gml:exterior";
1383 boundaryName = ( gmlVersion == GML_2_1_2 ) ?
"gml:innerBoundaryIs" :
"gml:interior";
1385 QDomElement boundaryElem = doc.createElement( boundaryName );
1386 QDomElement ringElem = doc.createElement( QStringLiteral(
"gml:LinearRing" ) );
1390 ringNumPoints[idx] = nPoints;
1392 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1393 QString coordString;
1394 for (
int jdx = 0; jdx < nPoints; jdx++ )
1402 if ( invertAxisOrientation )
1410 wkbPtr +=
sizeof( double );
1413 QDomText coordText = doc.createTextNode( coordString );
1414 coordElem.appendChild( coordText );
1415 ringElem.appendChild( coordElem );
1416 boundaryElem.appendChild( ringElem );
1417 polygonElem.appendChild( boundaryElem );
1419 delete [] ringNumPoints;
1428 QDomElement multiPolygonElem = doc.createElement( QStringLiteral(
"gml:MultiPolygon" ) );
1429 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1430 multiPolygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1431 if ( !srsName.isEmpty() )
1432 multiPolygonElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1435 wkbPtr >> numPolygons;
1437 for (
int kdx = 0; kdx < numPolygons; kdx++ )
1439 QDomElement polygonMemberElem = doc.createElement( QStringLiteral(
"gml:polygonMember" ) );
1440 QDomElement polygonElem = doc.createElement( QStringLiteral(
"gml:Polygon" ) );
1441 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1442 polygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( kdx + 1 ) );
1444 wkbPtr.readHeader();
1449 for (
int idx = 0; idx < numRings; idx++ )
1451 QString boundaryName = ( gmlVersion == GML_2_1_2 ) ?
"gml:outerBoundaryIs" :
"gml:exterior";
1454 boundaryName = ( gmlVersion == GML_2_1_2 ) ?
"gml:innerBoundaryIs" :
"gml:interior";
1456 QDomElement boundaryElem = doc.createElement( boundaryName );
1457 QDomElement ringElem = doc.createElement( QStringLiteral(
"gml:LinearRing" ) );
1462 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1463 QString coordString;
1464 for (
int jdx = 0; jdx < nPoints; jdx++ )
1472 if ( invertAxisOrientation )
1481 wkbPtr +=
sizeof( double );
1484 QDomText coordText = doc.createTextNode( coordString );
1485 coordElem.appendChild( coordText );
1486 ringElem.appendChild( coordElem );
1487 boundaryElem.appendChild( ringElem );
1488 polygonElem.appendChild( boundaryElem );
1489 polygonMemberElem.appendChild( polygonElem );
1490 multiPolygonElem.appendChild( polygonMemberElem );
1493 return multiPolygonElem;
1496 return QDomElement();
1502 return QDomElement();
1508 return geometryToGML( geometry, doc, QStringLiteral(
"GML2" ), precision );
1511 QDomElement QgsOgcUtils::createGMLCoordinates(
const QgsPolylineXY &points, QDomDocument &doc )
1513 QDomElement coordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1514 coordElem.setAttribute( QStringLiteral(
"cs" ), QStringLiteral(
"," ) );
1515 coordElem.setAttribute( QStringLiteral(
"ts" ), QStringLiteral(
" " ) );
1517 QString coordString;
1518 QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
1519 for ( ; pointIt != points.constEnd(); ++pointIt )
1521 if ( pointIt != points.constBegin() )
1530 QDomText coordText = doc.createTextNode( coordString );
1531 coordElem.appendChild( coordText );
1535 QDomElement QgsOgcUtils::createGMLPositions(
const QgsPolylineXY &points, QDomDocument &doc )
1537 QDomElement posElem = doc.createElement( QStringLiteral(
"gml:pos" ) );
1538 if ( points.size() > 1 )
1539 posElem = doc.createElement( QStringLiteral(
"gml:posList" ) );
1540 posElem.setAttribute( QStringLiteral(
"srsDimension" ), QStringLiteral(
"2" ) );
1542 QString coordString;
1543 QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
1544 for ( ; pointIt != points.constEnd(); ++pointIt )
1546 if ( pointIt != points.constBegin() )
1555 QDomText coordText = doc.createTextNode( coordString );
1556 posElem.appendChild( coordText );
1566 if ( fillElement.isNull() || !fillElement.hasChildNodes() )
1574 QDomElement cssElem = fillElement.firstChildElement( QStringLiteral(
"CssParameter" ) );
1575 while ( !cssElem.isNull() )
1577 cssName = cssElem.attribute( QStringLiteral(
"name" ), QStringLiteral(
"not_found" ) );
1578 if ( cssName != QLatin1String(
"not_found" ) )
1580 elemText = cssElem.text();
1581 if ( cssName == QLatin1String(
"fill" ) )
1583 color.setNamedColor( elemText );
1585 else if ( cssName == QLatin1String(
"fill-opacity" ) )
1588 double opacity = elemText.toDouble( &ok );
1591 color.setAlphaF( opacity );
1596 cssElem = cssElem.nextSiblingElement( QStringLiteral(
"CssParameter" ) );
1610 if ( element.isNull() || !element.hasChildNodes() )
1617 if ( element.firstChild().nodeType() == QDomNode::TextNode )
1627 QDomElement childElem = element.firstChildElement();
1628 while ( !childElem.isNull() )
1640 if ( !expr->d->mRootNode )
1642 expr->d->mRootNode = node;
1649 childElem = childElem.nextSiblingElement();
1653 expr->d->mExp = expr->
dump();
1658 static const QMap<QString, int> BINARY_OPERATORS_TAG_NAMES_MAP
1678 static int binaryOperatorFromTagName(
const QString &tagName )
1681 return BINARY_OPERATORS_TAG_NAMES_MAP.value( tagName, -1 );
1688 return QStringLiteral(
"PropertyIsLike" );
1690 return BINARY_OPERATORS_TAG_NAMES_MAP.key( op, QString() );
1693 static bool isBinaryOperator(
const QString &tagName )
1695 return binaryOperatorFromTagName( tagName ) >= 0;
1699 static bool isSpatialOperator(
const QString &tagName )
1701 static QStringList spatialOps;
1702 if ( spatialOps.isEmpty() )
1704 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
1705 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
1708 return spatialOps.contains( tagName );
1789 return expressionToOgcFilter( exp, doc, GML_2_1_2, FILTER_OGC_1_0,
1790 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage );
1795 return expressionToOgcExpression( exp, doc, GML_2_1_2, FILTER_OGC_1_0,
1796 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage );
1804 const QString &srsName,
1805 bool honourAxisOrientation,
1806 bool invertAxisOrientation,
1810 return QDomElement();
1816 QgsOgcUtilsExprToFilter utils( doc, gmlVersion, filterVersion, geometryName, srsName, honourAxisOrientation, invertAxisOrientation );
1820 if ( exprRootElem.isNull() )
1821 return QDomElement();
1823 QDomElement filterElem =
1824 ( filterVersion == FILTER_FES_2_0 ) ?
1825 doc.createElementNS( FES_NAMESPACE, QStringLiteral(
"fes:Filter" ) ) :
1826 doc.createElementNS( OGC_NAMESPACE, QStringLiteral(
"ogc:Filter" ) );
1829 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:gml" ) );
1830 if ( gmlVersion == GML_3_2_1 )
1831 attr.setValue( GML32_NAMESPACE );
1834 filterElem.setAttributeNode( attr );
1836 filterElem.appendChild( exprRootElem );
1845 const QString &srsName,
1846 bool honourAxisOrientation,
1847 bool invertAxisOrientation,
1857 return QDomElement();
1865 QgsOgcUtilsExprToFilter utils( doc, gmlVersion, filterVersion, geometryName, srsName, honourAxisOrientation, invertAxisOrientation );
1871 if ( !exprRootElem.isNull() )
1873 return exprRootElem;
1880 *errorMessage = QObject::tr(
"Node type not supported in expression translation: %1" ).arg( node->
nodeType() );
1884 return QDomElement();
1891 const QList<LayerProperties> &layerProperties,
1892 bool honourAxisOrientation,
1893 bool invertAxisOrientation,
1894 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename,
1898 return QDomElement();
1901 layerProperties, honourAxisOrientation, invertAxisOrientation,
1902 mapUnprefixedTypenameToPrefixedTypename );
1906 if ( exprRootElem.isNull() )
1907 return QDomElement();
1909 QDomElement filterElem =
1910 ( filterVersion == FILTER_FES_2_0 ) ?
1911 doc.createElementNS( FES_NAMESPACE, QStringLiteral(
"fes:Filter" ) ) :
1912 doc.createElementNS( OGC_NAMESPACE, QStringLiteral(
"ogc:Filter" ) );
1915 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:gml" ) );
1916 if ( gmlVersion == GML_3_2_1 )
1917 attr.setValue( GML32_NAMESPACE );
1920 filterElem.setAttributeNode( attr );
1922 filterElem.appendChild( exprRootElem );
1934 return expressionUnaryOperatorToOgcFilter( static_cast<const QgsExpressionNodeUnaryOperator *>( node ), expression, context );
1936 return expressionBinaryOperatorToOgcFilter( static_cast<const QgsExpressionNodeBinaryOperator *>( node ), expression, context );
1938 return expressionInOperatorToOgcFilter( static_cast<const QgsExpressionNodeInOperator *>( node ), expression, context );
1940 return expressionFunctionToOgcFilter( static_cast<const QgsExpressionNodeFunction *>( node ), expression, context );
1942 return expressionLiteralToOgcFilter( static_cast<const QgsExpressionNodeLiteral *>( node ), expression, context );
1944 return expressionColumnRefToOgcFilter( static_cast<const QgsExpressionNodeColumnRef *>( node ), expression, context );
1947 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
1948 return QDomElement();
1955 if ( !mErrorMessage.isEmpty() )
1956 return QDomElement();
1959 switch ( node->
op() )
1962 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
1967 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
1968 mDoc.removeChild( operandElem );
1972 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
1973 return QDomElement();
1977 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
1978 uoElem.appendChild( operandElem );
1982 mErrorMessage = QObject::tr(
"Unary operator '%1' not implemented yet" ).arg( node->
text() );
1983 return QDomElement();
1993 if ( !mErrorMessage.isEmpty() )
1994 return QDomElement();
2004 if ( rightLit->
value().isNull() )
2007 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2008 elem.appendChild( leftElem );
2012 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2013 notElem.appendChild( elem );
2027 if ( !mErrorMessage.isEmpty() )
2028 return QDomElement();
2031 QString opText = binaryOperatorToTagName( op );
2032 if ( opText.isEmpty() )
2036 mErrorMessage = QObject::tr(
"Binary operator %1 not implemented yet" ).arg( node->
text() );
2037 return QDomElement();
2040 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2045 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2048 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2049 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2051 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2053 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2056 boElem.appendChild( leftElem );
2057 boElem.appendChild( rightElem );
2064 Q_UNUSED( expression )
2067 switch ( node->
value().type() )
2070 value = QString::number( node->
value().toInt() );
2072 case QVariant::Double:
2075 case QVariant::String:
2076 value = node->
value().toString();
2078 case QVariant::Date:
2079 value = node->
value().toDate().toString( Qt::ISODate );
2081 case QVariant::DateTime:
2082 value = node->
value().toDateTime().toString( Qt::ISODate );
2086 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2087 return QDomElement();
2090 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2091 litElem.appendChild( mDoc.createTextNode( value ) );
2098 Q_UNUSED( expression )
2100 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2101 propElem.appendChild( mDoc.createTextNode( node->
name() ) );
2109 if ( node->
list()->
list().size() == 1 )
2112 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2115 const auto constList = node->
list()->
list();
2119 if ( !mErrorMessage.isEmpty() )
2120 return QDomElement();
2122 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2123 eqElem.appendChild( leftNode.cloneNode() );
2124 eqElem.appendChild( listNode );
2126 orElem.appendChild( eqElem );
2131 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2132 notElem.appendChild( orElem );
2139 static const QMap<QString, QString> BINARY_SPATIAL_OPS_MAP
2141 { QStringLiteral(
"disjoint" ), QStringLiteral(
"Disjoint" ) },
2142 { QStringLiteral(
"intersects" ), QStringLiteral(
"Intersects" )},
2143 { QStringLiteral(
"touches" ), QStringLiteral(
"Touches" ) },
2144 { QStringLiteral(
"crosses" ), QStringLiteral(
"Crosses" ) },
2145 { QStringLiteral(
"contains" ), QStringLiteral(
"Contains" ) },
2146 { QStringLiteral(
"overlaps" ), QStringLiteral(
"Overlaps" ) },
2147 { QStringLiteral(
"within" ), QStringLiteral(
"Within" ) }
2150 static bool isBinarySpatialOperator(
const QString &fnName )
2152 return BINARY_SPATIAL_OPS_MAP.contains( fnName );
2155 static QString tagNameForSpatialOperator(
const QString &fnName )
2157 return BINARY_SPATIAL_OPS_MAP.value( fnName );
2167 return fd->
name() == QLatin1String(
"$geometry" );
2179 if ( fnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2181 const QList<QgsExpressionNode *> &args = fnNode->
args()->
list();
2197 if ( fd->
name() == QLatin1String(
"intersects_bbox" ) )
2199 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2200 Q_ASSERT( argNodes.count() == 2 );
2202 QgsGeometry geom = geometryFromConstExpr( argNodes[1] );
2203 if ( !geom.isNull() && isGeometryColumn( argNodes[0] ) )
2213 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2214 geomProperty.appendChild( mDoc.createTextNode( mGeometryName ) );
2216 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":BBOX" );
2217 funcElem.appendChild( geomProperty );
2218 funcElem.appendChild( elemBox );
2223 mErrorMessage = QObject::tr(
"<BBOX> is currently supported only in form: bbox($geometry, geomFromWKT('…'))" );
2224 return QDomElement();
2228 if ( isBinarySpatialOperator( fd->
name() ) )
2230 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2231 Q_ASSERT( argNodes.count() == 2 );
2234 if ( isGeometryColumn( argNodes[0] ) )
2235 otherNode = argNodes[1];
2236 else if ( isGeometryColumn( argNodes[1] ) )
2237 otherNode = argNodes[0];
2240 mErrorMessage = QObject::tr(
"Unable to translate spatial operator: at least one must refer to geometry." );
2241 return QDomElement();
2244 QDomElement otherGeomElem;
2249 mErrorMessage = QObject::tr(
"spatial operator: the other operator must be a geometry constructor function" );
2250 return QDomElement();
2255 if ( otherFnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2260 mErrorMessage = QObject::tr(
"geom_from_wkt: argument must be string literal" );
2261 return QDomElement();
2266 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2269 else if ( otherFnDef->
name() == QLatin1String(
"geom_from_gml" ) )
2274 mErrorMessage = QObject::tr(
"geom_from_gml: argument must be string literal" );
2275 return QDomElement();
2278 QDomDocument geomDoc;
2280 if ( !geomDoc.setContent( gml,
true ) )
2282 mErrorMessage = QObject::tr(
"geom_from_gml: unable to parse XML" );
2283 return QDomElement();
2286 QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(), true );
2287 otherGeomElem = geomNode.toElement();
2291 mErrorMessage = QObject::tr(
"spatial operator: unknown geometry constructor function" );
2292 return QDomElement();
2297 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + tagNameForSpatialOperator( fd->
name() ) );
2298 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2299 geomProperty.appendChild( mDoc.createTextNode( mGeometryName ) );
2300 funcElem.appendChild( geomProperty );
2301 funcElem.appendChild( otherGeomElem );
2305 if ( fd->
isStatic( node, expression, context ) )
2307 QVariant result = fd->
run( node->
args(), context, expression, node );
2309 return expressionLiteralToOgcFilter( &literal, expression, context );
2314 mErrorMessage = QObject::tr(
"Special columns/constants are not supported." );
2315 return QDomElement();
2319 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
2320 funcElem.setAttribute( QStringLiteral(
"name" ), fd->
name() );
2321 const auto constList = node->
args()->
list();
2325 if ( !mErrorMessage.isEmpty() )
2326 return QDomElement();
2328 funcElem.appendChild( childElem );
2339 const QList<QgsOgcUtils::LayerProperties> &layerProperties,
2340 bool honourAxisOrientation,
2341 bool invertAxisOrientation,
2342 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename )
2345 , mGMLVersion( gmlVersion )
2346 , mFilterVersion( filterVersion )
2347 , mLayerProperties( layerProperties )
2348 , mHonourAxisOrientation( honourAxisOrientation )
2349 , mInvertAxisOrientation( invertAxisOrientation )
2350 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
2351 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
2353 , mMapUnprefixedTypenameToPrefixedTypename( mapUnprefixedTypenameToPrefixedTypename )
2362 return toOgcFilter( static_cast<const QgsSQLStatement::NodeUnaryOperator *>( node ) );
2364 return toOgcFilter( static_cast<const QgsSQLStatement::NodeBinaryOperator *>( node ) );
2366 return toOgcFilter( static_cast<const QgsSQLStatement::NodeInOperator *>( node ) );
2368 return toOgcFilter( static_cast<const QgsSQLStatement::NodeBetweenOperator *>( node ) );
2370 return toOgcFilter( static_cast<const QgsSQLStatement::NodeFunction *>( node ) );
2372 return toOgcFilter( static_cast<const QgsSQLStatement::NodeLiteral *>( node ) );
2374 return toOgcFilter( static_cast<const QgsSQLStatement::NodeColumnRef *>( node ) );
2376 return toOgcFilter( static_cast<const QgsSQLStatement::NodeSelect *>( node ) );
2379 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
2380 return QDomElement();
2389 if ( !mErrorMessage.isEmpty() )
2390 return QDomElement();
2393 switch ( node->
op() )
2396 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2401 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
2402 mDoc.removeChild( operandElem );
2406 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
2407 return QDomElement();
2411 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
2412 uoElem.appendChild( operandElem );
2417 return QDomElement();
2427 if ( !mErrorMessage.isEmpty() )
2428 return QDomElement();
2438 if ( rightLit->
value().isNull() )
2441 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2442 elem.appendChild( leftElem );
2446 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2447 notElem.appendChild( elem );
2461 if ( !mErrorMessage.isEmpty() )
2462 return QDomElement();
2467 opText = QStringLiteral(
"Or" );
2469 opText = QStringLiteral(
"And" );
2471 opText = QStringLiteral(
"PropertyIsEqualTo" );
2473 opText = QStringLiteral(
"PropertyIsNotEqualTo" );
2475 opText = QStringLiteral(
"PropertyIsLessThanOrEqualTo" );
2477 opText = QStringLiteral(
"PropertyIsGreaterThanOrEqualTo" );
2479 opText = QStringLiteral(
"PropertyIsLessThan" );
2481 opText = QStringLiteral(
"PropertyIsGreaterThan" );
2483 opText = QStringLiteral(
"PropertyIsLike" );
2485 opText = QStringLiteral(
"PropertyIsLike" );
2487 if ( opText.isEmpty() )
2491 return QDomElement();
2494 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2499 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2502 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2503 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2505 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2507 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2510 boElem.appendChild( leftElem );
2511 boElem.appendChild( rightElem );
2519 switch ( node->
value().type() )
2522 value = QString::number( node->
value().toInt() );
2524 case QVariant::LongLong:
2525 value = QString::number( node->
value().toLongLong() );
2527 case QVariant::Double:
2530 case QVariant::String:
2531 value = node->
value().toString();
2535 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2536 return QDomElement();
2539 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2540 litElem.appendChild( mDoc.createTextNode( value ) );
2547 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2548 if ( node->
tableName().isEmpty() || mLayerProperties.size() == 1 )
2549 propElem.appendChild( mDoc.createTextNode( node->
name() ) );
2552 QString tableName( mMapTableAliasToNames[node->
tableName()] );
2553 if ( mMapUnprefixedTypenameToPrefixedTypename.contains( tableName ) )
2554 tableName = mMapUnprefixedTypenameToPrefixedTypename[tableName];
2555 propElem.appendChild( mDoc.createTextNode( tableName +
"/" + node->
name() ) );
2562 if ( node->
list()->
list().size() == 1 )
2565 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2568 const auto constList = node->
list()->
list();
2572 if ( !mErrorMessage.isEmpty() )
2573 return QDomElement();
2575 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2576 eqElem.appendChild( leftNode.cloneNode() );
2577 eqElem.appendChild( listNode );
2579 orElem.appendChild( eqElem );
2584 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2585 notElem.appendChild( orElem );
2594 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsBetween" );
2596 QDomElement lowerBoundary = mDoc.createElement( mFilterPrefix +
":LowerBoundary" );
2598 elem.appendChild( lowerBoundary );
2599 QDomElement upperBoundary = mDoc.createElement( mFilterPrefix +
":UpperBoundary" );
2601 elem.appendChild( upperBoundary );
2605 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2606 notElem.appendChild( elem );
2613 static QString mapBinarySpatialToOgc(
const QString &name )
2615 QString nameCompare( name );
2616 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2617 nameCompare = name.mid( 3 );
2618 QStringList spatialOps;
2619 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
2620 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
2621 const auto constSpatialOps = spatialOps;
2622 for ( QString op : constSpatialOps )
2624 if ( nameCompare.compare( op, Qt::CaseInsensitive ) == 0 )
2630 static QString mapTernarySpatialToOgc(
const QString &name )
2632 QString nameCompare( name );
2633 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2634 nameCompare = name.mid( 3 );
2635 if ( nameCompare.compare( QLatin1String(
"DWithin" ), Qt::CaseInsensitive ) == 0 )
2636 return QStringLiteral(
"DWithin" );
2637 if ( nameCompare.compare( QLatin1String(
"Beyond" ), Qt::CaseInsensitive ) == 0 )
2638 return QStringLiteral(
"Beyond" );
2642 QString QgsOgcUtilsSQLStatementToFilter::getGeometryColumnSRSName(
const QgsSQLStatement::Node *node )
2650 const auto constMLayerProperties = mLayerProperties;
2653 if ( prop.mName.compare( mMapTableAliasToNames[col->
tableName()], Qt::CaseInsensitive ) == 0 &&
2654 prop.mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2656 return prop.mSRSName;
2660 if ( !mLayerProperties.empty() &&
2661 mLayerProperties.at( 0 ).mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2663 return mLayerProperties.at( 0 ).mSRSName;
2669 QList<QgsSQLStatement::Node *> args,
2670 bool lastArgIsSRSName,
2672 bool &axisInversion )
2674 srsName = mCurrentSRSName;
2675 axisInversion = mInvertAxisOrientation;
2677 if ( lastArgIsSRSName )
2682 mErrorMessage = QObject::tr(
"%1: Last argument must be string or integer literal" ).arg( mainNode->
name() );
2686 if ( lit->
value().type() == QVariant::Int )
2690 srsName =
"EPSG:" + QString::number( lit->
value().toInt() );
2694 srsName =
"urn:ogc:def:crs:EPSG::" + QString::number( lit->
value().toInt() );
2699 srsName = lit->
value().toString();
2700 if ( srsName.startsWith( QLatin1String(
"EPSG:" ), Qt::CaseInsensitive ) )
2706 if ( !srsName.isEmpty() )
2712 axisInversion = !axisInversion;
2722 if ( node->
name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 )
2724 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2725 if ( args.size() != 1 && args.size() != 2 )
2727 mErrorMessage = QObject::tr(
"Function %1 should have 1 or 2 arguments" ).arg( node->
name() );
2728 return QDomElement();
2734 mErrorMessage = QObject::tr(
"%1: First argument must be string literal" ).arg( node->
name() );
2735 return QDomElement();
2740 if ( ! processSRSName( node, args, args.size() == 2, srsName, axisInversion ) )
2742 return QDomElement();
2748 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2750 if ( geomElem.isNull() )
2752 mErrorMessage = QObject::tr(
"%1: invalid WKT" ).arg( node->
name() );
2753 return QDomElement();
2760 if ( node->
name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 )
2762 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2763 if ( args.size() != 4 && args.size() != 5 )
2765 mErrorMessage = QObject::tr(
"Function %1 should have 4 or 5 arguments" ).arg( node->
name() );
2766 return QDomElement();
2771 for (
int i = 0; i < 4; i++ )
2776 mErrorMessage = QObject::tr(
"%1: Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2777 return QDomElement();
2781 if ( lit->
value().type() == QVariant::Int )
2782 val = lit->
value().toInt();
2783 else if ( lit->
value().type() == QVariant::LongLong )
2784 val = lit->
value().toLongLong();
2785 else if ( lit->
value().type() == QVariant::Double )
2786 val = lit->
value().toDouble();
2789 mErrorMessage = QObject::tr(
"%1 Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2790 return QDomElement();
2804 if ( ! processSRSName( node, args, args.size() == 5, srsName, axisInversion ) )
2806 return QDomElement();
2817 if ( node->
name().compare( QLatin1String(
"ST_GeomFromGML" ), Qt::CaseInsensitive ) == 0 )
2819 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2820 if ( args.size() != 1 )
2822 mErrorMessage = QObject::tr(
"Function %1 should have 1 argument" ).arg( node->
name() );
2823 return QDomElement();
2829 mErrorMessage = QObject::tr(
"%1: Argument must be string literal" ).arg( node->
name() );
2830 return QDomElement();
2833 QDomDocument geomDoc;
2835 if ( !geomDoc.setContent( gml,
true ) )
2837 mErrorMessage = QObject::tr(
"ST_GeomFromGML: unable to parse XML" );
2838 return QDomElement();
2841 QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(), true );
2843 return geomNode.toElement();
2847 QString ogcName( mapBinarySpatialToOgc( node->
name() ) );
2848 if ( !ogcName.isEmpty() )
2850 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2851 if ( args.size() != 2 )
2853 mErrorMessage = QObject::tr(
"Function %1 should have 2 arguments" ).arg( node->
name() );
2854 return QDomElement();
2857 for (
int i = 0; i < 2; i ++ )
2860 ( static_cast<const QgsSQLStatement::NodeFunction *>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
2861 static_cast<const QgsSQLStatement::NodeFunction *>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
2863 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
2870 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + ogcName );
2871 const auto constArgs = args;
2875 if ( !mErrorMessage.isEmpty() )
2877 mCurrentSRSName.clear();
2878 return QDomElement();
2881 funcElem.appendChild( childElem );
2884 mCurrentSRSName.clear();
2888 ogcName = mapTernarySpatialToOgc( node->
name() );
2889 if ( !ogcName.isEmpty() )
2891 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2892 if ( args.size() != 3 )
2894 mErrorMessage = QObject::tr(
"Function %1 should have 3 arguments" ).arg( node->
name() );
2895 return QDomElement();
2898 for (
int i = 0; i < 2; i ++ )
2901 ( static_cast<const QgsSQLStatement::NodeFunction *>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
2902 static_cast<const QgsSQLStatement::NodeFunction *>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
2904 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
2909 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + node->
name().mid( 3 ) );
2910 for (
int i = 0; i < 2; i++ )
2913 if ( !mErrorMessage.isEmpty() )
2915 mCurrentSRSName.clear();
2916 return QDomElement();
2919 funcElem.appendChild( childElem );
2921 mCurrentSRSName.clear();
2926 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() );
2927 return QDomElement();
2930 if ( lit->
value().isNull() )
2932 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() );
2933 return QDomElement();
2936 QString unit( QStringLiteral(
"m" ) );
2937 switch ( lit->
value().type() )
2940 distance = QString::number( lit->
value().toInt() );
2942 case QVariant::LongLong:
2943 distance = QString::number( lit->
value().toLongLong() );
2945 case QVariant::Double:
2948 case QVariant::String:
2950 distance = lit->
value().toString();
2951 for (
int i = 0; i < distance.size(); i++ )
2953 if ( !( ( distance[i] >=
'0' && distance[i] <=
'9' ) || distance[i] ==
'-' || distance[i] ==
'.' || distance[i] ==
'e' || distance[i] ==
'E' ) )
2955 unit = distance.mid( i ).trimmed();
2956 distance = distance.mid( 0, i );
2964 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( lit->
value().type() );
2965 return QDomElement();
2968 QDomElement distanceElem = mDoc.createElement( mFilterPrefix +
":Distance" );
2970 distanceElem.setAttribute( QStringLiteral(
"uom" ), unit );
2972 distanceElem.setAttribute( QStringLiteral(
"unit" ), unit );
2973 distanceElem.appendChild( mDoc.createTextNode( distance ) );
2974 funcElem.appendChild( distanceElem );
2979 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
2980 funcElem.setAttribute( QStringLiteral(
"name" ), node->
name() );
2981 const auto constList = node->
args()->
list();
2985 if ( !mErrorMessage.isEmpty() )
2986 return QDomElement();
2988 funcElem.appendChild( childElem );
2994 const QString &leftTable )
3002 QList<QDomElement> listElem;
3004 for (
const QString &columnName : constUsingColumns )
3006 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
3007 QDomElement propElem1 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3008 propElem1.appendChild( mDoc.createTextNode( leftTable +
"/" + columnName ) );
3009 eqElem.appendChild( propElem1 );
3010 QDomElement propElem2 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3011 propElem2.appendChild( mDoc.createTextNode( node->
tableDef()->
name() +
"/" + columnName ) );
3012 eqElem.appendChild( propElem2 );
3013 listElem.append( eqElem );
3016 if ( listElem.size() == 1 )
3020 else if ( listElem.size() > 1 )
3022 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3023 const auto constListElem = listElem;
3024 for (
const QDomElement &elem : constListElem )
3026 andElem.appendChild( elem );
3031 return QDomElement();
3036 if ( node->
alias().isEmpty() )
3038 mMapTableAliasToNames[ node->
name()] = node->
name();
3042 mMapTableAliasToNames[ node->
alias()] = node->
name();
3048 QList<QDomElement> listElem;
3051 ( node->
tables().size() != 1 || !node->
joins().empty() ) )
3053 mErrorMessage = QObject::tr(
"Joins are only supported with WFS 2.0" );
3054 return QDomElement();
3058 const auto constTables = node->
tables();
3063 const auto constJoins = node->
joins();
3066 visit( join->tableDef() );
3070 QList< QgsSQLStatement::NodeTableDef *> nodeTables = node->
tables();
3071 QString leftTable = nodeTables.at( nodeTables.length() - 1 )->name();
3074 QDomElement joinElem =
toOgcFilter( join, leftTable );
3075 if ( !mErrorMessage.isEmpty() )
3076 return QDomElement();
3077 listElem.append( joinElem );
3078 leftTable = join->tableDef()->name();
3082 if ( node->
where() )
3085 if ( !mErrorMessage.isEmpty() )
3086 return QDomElement();
3087 listElem.append( whereElem );
3091 if ( listElem.size() == 1 )
3095 else if ( listElem.size() > 1 )
3097 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3098 const auto constListElem = listElem;
3099 for (
const QDomElement &elem : constListElem )
3101 andElem.appendChild( elem );
3106 return QDomElement();
3112 mPropertyName = QStringLiteral(
"PropertyName" );
3113 mPrefix = QStringLiteral(
"ogc" );
3117 mPropertyName = QStringLiteral(
"ValueReference" );
3118 mPrefix = QStringLiteral(
"fes" );
3124 if ( element.isNull() )
3128 if ( isBinaryOperator( element.tagName() ) )
3134 if ( isSpatialOperator( element.tagName() ) )
3140 if ( element.tagName() == QLatin1String(
"Not" ) )
3144 else if ( element.tagName() == QLatin1String(
"PropertyIsNull" ) )
3148 else if ( element.tagName() == QLatin1String(
"Literal" ) )
3152 else if ( element.tagName() == QLatin1String(
"Function" ) )
3156 else if ( element.tagName() == mPropertyName )
3160 else if ( element.tagName() == QLatin1String(
"PropertyIsBetween" ) )
3165 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() );
3171 if ( element.isNull() )
3174 int op = binaryOperatorFromTagName( element.tagName() );
3177 mErrorMessage = QObject::tr(
"'%1' binary operator not supported." ).arg( element.tagName() );
3181 if ( op ==
QgsExpressionNodeBinaryOperator::boLike && element.hasAttribute( QStringLiteral(
"matchCase" ) ) && element.attribute( QStringLiteral(
"matchCase" ) ) == QLatin1String(
"false" ) )
3186 QDomElement operandElem = element.firstChildElement();
3191 mErrorMessage = QObject::tr(
"invalid left operand for '%1' binary operator" ).arg( element.tagName() );
3195 std::unique_ptr<QgsExpressionNode> leftOp( expr->clone() );
3196 for ( operandElem = operandElem.nextSiblingElement(); !operandElem.isNull(); operandElem = operandElem.nextSiblingElement() )
3201 mErrorMessage = QObject::tr(
"invalid right operand for '%1' binary operator" ).arg( element.tagName() );
3208 if ( element.hasAttribute( QStringLiteral(
"wildCard" ) ) )
3210 wildCard = element.attribute( QStringLiteral(
"wildCard" ) );
3213 if ( element.hasAttribute( QStringLiteral(
"singleChar" ) ) )
3215 singleChar = element.attribute( QStringLiteral(
"singleChar" ) );
3217 QString escape = QStringLiteral(
"\\" );
3218 if ( element.hasAttribute( QStringLiteral(
"escape" ) ) )
3220 escape = element.attribute( QStringLiteral(
"escape" ) );
3222 if ( element.hasAttribute( QStringLiteral(
"escapeChar" ) ) )
3224 escape = element.attribute( QStringLiteral(
"escapeChar" ) );
3228 if ( !wildCard.isEmpty() && wildCard != QLatin1String(
"%" ) )
3230 oprValue.replace(
'%', QLatin1String(
"\\%" ) );
3231 if ( oprValue.startsWith( wildCard ) )
3233 oprValue.replace( 0, 1, QStringLiteral(
"%" ) );
3235 QRegExp rx(
"[^" + QRegExp::escape( escape ) +
"](" + QRegExp::escape( wildCard ) +
")" );
3237 while ( ( pos = rx.indexIn( oprValue, pos ) ) != -1 )
3239 oprValue.replace( pos + 1, 1, QStringLiteral(
"%" ) );
3242 oprValue.replace( escape + wildCard, wildCard );
3244 if ( !singleChar.isEmpty() && singleChar != QLatin1String(
"_" ) )
3246 oprValue.replace(
'_', QLatin1String(
"\\_" ) );
3247 if ( oprValue.startsWith( singleChar ) )
3249 oprValue.replace( 0, 1, QStringLiteral(
"_" ) );
3251 QRegExp rx(
"[^" + QRegExp::escape( escape ) +
"](" + QRegExp::escape( singleChar ) +
")" );
3253 while ( ( pos = rx.indexIn( oprValue, pos ) ) != -1 )
3255 oprValue.replace( pos + 1, 1, QStringLiteral(
"_" ) );
3258 oprValue.replace( escape + singleChar, singleChar );
3260 if ( !escape.isEmpty() && escape != QLatin1String(
"\\" ) )
3262 oprValue.replace( escape + escape, escape );
3267 expr.reset(
new QgsExpressionNodeBinaryOperator( static_cast< QgsExpressionNodeBinaryOperator::BinaryOperator >( op ), expr.release(), opRight.release() ) );
3270 if ( expr == leftOp )
3272 mErrorMessage = QObject::tr(
"only one operand for '%1' binary operator" ).arg( element.tagName() );
3286 QDomElement childElem = element.firstChildElement();
3288 while ( !childElem.isNull() && gml2Str.isEmpty() )
3290 if ( childElem.tagName() != mPropertyName )
3292 QTextStream gml2Stream( &gml2Str );
3293 childElem.save( gml2Stream, 0 );
3295 childElem = childElem.nextSiblingElement();
3297 if ( !gml2Str.isEmpty() )
3303 mErrorMessage = QObject::tr(
"No OGC Geometry found" );
3316 if ( element.isNull() || element.tagName() != mPropertyName )
3318 mErrorMessage = QObject::tr(
"%1:PropertyName expected, got %2" ).arg( mPrefix, element.tagName() );
3327 if ( element.isNull() || element.tagName() != QLatin1String(
"Literal" ) )
3329 mErrorMessage = QObject::tr(
"%1:Literal expected, got %2" ).arg( mPrefix, element.tagName() );
3333 std::unique_ptr<QgsExpressionNode> root;
3336 QDomNode childNode = element.firstChild();
3337 while ( !childNode.isNull() )
3339 std::unique_ptr<QgsExpressionNode> operand;
3341 if ( childNode.nodeType() == QDomNode::ElementNode )
3344 const QDomElement operandElem = childNode.toElement();
3348 mErrorMessage = QObject::tr(
"'%1' is an invalid or not supported content for %2:Literal" ).arg( operandElem.tagName(), mPrefix );
3355 QVariant value = childNode.nodeValue();
3357 bool converted =
false;
3362 QDomElement propertyNameElement = element.previousSiblingElement( mPropertyName );
3363 if ( propertyNameElement.isNull() || propertyNameElement.tagName() != mPropertyName )
3365 propertyNameElement = element.nextSiblingElement( mPropertyName );
3367 if ( !propertyNameElement.isNull() || propertyNameElement.tagName() == mPropertyName )
3369 const int fieldIndex = mLayer->
fields().
indexOf( propertyNameElement.firstChild().nodeValue() );
3370 if ( fieldIndex != -1 )
3383 const double d = value.toDouble( &ok );
3396 root = std::move( operand );
3403 childNode = childNode.nextSibling();
3407 return root.release();
3414 if ( element.tagName() != QLatin1String(
"Not" ) )
3417 const QDomElement operandElem = element.firstChildElement();
3421 mErrorMessage = QObject::tr(
"invalid operand for '%1' unary operator" ).arg( element.tagName() );
3431 if ( element.tagName() != QLatin1String(
"PropertyIsNull" ) )
3436 const QDomElement operandElem = element.firstChildElement();
3447 if ( element.isNull() || element.tagName() != QLatin1String(
"Function" ) )
3449 mErrorMessage = QObject::tr(
"%1:Function expected, got %2" ).arg( mPrefix, element.tagName() );
3457 if ( element.attribute( QStringLiteral(
"name" ) ) != funcDef->
name() )
3462 QDomElement operandElem = element.firstChildElement();
3463 while ( !operandElem.isNull() )
3470 args->append( op.release() );
3472 operandElem = operandElem.nextSiblingElement();
3484 std::unique_ptr<QgsExpressionNode> operand;
3485 std::unique_ptr<QgsExpressionNode> lowerBound;
3486 std::unique_ptr<QgsExpressionNode> upperBound;
3488 QDomElement operandElem = element.firstChildElement();
3489 while ( !operandElem.isNull() )
3491 if ( operandElem.tagName() == QLatin1String(
"LowerBoundary" ) )
3493 QDomElement lowerBoundElem = operandElem.firstChildElement();
3496 else if ( operandElem.tagName() == QLatin1String(
"UpperBoundary" ) )
3498 QDomElement upperBoundElem = operandElem.firstChildElement();
3507 if ( operand && lowerBound && upperBound )
3510 operandElem = operandElem.nextSiblingElement();
3513 if ( !operand || !lowerBound || !upperBound )
3515 mErrorMessage = QObject::tr(
"missing some required sub-elements in %1:PropertyIsBetween" ).arg( mPrefix );
3526 return mErrorMessage;
Class for parsing and evaluation of expressions (formerly called "search strings").
QgsSQLStatement::NodeList * list() const
Values list.
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.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
QDomElement expressionNodeToOgcFilter(const QgsExpressionNode *node, QgsExpression *expression, const QgsExpressionContext *context)
Convert an expression to a OGC filter.
QgsExpressionNode * nodeLiteralFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with literal tag.
QgsSQLStatement::Node * onExpr() const
On expression. Will be nullptr if usingColumns() is not empty.
int params() const
The number of parameters this function takes.
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.
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...
QgsExpressionNode * nodeFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document element.
QgsExpressionNode * opRight() const
Returns the node to the right of the operator.
QgsWkbTypes::Type wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
QgsExpressionNodeFunction * nodeFunctionFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with functions.
A class to represent a 2D point.
QgsSQLStatement::NodeTableDef * tableDef() const
Table definition.
QString dump() const
Returns an expression string, constructed from the internal abstract syntax tree. ...
QgsSQLStatement::Node * operand() const
Operand.
QgsSQLStatement::Node * where() const
Returns the where clause.
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 convertCompatible(QVariant &v) const
Converts the provided variant to a compatible format.
QString errorMessage() const
Returns the error message.
bool GMLNamespaceUsed() const
Returns whether the gml: namespace is used.
A geometry is the spatial representation of a feature.
QgsExpressionNode::NodeList * list() const
Returns the list of nodes to search for matching values within.
QgsExpressionNodeUnaryOperator * nodeNotFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with Not operator.
QgsExpressionNode * opLeft() const
Returns the node to the left of the operator.
static QDomElement rectangleToGMLBox(QgsRectangle *box, QDomDocument &doc, int precision=17)
Exports the rectangle to GML2 Box.
QDomElement toOgcFilter(const QgsSQLStatement::Node *node)
Convert a SQL statement to a OGC filter.
const QgsCoordinateReferenceSystem & crs
Binary logical/arithmetical operator (AND, OR, =, +, ...)
QString name() const
The name of the column.
QString errorMessage() const
Returns the underlying error message, or an empty string in case of no error.
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
QString name() const
Returns function name.
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.
static QgsRectangle rectangleFromGMLBox(const QDomNode &boxNode)
Read rectangle from GML2 Box.
QgsSQLStatement::Node * node() const
Variable at the left of BETWEEN.
QList< QString > usingColumns() const
Columns referenced by USING.
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.
QgsSQLStatement::Node * minVal() const
Minimum bound.
bool GMLNamespaceUsed() const
Returns whether the gml: namespace is used.
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.
QString text() const
Returns a the name of this operator without the operands.
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.
QString name() const
Table name.
QString alias() const
Table alias.
static int functionIndex(const QString &name)
Returns index of the function in Functions array.
const QString & geometryName
QgsExpressionNodeFunction * nodeSpatialOperatorFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with spatial operators.
QgsSQLStatement::NodeList * args() const
Returns arguments.
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...
BinaryOperator
list of binary operators
An expression node for value IN or NOT IN clauses.
Literal value (integer, integer64, double, string)
QString errorMessage() const
Returns the error message.
QString name() const
The name of the column.
QList< QgsSQLStatement::NodeTableDef * > tables() const
Returns the list of tables.
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, - )
QgsSQLStatement::BinaryOperator op() const
Operator.
const QgsSQLStatement::Node * rootNode() const
Returns the root node of the statement.
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
virtual bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
Will be called during prepare to determine if the function is static.
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.
static const QList< QgsExpressionFunction * > & Functions()
QgsSQLStatement::Node * maxVal() const
Maximum bound.
bool isNotBetween() const
Whether this is a NOT BETWEEN operator.
FilterVersion
OGC filter version.
QByteArray asWkb() const
Export the geometry to WKB.
'X BETWEEN y and z' operator
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
QString name() const
The name of the function.
Custom exception class for Wkb related exceptions.
double xMaximum() const
Returns the x maximum value (right side of rectangle).
QVariant value() const
The value of the literal.
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
QList< QgsSQLStatement::NodeJoin * > joins() const
Returns the list of joins.
A abstract base class for defining QgsExpression functions.
A list of expression nodes.
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.
QgsExpressionNodeUnaryOperator::UnaryOperator op() const
Returns the unary operator.
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
An expression node for literal values.
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
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.
A binary expression operator, which operates on two values.
bool hasAxisInverted() const
Returns whether axis is inverted (e.g., for WMS 1.3) for the CRS.
This class represents a coordinate reference system (CRS).
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.
QString text() const
Returns a the name of this operator without the operands.
static QDomElement rectangleToGMLEnvelope(QgsRectangle *env, QDomDocument &doc, int precision=17)
Exports the rectangle to GML3 Envelope.
static const char * UNARY_OPERATOR_TEXT[]
double xMinimum() const
Returns the x minimum value (left side of rectangle).
static QColor colorFromOgcFill(const QDomElement &fillElement)
Parse XML with OGC fill into QColor.
QgsOgcUtilsExpressionFromFilter(QgsOgcUtils::FilterVersion version=QgsOgcUtils::FILTER_OGC_1_0, const QgsVectorLayer *layer=nullptr)
Constructor for QgsOgcUtilsExpressionFromFilter.
QString tableName() const
The name of the table. May be empty.
double yMaximum() const
Returns the y maximum value (top side of rectangle).
void normalize()
Normalize the rectangle so it has non-negative width/height.
QgsSQLStatement::UnaryOperator op() const
Operator.
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
QgsExpressionNode * node() const
Returns the expression node.
Represents a vector layer which manages a vector based data sets.
'x IN (y, z)' operator
bool isNotIn() const
Returns true if this node is a "NOT IN" operator, or false if the node is a normal "IN" operator...
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
QgsExpressionNode * operand() const
Returns the node the operator will operate upon.
QgsSQLStatement::Node * node() const
Variable at the left of IN.
The QgsOgcUtils class provides various utility functions for conversion between OGC (Open Geospatial ...
QgsExpressionNodeBinaryOperator::BinaryOperator op() const
Returns the binary operator.
QgsSQLStatement::Node * opLeft() const
Left operand.
QgsField field(int fieldIdx) const
Gets field at particular index (must be in range 0..N-1)
QgsSQLStatement::Node * opRight() const
Right operand.
QgsExpressionNodeBinaryOperator * nodePropertyIsNullFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with IsNull operator.
void setXMinimum(double x)
Set the minimum x value.
QVariant value() const
The value of the literal.
virtual QgsSQLStatement::NodeType nodeType() const =0
Abstract virtual that returns the type of this node.
int fnIndex() const
Returns the index of the node's function.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.