17 #include "qgsexpression.h" 18 #include "qgsexpressionnodeimpl.h" 19 #include "qgsexpressionfunction.h" 27 #include <QStringList> 28 #include <QTextStream> 32 #include <netinet/in.h> 38 static const QString
GML_NAMESPACE = QStringLiteral(
"http://www.opengis.net/gml" );
39 static const QString GML32_NAMESPACE = QStringLiteral(
"http://www.opengis.net/gml/3.2" );
40 static const QString OGC_NAMESPACE = QStringLiteral(
"http://www.opengis.net/ogc" );
41 static const QString FES_NAMESPACE = QStringLiteral(
"http://www.opengis.net/fes/2.0" );
46 const QString &geometryName,
47 const QString &srsName,
48 bool honourAxisOrientation,
49 bool invertAxisOrientation )
52 , mGMLVersion( gmlVersion )
53 , mFilterVersion( filterVersion )
54 , mGeometryName( geometryName )
56 , mInvertAxisOrientation( invertAxisOrientation )
57 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
58 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
62 if ( !mSrsName.isEmpty() )
68 mInvertAxisOrientation = !mInvertAxisOrientation;
75 QDomElement geometryTypeElement = geometryNode.toElement();
76 QString geomType = geometryTypeElement.tagName();
78 if ( !( geomType == QLatin1String(
"Point" ) || geomType == QLatin1String(
"LineString" ) || geomType == QLatin1String(
"Polygon" ) ||
79 geomType == QLatin1String(
"MultiPoint" ) || geomType == QLatin1String(
"MultiLineString" ) || geomType == QLatin1String(
"MultiPolygon" ) ||
80 geomType == QLatin1String(
"Box" ) || geomType == QLatin1String(
"Envelope" ) ) )
82 QDomNode geometryChild = geometryNode.firstChild();
83 if ( geometryChild.isNull() )
87 geometryTypeElement = geometryChild.toElement();
88 geomType = geometryTypeElement.tagName();
91 if ( !( geomType == QLatin1String(
"Point" ) || geomType == QLatin1String(
"LineString" ) || geomType == QLatin1String(
"Polygon" ) ||
92 geomType == QLatin1String(
"MultiPoint" ) || geomType == QLatin1String(
"MultiLineString" ) || geomType == QLatin1String(
"MultiPolygon" ) ||
93 geomType == QLatin1String(
"Box" ) || geomType == QLatin1String(
"Envelope" ) ) )
96 if ( geomType == QLatin1String(
"Point" ) )
98 return geometryFromGMLPoint( geometryTypeElement );
100 else if ( geomType == QLatin1String(
"LineString" ) )
102 return geometryFromGMLLineString( geometryTypeElement );
104 else if ( geomType == QLatin1String(
"Polygon" ) )
106 return geometryFromGMLPolygon( geometryTypeElement );
108 else if ( geomType == QLatin1String(
"MultiPoint" ) )
110 return geometryFromGMLMultiPoint( geometryTypeElement );
112 else if ( geomType == QLatin1String(
"MultiLineString" ) )
114 return geometryFromGMLMultiLineString( geometryTypeElement );
116 else if ( geomType == QLatin1String(
"MultiPolygon" ) )
118 return geometryFromGMLMultiPolygon( geometryTypeElement );
120 else if ( geomType == QLatin1String(
"Box" ) )
124 else if ( geomType == QLatin1String(
"Envelope" ) )
137 QString xml = QStringLiteral(
"<tmp xmlns=\"%1\" xmlns:gml=\"%1\">%2</tmp>" ).arg(
GML_NAMESPACE, xmlString );
139 if ( !doc.setContent( xml,
true ) )
142 return geometryFromGML( doc.documentElement().firstChildElement() );
146 QgsGeometry QgsOgcUtils::geometryFromGMLPoint(
const QDomElement &geometryElement )
150 QDomNodeList coordList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
151 if ( !coordList.isEmpty() )
153 QDomElement coordElement = coordList.at( 0 ).toElement();
154 if ( readGMLCoordinates( pointCoordinate, coordElement ) != 0 )
161 QDomNodeList posList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pos" ) );
162 if ( posList.size() < 1 )
166 QDomElement posElement = posList.at( 0 ).toElement();
167 if ( readGMLPositions( pointCoordinate, posElement ) != 0 )
173 if ( pointCoordinate.empty() )
178 QgsPolylineXY::const_iterator point_it = pointCoordinate.constBegin();
179 char e = htonl( 1 ) != 1;
180 double x = point_it->x();
181 double y = point_it->y();
182 int size = 1 +
sizeof( int ) + 2 *
sizeof(
double );
185 unsigned char *wkb =
new unsigned char[size];
188 memcpy( &( wkb )[wkbPosition], &e, 1 );
190 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
191 wkbPosition +=
sizeof( int );
192 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
193 wkbPosition +=
sizeof( double );
194 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
201 QgsGeometry QgsOgcUtils::geometryFromGMLLineString(
const QDomElement &geometryElement )
205 QDomNodeList coordList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
206 if ( !coordList.isEmpty() )
208 QDomElement coordElement = coordList.at( 0 ).toElement();
209 if ( readGMLCoordinates( lineCoordinates, coordElement ) != 0 )
216 QDomNodeList posList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
217 if ( posList.size() < 1 )
221 QDomElement posElement = posList.at( 0 ).toElement();
222 if ( readGMLPositions( lineCoordinates, posElement ) != 0 )
228 char e = htonl( 1 ) != 1;
229 int size = 1 + 2 *
sizeof( int ) + lineCoordinates.size() * 2 *
sizeof( double );
232 unsigned char *wkb =
new unsigned char[size];
236 int nPoints = lineCoordinates.size();
239 memcpy( &( wkb )[wkbPosition], &e, 1 );
241 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
242 wkbPosition +=
sizeof( int );
243 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
244 wkbPosition +=
sizeof( int );
246 QgsPolylineXY::const_iterator iter;
247 for ( iter = lineCoordinates.constBegin(); iter != lineCoordinates.constEnd(); ++iter )
251 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
252 wkbPosition +=
sizeof( double );
253 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
254 wkbPosition +=
sizeof( double );
262 QgsGeometry QgsOgcUtils::geometryFromGMLPolygon(
const QDomElement &geometryElement )
269 QDomNodeList outerBoundaryList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"outerBoundaryIs" ) );
270 if ( !outerBoundaryList.isEmpty() )
272 QDomElement coordinatesElement = outerBoundaryList.at( 0 ).firstChild().firstChild().toElement();
273 if ( coordinatesElement.isNull() )
277 if ( readGMLCoordinates( exteriorPointList, coordinatesElement ) != 0 )
281 ringCoordinates.push_back( exteriorPointList );
284 QDomNodeList innerBoundaryList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"innerBoundaryIs" ) );
285 for (
int i = 0; i < innerBoundaryList.size(); ++i )
288 coordinatesElement = innerBoundaryList.at( i ).firstChild().firstChild().toElement();
289 if ( coordinatesElement.isNull() )
293 if ( readGMLCoordinates( interiorPointList, coordinatesElement ) != 0 )
297 ringCoordinates.push_back( interiorPointList );
303 QDomNodeList exteriorList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"exterior" ) );
304 if ( exteriorList.size() < 1 )
308 QDomElement posElement = exteriorList.at( 0 ).firstChild().firstChild().toElement();
309 if ( posElement.isNull() )
313 if ( readGMLPositions( exteriorPointList, posElement ) != 0 )
317 ringCoordinates.push_back( exteriorPointList );
320 QDomNodeList interiorList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"interior" ) );
321 for (
int i = 0; i < interiorList.size(); ++i )
324 QDomElement posElement = interiorList.at( i ).firstChild().firstChild().toElement();
325 if ( posElement.isNull() )
329 if ( readGMLPositions( interiorPointList, posElement ) != 0 )
333 ringCoordinates.push_back( interiorPointList );
338 int nrings = ringCoordinates.size();
343 for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
345 npoints += it->size();
347 int size = 1 + 2 *
sizeof( int ) + nrings *
sizeof(
int ) + 2 * npoints *
sizeof( double );
350 unsigned char *wkb =
new unsigned char[size];
353 char e = htonl( 1 ) != 1;
355 int nPointsInRing = 0;
359 memcpy( &( wkb )[wkbPosition], &e, 1 );
361 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
362 wkbPosition +=
sizeof( int );
363 memcpy( &( wkb )[wkbPosition], &nrings,
sizeof(
int ) );
364 wkbPosition +=
sizeof( int );
365 for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
367 nPointsInRing = it->size();
368 memcpy( &( wkb )[wkbPosition], &nPointsInRing,
sizeof(
int ) );
369 wkbPosition +=
sizeof( int );
371 QgsPolylineXY::const_iterator iter;
372 for ( iter = it->begin(); iter != it->end(); ++iter )
377 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
378 wkbPosition +=
sizeof( double );
379 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
380 wkbPosition +=
sizeof( double );
389 QgsGeometry QgsOgcUtils::geometryFromGMLMultiPoint(
const QDomElement &geometryElement )
393 QDomNodeList pointMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pointMember" ) );
394 if ( pointMemberList.size() < 1 )
398 QDomNodeList pointNodeList;
400 QDomNodeList coordinatesList;
401 QDomNodeList posList;
402 for (
int i = 0; i < pointMemberList.size(); ++i )
405 pointNodeList = pointMemberList.at( i ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"Point" ) );
406 if ( pointNodeList.size() < 1 )
411 coordinatesList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
412 if ( !coordinatesList.isEmpty() )
414 currentPoint.clear();
415 if ( readGMLCoordinates( currentPoint, coordinatesList.at( 0 ).toElement() ) != 0 )
419 if ( currentPoint.empty() )
423 pointList.push_back( ( *currentPoint.begin() ) );
429 posList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pos" ) );
430 if ( posList.size() < 1 )
434 currentPoint.clear();
435 if ( readGMLPositions( currentPoint, posList.at( 0 ).toElement() ) != 0 )
439 if ( currentPoint.empty() )
443 pointList.push_back( ( *currentPoint.begin() ) );
447 int nPoints = pointList.size();
452 int size = 1 + 2 *
sizeof( int ) + pointList.size() * ( 2 *
sizeof( double ) + 1 +
sizeof(
int ) );
455 unsigned char *wkb =
new unsigned char[size];
458 char e = htonl( 1 ) != 1;
461 memcpy( &( wkb )[wkbPosition], &e, 1 );
463 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
464 wkbPosition +=
sizeof( int );
465 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
466 wkbPosition +=
sizeof( int );
468 for ( QgsPolylineXY::const_iterator it = pointList.constBegin(); it != pointList.constEnd(); ++it )
470 memcpy( &( wkb )[wkbPosition], &e, 1 );
472 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
473 wkbPosition +=
sizeof( int );
475 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
476 wkbPosition +=
sizeof( double );
478 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
479 wkbPosition +=
sizeof( double );
487 QgsGeometry QgsOgcUtils::geometryFromGMLMultiLineString(
const QDomElement &geometryElement )
498 QList< QgsPolylineXY > lineCoordinates;
499 QDomElement currentLineStringElement;
500 QDomNodeList currentCoordList;
501 QDomNodeList currentPosList;
503 QDomNodeList lineStringMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"lineStringMember" ) );
504 if ( !lineStringMemberList.isEmpty() )
506 for (
int i = 0; i < lineStringMemberList.size(); ++i )
508 QDomNodeList lineStringNodeList = lineStringMemberList.at( i ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LineString" ) );
509 if ( lineStringNodeList.size() < 1 )
513 currentLineStringElement = lineStringNodeList.at( 0 ).toElement();
514 currentCoordList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
515 if ( !currentCoordList.isEmpty() )
518 if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
522 lineCoordinates.push_back( currentPointList );
526 currentPosList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
527 if ( currentPosList.size() < 1 )
532 if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
536 lineCoordinates.push_back( currentPointList );
542 QDomNodeList lineStringList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LineString" ) );
543 if ( !lineStringList.isEmpty() )
545 for (
int i = 0; i < lineStringList.size(); ++i )
547 currentLineStringElement = lineStringList.at( i ).toElement();
548 currentCoordList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
549 if ( !currentCoordList.isEmpty() )
552 if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
556 lineCoordinates.push_back( currentPointList );
561 currentPosList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
562 if ( currentPosList.size() < 1 )
567 if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
571 lineCoordinates.push_back( currentPointList );
581 int nLines = lineCoordinates.size();
586 int size = ( lineCoordinates.size() + 1 ) * ( 1 + 2 *
sizeof(
int ) );
587 for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
589 size += it->size() * 2 *
sizeof( double );
593 unsigned char *wkb =
new unsigned char[size];
596 char e = htonl( 1 ) != 1;
600 memcpy( &( wkb )[wkbPosition], &e, 1 );
602 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
603 wkbPosition +=
sizeof( int );
604 memcpy( &( wkb )[wkbPosition], &nLines,
sizeof(
int ) );
605 wkbPosition +=
sizeof( int );
607 for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
609 memcpy( &( wkb )[wkbPosition], &e, 1 );
611 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
612 wkbPosition +=
sizeof( int );
613 nPoints = it->size();
614 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
615 wkbPosition +=
sizeof( int );
616 for ( QgsPolylineXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
621 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
622 wkbPosition +=
sizeof( double );
623 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
624 wkbPosition +=
sizeof( double );
633 QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon(
const QDomElement &geometryElement )
637 QDomElement currentPolygonMemberElement;
638 QDomNodeList polygonList;
639 QDomElement currentPolygonElement;
641 QDomNodeList outerBoundaryList;
642 QDomElement currentOuterBoundaryElement;
643 QDomNodeList innerBoundaryList;
644 QDomElement currentInnerBoundaryElement;
646 QDomNodeList exteriorList;
647 QDomElement currentExteriorElement;
648 QDomElement currentInteriorElement;
649 QDomNodeList interiorList;
651 QDomNodeList linearRingNodeList;
652 QDomElement currentLinearRingElement;
654 QDomNodeList currentCoordinateList;
655 QDomNodeList currentPosList;
657 QDomNodeList polygonMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"polygonMember" ) );
659 for (
int i = 0; i < polygonMemberList.size(); ++i )
661 currentPolygonList.resize( 0 );
662 currentPolygonMemberElement = polygonMemberList.at( i ).toElement();
663 polygonList = currentPolygonMemberElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"Polygon" ) );
664 if ( polygonList.size() < 1 )
668 currentPolygonElement = polygonList.at( 0 ).toElement();
671 outerBoundaryList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"outerBoundaryIs" ) );
672 if ( !outerBoundaryList.isEmpty() )
674 currentOuterBoundaryElement = outerBoundaryList.at( 0 ).toElement();
677 linearRingNodeList = currentOuterBoundaryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
678 if ( linearRingNodeList.size() < 1 )
682 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
683 currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
684 if ( currentCoordinateList.size() < 1 )
688 if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
692 currentPolygonList.push_back( ringCoordinates );
695 QDomNodeList innerBoundaryList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"innerBoundaryIs" ) );
696 for (
int j = 0; j < innerBoundaryList.size(); ++j )
699 currentInnerBoundaryElement = innerBoundaryList.at( j ).toElement();
700 linearRingNodeList = currentInnerBoundaryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
701 if ( linearRingNodeList.size() < 1 )
705 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
706 currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
707 if ( currentCoordinateList.size() < 1 )
711 if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
715 currentPolygonList.push_back( ringCoordinates );
721 exteriorList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"exterior" ) );
722 if ( exteriorList.size() < 1 )
727 currentExteriorElement = exteriorList.at( 0 ).toElement();
730 linearRingNodeList = currentExteriorElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
731 if ( linearRingNodeList.size() < 1 )
735 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
736 currentPosList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
737 if ( currentPosList.size() < 1 )
741 if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
745 currentPolygonList.push_back( ringPositions );
748 QDomNodeList interiorList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"interior" ) );
749 for (
int j = 0; j < interiorList.size(); ++j )
752 currentInteriorElement = interiorList.at( j ).toElement();
753 linearRingNodeList = currentInteriorElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
754 if ( linearRingNodeList.size() < 1 )
758 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
759 currentPosList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
760 if ( currentPosList.size() < 1 )
764 if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
768 currentPolygonList.push_back( ringPositions );
771 multiPolygonPoints.push_back( currentPolygonList );
774 int nPolygons = multiPolygonPoints.size();
778 int size = 1 + 2 *
sizeof( int );
780 for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
782 size += 1 + 2 *
sizeof( int );
783 for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
785 size +=
sizeof( int ) + 2 * iter->size() *
sizeof( double );
790 unsigned char *wkb =
new unsigned char[size];
792 char e = htonl( 1 ) != 1;
799 memcpy( &( wkb )[wkbPosition], &e, 1 );
801 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
802 wkbPosition +=
sizeof( int );
803 memcpy( &( wkb )[wkbPosition], &nPolygons,
sizeof(
int ) );
804 wkbPosition +=
sizeof( int );
808 for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
810 memcpy( &( wkb )[wkbPosition], &e, 1 );
812 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
813 wkbPosition +=
sizeof( int );
815 memcpy( &( wkb )[wkbPosition], &nRings,
sizeof(
int ) );
816 wkbPosition +=
sizeof( int );
817 for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
819 nPointsInRing = iter->size();
820 memcpy( &( wkb )[wkbPosition], &nPointsInRing,
sizeof(
int ) );
821 wkbPosition +=
sizeof( int );
822 for ( QgsPolylineXY::const_iterator iterator = iter->begin(); iterator != iter->end(); ++iterator )
826 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
827 wkbPosition +=
sizeof( double );
828 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
829 wkbPosition +=
sizeof( double );
839 bool QgsOgcUtils::readGMLCoordinates(
QgsPolylineXY &coords,
const QDomElement &elem )
841 QString coordSeparator = QStringLiteral(
"," );
842 QString tupelSeparator = QStringLiteral(
" " );
847 if ( elem.hasAttribute( QStringLiteral(
"cs" ) ) )
849 coordSeparator = elem.attribute( QStringLiteral(
"cs" ) );
851 if ( elem.hasAttribute( QStringLiteral(
"ts" ) ) )
853 tupelSeparator = elem.attribute( QStringLiteral(
"ts" ) );
856 QStringList tupels = elem.text().split( tupelSeparator, QString::SkipEmptyParts );
857 QStringList tupel_coords;
859 bool conversionSuccess;
861 QStringList::const_iterator it;
862 for ( it = tupels.constBegin(); it != tupels.constEnd(); ++it )
864 tupel_coords = ( *it ).split( coordSeparator, QString::SkipEmptyParts );
865 if ( tupel_coords.size() < 2 )
869 x = tupel_coords.at( 0 ).toDouble( &conversionSuccess );
870 if ( !conversionSuccess )
874 y = tupel_coords.at( 1 ).toDouble( &conversionSuccess );
875 if ( !conversionSuccess )
888 QDomElement boxElem = boxNode.toElement();
889 if ( boxElem.tagName() != QLatin1String(
"Box" ) )
892 QDomElement bElem = boxElem.firstChild().toElement();
893 QString coordSeparator = QStringLiteral(
"," );
894 QString tupelSeparator = QStringLiteral(
" " );
895 if ( bElem.hasAttribute( QStringLiteral(
"cs" ) ) )
897 coordSeparator = bElem.attribute( QStringLiteral(
"cs" ) );
899 if ( bElem.hasAttribute( QStringLiteral(
"ts" ) ) )
901 tupelSeparator = bElem.attribute( QStringLiteral(
"ts" ) );
904 QString bString = bElem.text();
905 bool ok1, ok2, ok3, ok4;
906 double xmin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 0, 0 ).toDouble( &ok1 );
907 double ymin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 1, 1 ).toDouble( &ok2 );
908 double xmax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 0, 0 ).toDouble( &ok3 );
909 double ymax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 1, 1 ).toDouble( &ok4 );
911 if ( ok1 && ok2 && ok3 && ok4 )
920 bool QgsOgcUtils::readGMLPositions(
QgsPolylineXY &coords,
const QDomElement &elem )
924 QStringList pos = elem.text().split(
' ', QString::SkipEmptyParts );
926 bool conversionSuccess;
927 int posSize = pos.size();
929 int srsDimension = 2;
930 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
932 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
933 if ( !conversionSuccess )
938 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
940 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
941 if ( !conversionSuccess )
947 for (
int i = 0; i < posSize / srsDimension; i++ )
949 x = pos.at( i * srsDimension ).toDouble( &conversionSuccess );
950 if ( !conversionSuccess )
954 y = pos.at( i * srsDimension + 1 ).toDouble( &conversionSuccess );
955 if ( !conversionSuccess )
969 QDomElement envelopeElem = envelopeNode.toElement();
970 if ( envelopeElem.tagName() != QLatin1String(
"Envelope" ) )
973 QDomNodeList lowerCornerList = envelopeElem.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"lowerCorner" ) );
974 if ( lowerCornerList.size() < 1 )
977 QDomNodeList upperCornerList = envelopeElem.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"upperCorner" ) );
978 if ( upperCornerList.size() < 1 )
981 bool conversionSuccess;
982 int srsDimension = 2;
984 QDomElement elem = lowerCornerList.at( 0 ).toElement();
985 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
987 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
988 if ( !conversionSuccess )
993 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
995 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
996 if ( !conversionSuccess )
1001 QString bString = elem.text();
1003 double xmin = bString.section(
' ', 0, 0 ).toDouble( &conversionSuccess );
1004 if ( !conversionSuccess )
1006 double ymin = bString.section(
' ', 1, 1 ).toDouble( &conversionSuccess );
1007 if ( !conversionSuccess )
1010 elem = upperCornerList.at( 0 ).toElement();
1011 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
1013 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
1014 if ( !conversionSuccess )
1019 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1021 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1022 if ( !conversionSuccess )
1028 Q_UNUSED( srsDimension );
1030 bString = elem.text();
1031 double xmax = bString.section(
' ', 0, 0 ).toDouble( &conversionSuccess );
1032 if ( !conversionSuccess )
1034 double ymax = bString.section(
' ', 1, 1 ).toDouble( &conversionSuccess );
1035 if ( !conversionSuccess )
1046 return rectangleToGMLBox( box, doc, QString(),
false, precision );
1050 const QString &srsName,
1051 bool invertAxisOrientation,
1056 return QDomElement();
1059 QDomElement boxElem = doc.createElement( QStringLiteral(
"gml:Box" ) );
1060 if ( !srsName.isEmpty() )
1062 boxElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1064 QDomElement coordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1065 coordElem.setAttribute( QStringLiteral(
"cs" ), QStringLiteral(
"," ) );
1066 coordElem.setAttribute( QStringLiteral(
"ts" ), QStringLiteral(
" " ) );
1068 QString coordString;
1077 QDomText coordText = doc.createTextNode( coordString );
1078 coordElem.appendChild( coordText );
1079 boxElem.appendChild( coordElem );
1086 return rectangleToGMLEnvelope( env, doc, QString(),
false, precision );
1090 const QString &srsName,
1091 bool invertAxisOrientation,
1096 return QDomElement();
1099 QDomElement envElem = doc.createElement( QStringLiteral(
"gml:Envelope" ) );
1100 if ( !srsName.isEmpty() )
1102 envElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1106 QDomElement lowerCornerElem = doc.createElement( QStringLiteral(
"gml:lowerCorner" ) );
1110 QDomText lowerCornerText = doc.createTextNode( posList );
1111 lowerCornerElem.appendChild( lowerCornerText );
1112 envElem.appendChild( lowerCornerElem );
1114 QDomElement upperCornerElem = doc.createElement( QStringLiteral(
"gml:upperCorner" ) );
1118 QDomText upperCornerText = doc.createTextNode( posList );
1119 upperCornerElem.appendChild( upperCornerText );
1120 envElem.appendChild( upperCornerElem );
1127 return geometryToGML( geometry, doc, ( format == QLatin1String(
"GML2" ) ) ? GML_2_1_2 : GML_3_2_1, QString(),
false, QString(), precision );
1132 const QString &srsName,
1133 bool invertAxisOrientation,
1134 const QString &gmlIdBase,
1138 return QDomElement();
1141 QString cs = QStringLiteral(
"," );
1143 QString ts = QStringLiteral(
" " );
1145 QDomElement baseCoordElem;
1147 bool hasZValue =
false;
1149 QByteArray wkb( geometry.
asWkb() );
1153 wkbPtr.readHeader();
1159 return QDomElement();
1162 if ( gmlVersion != GML_2_1_2 )
1170 baseCoordElem = doc.createElement( QStringLiteral(
"gml:pos" ) );
1173 baseCoordElem = doc.createElement( QStringLiteral(
"gml:posList" ) );
1176 baseCoordElem.setAttribute( QStringLiteral(
"srsDimension" ), QStringLiteral(
"2" ) );
1181 baseCoordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1182 baseCoordElem.setAttribute( QStringLiteral(
"cs" ), cs );
1183 baseCoordElem.setAttribute( QStringLiteral(
"ts" ), ts );
1193 QDomElement pointElem = doc.createElement( QStringLiteral(
"gml:Point" ) );
1194 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1195 pointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1196 if ( !srsName.isEmpty() )
1197 pointElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1198 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1202 if ( invertAxisOrientation )
1208 coordElem.appendChild( coordText );
1209 pointElem.appendChild( coordElem );
1218 QDomElement multiPointElem = doc.createElement( QStringLiteral(
"gml:MultiPoint" ) );
1219 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1220 multiPointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1221 if ( !srsName.isEmpty() )
1222 multiPointElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1227 for (
int idx = 0; idx < nPoints; ++idx )
1229 QDomElement pointMemberElem = doc.createElement( QStringLiteral(
"gml:pointMember" ) );
1230 QDomElement pointElem = doc.createElement( QStringLiteral(
"gml:Point" ) );
1231 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1232 pointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( idx + 1 ) );
1233 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1235 wkbPtr.readHeader();
1238 if ( invertAxisOrientation )
1244 coordElem.appendChild( coordText );
1245 pointElem.appendChild( coordElem );
1249 wkbPtr +=
sizeof( double );
1251 pointMemberElem.appendChild( pointElem );
1252 multiPointElem.appendChild( pointMemberElem );
1254 return multiPointElem;
1262 QDomElement lineStringElem = doc.createElement( QStringLiteral(
"gml:LineString" ) );
1263 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1264 lineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1265 if ( !srsName.isEmpty() )
1266 lineStringElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1272 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1273 QString coordString;
1274 for (
int idx = 0; idx < nPoints; ++idx )
1282 if ( invertAxisOrientation )
1290 wkbPtr +=
sizeof( double );
1293 QDomText coordText = doc.createTextNode( coordString );
1294 coordElem.appendChild( coordText );
1295 lineStringElem.appendChild( coordElem );
1296 return lineStringElem;
1304 QDomElement multiLineStringElem = doc.createElement( QStringLiteral(
"gml:MultiLineString" ) );
1305 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1306 multiLineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1307 if ( !srsName.isEmpty() )
1308 multiLineStringElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1313 for (
int jdx = 0; jdx < nLines; jdx++ )
1315 QDomElement lineStringMemberElem = doc.createElement( QStringLiteral(
"gml:lineStringMember" ) );
1316 QDomElement lineStringElem = doc.createElement( QStringLiteral(
"gml:LineString" ) );
1317 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1318 lineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( jdx + 1 ) );
1320 wkbPtr.readHeader();
1325 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1326 QString coordString;
1327 for (
int idx = 0; idx < nPoints; idx++ )
1335 if ( invertAxisOrientation )
1344 wkbPtr +=
sizeof( double );
1347 QDomText coordText = doc.createTextNode( coordString );
1348 coordElem.appendChild( coordText );
1349 lineStringElem.appendChild( coordElem );
1350 lineStringMemberElem.appendChild( lineStringElem );
1351 multiLineStringElem.appendChild( lineStringMemberElem );
1353 return multiLineStringElem;
1361 QDomElement polygonElem = doc.createElement( QStringLiteral(
"gml:Polygon" ) );
1362 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1363 polygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1364 if ( !srsName.isEmpty() )
1365 polygonElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1371 if ( numRings == 0 )
1372 return QDomElement();
1374 int *ringNumPoints =
new int[numRings];
1376 for (
int idx = 0; idx < numRings; idx++ )
1378 QString boundaryName = ( gmlVersion == GML_2_1_2 ) ?
"gml:outerBoundaryIs" :
"gml:exterior";
1381 boundaryName = ( gmlVersion == GML_2_1_2 ) ?
"gml:innerBoundaryIs" :
"gml:interior";
1383 QDomElement boundaryElem = doc.createElement( boundaryName );
1384 QDomElement ringElem = doc.createElement( QStringLiteral(
"gml:LinearRing" ) );
1388 ringNumPoints[idx] = nPoints;
1390 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1391 QString coordString;
1392 for (
int jdx = 0; jdx < nPoints; jdx++ )
1400 if ( invertAxisOrientation )
1408 wkbPtr +=
sizeof( double );
1411 QDomText coordText = doc.createTextNode( coordString );
1412 coordElem.appendChild( coordText );
1413 ringElem.appendChild( coordElem );
1414 boundaryElem.appendChild( ringElem );
1415 polygonElem.appendChild( boundaryElem );
1417 delete [] ringNumPoints;
1426 QDomElement multiPolygonElem = doc.createElement( QStringLiteral(
"gml:MultiPolygon" ) );
1427 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1428 multiPolygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1429 if ( !srsName.isEmpty() )
1430 multiPolygonElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1433 wkbPtr >> numPolygons;
1435 for (
int kdx = 0; kdx < numPolygons; kdx++ )
1437 QDomElement polygonMemberElem = doc.createElement( QStringLiteral(
"gml:polygonMember" ) );
1438 QDomElement polygonElem = doc.createElement( QStringLiteral(
"gml:Polygon" ) );
1439 if ( gmlVersion == GML_3_2_1 && !gmlIdBase.isEmpty() )
1440 polygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( kdx + 1 ) );
1442 wkbPtr.readHeader();
1447 for (
int idx = 0; idx < numRings; idx++ )
1449 QString boundaryName = ( gmlVersion == GML_2_1_2 ) ?
"gml:outerBoundaryIs" :
"gml:exterior";
1452 boundaryName = ( gmlVersion == GML_2_1_2 ) ?
"gml:innerBoundaryIs" :
"gml:interior";
1454 QDomElement boundaryElem = doc.createElement( boundaryName );
1455 QDomElement ringElem = doc.createElement( QStringLiteral(
"gml:LinearRing" ) );
1460 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1461 QString coordString;
1462 for (
int jdx = 0; jdx < nPoints; jdx++ )
1470 if ( invertAxisOrientation )
1479 wkbPtr +=
sizeof( double );
1482 QDomText coordText = doc.createTextNode( coordString );
1483 coordElem.appendChild( coordText );
1484 ringElem.appendChild( coordElem );
1485 boundaryElem.appendChild( ringElem );
1486 polygonElem.appendChild( boundaryElem );
1487 polygonMemberElem.appendChild( polygonElem );
1488 multiPolygonElem.appendChild( polygonMemberElem );
1491 return multiPolygonElem;
1494 return QDomElement();
1500 return QDomElement();
1506 return geometryToGML( geometry, doc, QStringLiteral(
"GML2" ), precision );
1509 QDomElement QgsOgcUtils::createGMLCoordinates(
const QgsPolylineXY &points, QDomDocument &doc )
1511 QDomElement coordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1512 coordElem.setAttribute( QStringLiteral(
"cs" ), QStringLiteral(
"," ) );
1513 coordElem.setAttribute( QStringLiteral(
"ts" ), QStringLiteral(
" " ) );
1515 QString coordString;
1516 QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
1517 for ( ; pointIt != points.constEnd(); ++pointIt )
1519 if ( pointIt != points.constBegin() )
1528 QDomText coordText = doc.createTextNode( coordString );
1529 coordElem.appendChild( coordText );
1533 QDomElement QgsOgcUtils::createGMLPositions(
const QgsPolylineXY &points, QDomDocument &doc )
1535 QDomElement posElem = doc.createElement( QStringLiteral(
"gml:pos" ) );
1536 if ( points.size() > 1 )
1537 posElem = doc.createElement( QStringLiteral(
"gml:posList" ) );
1538 posElem.setAttribute( QStringLiteral(
"srsDimension" ), QStringLiteral(
"2" ) );
1540 QString coordString;
1541 QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
1542 for ( ; pointIt != points.constEnd(); ++pointIt )
1544 if ( pointIt != points.constBegin() )
1553 QDomText coordText = doc.createTextNode( coordString );
1554 posElem.appendChild( coordText );
1564 if ( fillElement.isNull() || !fillElement.hasChildNodes() )
1572 QDomElement cssElem = fillElement.firstChildElement( QStringLiteral(
"CssParameter" ) );
1573 while ( !cssElem.isNull() )
1575 cssName = cssElem.attribute( QStringLiteral(
"name" ), QStringLiteral(
"not_found" ) );
1576 if ( cssName != QLatin1String(
"not_found" ) )
1578 elemText = cssElem.text();
1579 if ( cssName == QLatin1String(
"fill" ) )
1581 color.setNamedColor( elemText );
1583 else if ( cssName == QLatin1String(
"fill-opacity" ) )
1586 double opacity = elemText.toDouble( &ok );
1589 color.setAlphaF( opacity );
1594 cssElem = cssElem.nextSiblingElement( QStringLiteral(
"CssParameter" ) );
1603 if ( element.isNull() || !element.hasChildNodes() )
1606 QgsExpression *expr =
new QgsExpression();
1610 if ( element.firstChild().nodeType() == QDomNode::TextNode )
1612 expr->setExpression( element.firstChild().nodeValue() );
1618 QDomElement childElem = element.firstChildElement();
1619 while ( !childElem.isNull() )
1622 QgsExpressionNode *node = nodeFromOgcFilter( childElem, errorMsg );
1626 expr->d->mParserErrorString = errorMsg;
1631 if ( !expr->d->mRootNode )
1633 expr->d->mRootNode = node;
1637 expr->d->mRootNode =
new QgsExpressionNodeBinaryOperator( QgsExpressionNodeBinaryOperator::boConcat, expr->d->mRootNode, node );
1640 childElem = childElem.nextSiblingElement();
1644 expr->d->mExp = expr->dump();
1650 static const QMap<QString, int> BINARY_OPERATORS_TAG_NAMES_MAP
1653 { QStringLiteral(
"Or" ), QgsExpressionNodeBinaryOperator::boOr },
1654 { QStringLiteral(
"And" ), QgsExpressionNodeBinaryOperator::boAnd },
1656 { QStringLiteral(
"PropertyIsEqualTo" ), QgsExpressionNodeBinaryOperator::boEQ },
1657 { QStringLiteral(
"PropertyIsNotEqualTo" ), QgsExpressionNodeBinaryOperator::boNE },
1658 { QStringLiteral(
"PropertyIsLessThanOrEqualTo" ), QgsExpressionNodeBinaryOperator::boLE },
1659 { QStringLiteral(
"PropertyIsGreaterThanOrEqualTo" ), QgsExpressionNodeBinaryOperator::boGE },
1660 { QStringLiteral(
"PropertyIsLessThan" ), QgsExpressionNodeBinaryOperator::boLT },
1661 { QStringLiteral(
"PropertyIsGreaterThan" ), QgsExpressionNodeBinaryOperator::boGT },
1662 { QStringLiteral(
"PropertyIsLike" ), QgsExpressionNodeBinaryOperator::boLike },
1664 { QStringLiteral(
"Add" ), QgsExpressionNodeBinaryOperator::boPlus },
1665 { QStringLiteral(
"Sub" ), QgsExpressionNodeBinaryOperator::boMinus },
1666 { QStringLiteral(
"Mul" ), QgsExpressionNodeBinaryOperator::boMul },
1667 { QStringLiteral(
"Div" ), QgsExpressionNodeBinaryOperator::boDiv },
1670 static int binaryOperatorFromTagName(
const QString &tagName )
1673 return BINARY_OPERATORS_TAG_NAMES_MAP.value( tagName, -1 );
1676 static QString binaryOperatorToTagName( QgsExpressionNodeBinaryOperator::BinaryOperator op )
1678 if ( op == QgsExpressionNodeBinaryOperator::boILike )
1680 return QStringLiteral(
"PropertyIsLike" );
1682 return BINARY_OPERATORS_TAG_NAMES_MAP.key( op, QString() );
1685 static bool isBinaryOperator(
const QString &tagName )
1687 return binaryOperatorFromTagName( tagName ) >= 0;
1691 static bool isSpatialOperator(
const QString &tagName )
1693 static QStringList spatialOps;
1694 if ( spatialOps.isEmpty() )
1696 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
1697 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
1700 return spatialOps.contains( tagName );
1705 QgsExpressionNode *QgsOgcUtils::nodeFromOgcFilter( QDomElement &element, QString &
errorMessage )
1707 if ( element.isNull() )
1711 if ( isBinaryOperator( element.tagName() ) )
1713 return nodeBinaryOperatorFromOgcFilter( element, errorMessage );
1717 if ( isSpatialOperator( element.tagName() ) )
1719 return nodeSpatialOperatorFromOgcFilter( element, errorMessage );
1724 if ( element.tagName() == QLatin1String(
"Not" ) )
1726 return nodeNotFromOgcFilter( element, errorMessage );
1728 else if ( element.tagName() == QLatin1String(
"PropertyIsNull" ) )
1730 return nodePropertyIsNullFromOgcFilter( element, errorMessage );
1732 else if ( element.tagName() == QLatin1String(
"Literal" ) )
1734 return nodeLiteralFromOgcFilter( element, errorMessage );
1736 else if ( element.tagName() == QLatin1String(
"Function" ) )
1738 return nodeFunctionFromOgcFilter( element, errorMessage );
1740 else if ( element.tagName() == QLatin1String(
"PropertyName" ) )
1742 return nodeColumnRefFromOgcFilter( element, errorMessage );
1744 else if ( element.tagName() == QLatin1String(
"PropertyIsBetween" ) )
1746 return nodeIsBetweenFromOgcFilter( element, errorMessage );
1749 errorMessage += QObject::tr(
"unable to convert '%1' element to a valid expression: it is not supported yet or it has invalid arguments" ).arg( element.tagName() );
1755 QgsExpressionNodeBinaryOperator *QgsOgcUtils::nodeBinaryOperatorFromOgcFilter( QDomElement &element, QString &
errorMessage )
1757 if ( element.isNull() )
1760 int op = binaryOperatorFromTagName( element.tagName() );
1763 if ( errorMessage.isEmpty() )
1764 errorMessage = QObject::tr(
"'%1' binary operator not supported." ).arg( element.tagName() );
1768 if ( op == QgsExpressionNodeBinaryOperator::boLike && element.hasAttribute( QStringLiteral(
"matchCase" ) ) && element.attribute( QStringLiteral(
"matchCase" ) ) == QLatin1String(
"false" ) )
1770 op = QgsExpressionNodeBinaryOperator::boILike;
1773 QDomElement operandElem = element.firstChildElement();
1774 QgsExpressionNode *expr = nodeFromOgcFilter( operandElem, errorMessage ), *leftOp = expr;
1777 if ( errorMessage.isEmpty() )
1778 errorMessage = QObject::tr(
"invalid left operand for '%1' binary operator" ).arg( element.tagName() );
1782 for ( operandElem = operandElem.nextSiblingElement(); !operandElem.isNull(); operandElem = operandElem.nextSiblingElement() )
1784 QgsExpressionNode *opRight = nodeFromOgcFilter( operandElem, errorMessage );
1787 if ( errorMessage.isEmpty() )
1788 errorMessage = QObject::tr(
"invalid right operand for '%1' binary operator" ).arg( element.tagName() );
1793 if ( op == QgsExpressionNodeBinaryOperator::boLike || op == QgsExpressionNodeBinaryOperator::boILike )
1796 if ( element.hasAttribute( QStringLiteral(
"wildCard" ) ) )
1798 wildCard = element.attribute( QStringLiteral(
"wildCard" ) );
1801 if ( element.hasAttribute( QStringLiteral(
"singleChar" ) ) )
1803 singleChar = element.attribute( QStringLiteral(
"singleChar" ) );
1805 QString escape = QStringLiteral(
"\\" );
1806 if ( element.hasAttribute( QStringLiteral(
"escape" ) ) )
1808 escape = element.attribute( QStringLiteral(
"escape" ) );
1811 QString oprValue =
static_cast<const QgsExpressionNodeLiteral *
>( opRight )->value().toString();
1812 if ( !wildCard.isEmpty() && wildCard != QLatin1String(
"%" ) )
1814 oprValue.replace(
'%', QLatin1String(
"\\%" ) );
1815 if ( oprValue.startsWith( wildCard ) )
1817 oprValue.replace( 0, 1, QStringLiteral(
"%" ) );
1819 QRegExp rx(
"[^" + QRegExp::escape( escape ) +
"](" + QRegExp::escape( wildCard ) +
")" );
1821 while ( ( pos = rx.indexIn( oprValue, pos ) ) != -1 )
1823 oprValue.replace( pos + 1, 1, QStringLiteral(
"%" ) );
1826 oprValue.replace( escape + wildCard, wildCard );
1828 if ( !singleChar.isEmpty() && singleChar != QLatin1String(
"_" ) )
1830 oprValue.replace(
'_', QLatin1String(
"\\_" ) );
1831 if ( oprValue.startsWith( singleChar ) )
1833 oprValue.replace( 0, 1, QStringLiteral(
"_" ) );
1835 QRegExp rx(
"[^" + QRegExp::escape( escape ) +
"](" + QRegExp::escape( singleChar ) +
")" );
1837 while ( ( pos = rx.indexIn( oprValue, pos ) ) != -1 )
1839 oprValue.replace( pos + 1, 1, QStringLiteral(
"_" ) );
1842 oprValue.replace( escape + singleChar, singleChar );
1844 if ( !escape.isEmpty() && escape != QLatin1String(
"\\" ) )
1846 oprValue.replace( escape + escape, escape );
1848 opRight =
new QgsExpressionNodeLiteral( oprValue );
1851 expr =
new QgsExpressionNodeBinaryOperator( static_cast< QgsExpressionNodeBinaryOperator::BinaryOperator >( op ), expr, opRight );
1854 if ( expr == leftOp )
1856 if ( errorMessage.isEmpty() )
1857 errorMessage = QObject::tr(
"only one operand for '%1' binary operator" ).arg( element.tagName() );
1862 QgsExpressionNodeBinaryOperator *ret =
dynamic_cast< QgsExpressionNodeBinaryOperator *
>( expr );
1870 QgsExpressionNodeFunction *QgsOgcUtils::nodeSpatialOperatorFromOgcFilter( QDomElement &element, QString &
errorMessage )
1873 int opIdx = QgsExpression::functionIndex( element.tagName().toLower() );
1875 QgsExpressionNode::NodeList *gml2Args =
new QgsExpressionNode::NodeList();
1876 QDomElement childElem = element.firstChildElement();
1878 while ( !childElem.isNull() && gml2Str.isEmpty() )
1880 if ( childElem.tagName() != QLatin1String(
"PropertyName" ) )
1882 QTextStream gml2Stream( &gml2Str );
1883 childElem.save( gml2Stream, 0 );
1885 childElem = childElem.nextSiblingElement();
1887 if ( !gml2Str.isEmpty() )
1889 gml2Args->append(
new QgsExpressionNodeLiteral( QVariant( gml2Str.remove(
'\n' ) ) ) );
1893 errorMessage = QObject::tr(
"No OGC Geometry found" );
1898 QgsExpressionNode::NodeList *opArgs =
new QgsExpressionNode::NodeList();
1899 opArgs->append(
new QgsExpressionNodeFunction( QgsExpression::functionIndex( QStringLiteral(
"$geometry" ) ),
new QgsExpressionNode::NodeList() ) );
1900 opArgs->append(
new QgsExpressionNodeFunction( QgsExpression::functionIndex( QStringLiteral(
"geomFromGML" ) ), gml2Args ) );
1902 return new QgsExpressionNodeFunction( opIdx, opArgs );
1906 QgsExpressionNodeUnaryOperator *QgsOgcUtils::nodeNotFromOgcFilter( QDomElement &element, QString &
errorMessage )
1908 if ( element.tagName() != QLatin1String(
"Not" ) )
1911 QDomElement operandElem = element.firstChildElement();
1912 QgsExpressionNode *operand = nodeFromOgcFilter( operandElem, errorMessage );
1915 if ( errorMessage.isEmpty() )
1916 errorMessage = QObject::tr(
"invalid operand for '%1' unary operator" ).arg( element.tagName() );
1920 return new QgsExpressionNodeUnaryOperator( QgsExpressionNodeUnaryOperator::uoNot, operand );
1924 QgsExpressionNodeFunction *QgsOgcUtils::nodeFunctionFromOgcFilter( QDomElement &element, QString &
errorMessage )
1926 if ( element.isNull() || element.tagName() != QLatin1String(
"Function" ) )
1928 errorMessage = QObject::tr(
"ogc:Function expected, got %1" ).arg( element.tagName() );
1932 for (
int i = 0; i < QgsExpression::Functions().size(); i++ )
1934 QgsExpressionFunction *funcDef = QgsExpression::Functions()[i];
1936 if ( element.attribute( QStringLiteral(
"name" ) ) != funcDef->name() )
1939 QgsExpressionNode::NodeList *args =
new QgsExpressionNode::NodeList();
1941 QDomElement operandElem = element.firstChildElement();
1942 while ( !operandElem.isNull() )
1944 QgsExpressionNode *op = nodeFromOgcFilter( operandElem, errorMessage );
1952 operandElem = operandElem.nextSiblingElement();
1955 return new QgsExpressionNodeFunction( i, args );
1963 QgsExpressionNode *QgsOgcUtils::nodeLiteralFromOgcFilter( QDomElement &element, QString &
errorMessage )
1965 if ( element.isNull() || element.tagName() != QLatin1String(
"Literal" ) )
1967 errorMessage = QObject::tr(
"ogc:Literal expected, got %1" ).arg( element.tagName() );
1971 QgsExpressionNode *root =
nullptr;
1974 QDomNode childNode = element.firstChild();
1975 while ( !childNode.isNull() )
1977 QgsExpressionNode *operand =
nullptr;
1979 if ( childNode.nodeType() == QDomNode::ElementNode )
1982 QDomElement operandElem = childNode.toElement();
1983 operand = nodeFromOgcFilter( operandElem, errorMessage );
1988 errorMessage = QObject::tr(
"'%1' is an invalid or not supported content for ogc:Literal" ).arg( operandElem.tagName() );
1995 QVariant value = childNode.nodeValue();
2000 double d = value.toDouble( &ok );
2004 operand =
new QgsExpressionNodeLiteral( value );
2016 root =
new QgsExpressionNodeBinaryOperator( QgsExpressionNodeBinaryOperator::boConcat, root, operand );
2019 childNode = childNode.nextSibling();
2029 QgsExpressionNodeColumnRef *QgsOgcUtils::nodeColumnRefFromOgcFilter( QDomElement &element, QString &
errorMessage )
2031 if ( element.isNull() || element.tagName() != QLatin1String(
"PropertyName" ) )
2033 errorMessage = QObject::tr(
"ogc:PropertyName expected, got %1" ).arg( element.tagName() );
2037 return new QgsExpressionNodeColumnRef( element.firstChild().nodeValue() );
2041 QgsExpressionNode *QgsOgcUtils::nodeIsBetweenFromOgcFilter( QDomElement &element, QString &
errorMessage )
2044 QgsExpressionNode *operand =
nullptr, *lowerBound =
nullptr;
2045 QgsExpressionNode *operand2 =
nullptr, *upperBound =
nullptr;
2047 QDomElement operandElem = element.firstChildElement();
2048 while ( !operandElem.isNull() )
2050 if ( operandElem.tagName() == QLatin1String(
"LowerBoundary" ) )
2052 QDomElement lowerBoundElem = operandElem.firstChildElement();
2053 lowerBound = nodeFromOgcFilter( lowerBoundElem, errorMessage );
2055 else if ( operandElem.tagName() == QLatin1String(
"UpperBoundary" ) )
2057 QDomElement upperBoundElem = operandElem.firstChildElement();
2058 upperBound = nodeFromOgcFilter( upperBoundElem, errorMessage );
2065 operand = nodeFromOgcFilter( operandElem, errorMessage );
2066 operand2 = nodeFromOgcFilter( operandElem, errorMessage );
2069 if ( operand && lowerBound && operand2 && upperBound )
2072 operandElem = operandElem.nextSiblingElement();
2075 if ( !operand || !lowerBound || !operand2 || !upperBound )
2081 errorMessage = QObject::tr(
"missing some required sub-elements in ogc:PropertyIsBetween" );
2085 QgsExpressionNode *geOperator =
new QgsExpressionNodeBinaryOperator( QgsExpressionNodeBinaryOperator::boGE, operand, lowerBound );
2086 QgsExpressionNode *leOperator =
new QgsExpressionNodeBinaryOperator( QgsExpressionNodeBinaryOperator::boLE, operand2, upperBound );
2087 return new QgsExpressionNodeBinaryOperator( QgsExpressionNodeBinaryOperator::boAnd, geOperator, leOperator );
2091 QgsExpressionNodeBinaryOperator *QgsOgcUtils::nodePropertyIsNullFromOgcFilter( QDomElement &element, QString &
errorMessage )
2094 if ( element.tagName() != QLatin1String(
"PropertyIsNull" ) )
2099 QDomElement operandElem = element.firstChildElement();
2100 QgsExpressionNode *opLeft = nodeFromOgcFilter( operandElem, errorMessage );
2104 QgsExpressionNode *opRight =
new QgsExpressionNodeLiteral( QVariant() );
2105 return new QgsExpressionNodeBinaryOperator( QgsExpressionNodeBinaryOperator::boIs, opLeft, opRight );
2114 return expressionToOgcFilter( exp, doc, GML_2_1_2, FILTER_OGC_1_0,
2115 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage );
2120 return expressionToOgcExpression( exp, doc, GML_2_1_2, FILTER_OGC_1_0,
2121 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage );
2128 const QString &geometryName,
2129 const QString &srsName,
2130 bool honourAxisOrientation,
2131 bool invertAxisOrientation,
2134 if ( !exp.rootNode() )
2135 return QDomElement();
2137 QgsOgcUtilsExprToFilter utils( doc, gmlVersion, filterVersion, geometryName, srsName, honourAxisOrientation, invertAxisOrientation );
2141 if ( exprRootElem.isNull() )
2142 return QDomElement();
2144 QDomElement filterElem =
2145 ( filterVersion == FILTER_FES_2_0 ) ?
2146 doc.createElementNS( FES_NAMESPACE, QStringLiteral(
"fes:Filter" ) ) :
2147 doc.createElementNS( OGC_NAMESPACE, QStringLiteral(
"ogc:Filter" ) );
2150 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:gml" ) );
2151 if ( gmlVersion == GML_3_2_1 )
2152 attr.setValue( GML32_NAMESPACE );
2155 filterElem.setAttributeNode( attr );
2157 filterElem.appendChild( exprRootElem );
2165 const QString &geometryName,
2166 const QString &srsName,
2167 bool honourAxisOrientation,
2168 bool invertAxisOrientation,
2171 const QgsExpressionNode *node = exp.rootNode();
2173 return QDomElement();
2175 switch ( node->nodeType() )
2177 case QgsExpressionNode::ntFunction:
2178 case QgsExpressionNode::ntLiteral:
2179 case QgsExpressionNode::ntColumnRef:
2181 QgsOgcUtilsExprToFilter utils( doc, gmlVersion, filterVersion, geometryName, srsName, honourAxisOrientation, invertAxisOrientation );
2187 if ( !exprRootElem.isNull() )
2189 return exprRootElem;
2194 *errorMessage = QObject::tr(
"Node type not supported in expression translation: %1" ).arg( node->nodeType() );
2197 return QDomElement();
2204 const QList<LayerProperties> &layerProperties,
2205 bool honourAxisOrientation,
2206 bool invertAxisOrientation,
2207 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename,
2211 return QDomElement();
2214 layerProperties, honourAxisOrientation, invertAxisOrientation,
2215 mapUnprefixedTypenameToPrefixedTypename );
2219 if ( exprRootElem.isNull() )
2220 return QDomElement();
2222 QDomElement filterElem =
2223 ( filterVersion == FILTER_FES_2_0 ) ?
2224 doc.createElementNS( FES_NAMESPACE, QStringLiteral(
"fes:Filter" ) ) :
2225 doc.createElementNS( OGC_NAMESPACE, QStringLiteral(
"ogc:Filter" ) );
2228 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:gml" ) );
2229 if ( gmlVersion == GML_3_2_1 )
2230 attr.setValue( GML32_NAMESPACE );
2233 filterElem.setAttributeNode( attr );
2235 filterElem.appendChild( exprRootElem );
2244 switch ( node->nodeType() )
2246 case QgsExpressionNode::ntUnaryOperator:
2247 return expressionUnaryOperatorToOgcFilter( static_cast<const QgsExpressionNodeUnaryOperator *>( node ) );
2248 case QgsExpressionNode::ntBinaryOperator:
2249 return expressionBinaryOperatorToOgcFilter( static_cast<const QgsExpressionNodeBinaryOperator *>( node ) );
2250 case QgsExpressionNode::ntInOperator:
2251 return expressionInOperatorToOgcFilter( static_cast<const QgsExpressionNodeInOperator *>( node ) );
2252 case QgsExpressionNode::ntFunction:
2253 return expressionFunctionToOgcFilter( static_cast<const QgsExpressionNodeFunction *>( node ) );
2254 case QgsExpressionNode::ntLiteral:
2255 return expressionLiteralToOgcFilter( static_cast<const QgsExpressionNodeLiteral *>( node ) );
2256 case QgsExpressionNode::ntColumnRef:
2257 return expressionColumnRefToOgcFilter( static_cast<const QgsExpressionNodeColumnRef *>( node ) );
2260 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->nodeType() );
2261 return QDomElement();
2266 QDomElement QgsOgcUtilsExprToFilter::expressionUnaryOperatorToOgcFilter(
const QgsExpressionNodeUnaryOperator *node )
2270 if ( !mErrorMessage.isEmpty() )
2271 return QDomElement();
2274 switch ( node->op() )
2276 case QgsExpressionNodeUnaryOperator::uoMinus:
2277 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2278 if ( node->operand()->nodeType() == QgsExpressionNode::ntLiteral )
2282 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
2283 mDoc.removeChild( operandElem );
2287 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
2288 return QDomElement();
2291 case QgsExpressionNodeUnaryOperator::uoNot:
2292 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
2293 uoElem.appendChild( operandElem );
2297 mErrorMessage = QObject::tr(
"Unary operator '%1' not implemented yet" ).arg( node->text() );
2298 return QDomElement();
2305 QDomElement QgsOgcUtilsExprToFilter::expressionBinaryOperatorToOgcFilter(
const QgsExpressionNodeBinaryOperator *node )
2308 if ( !mErrorMessage.isEmpty() )
2309 return QDomElement();
2311 QgsExpressionNodeBinaryOperator::BinaryOperator op = node->op();
2314 if ( op == QgsExpressionNodeBinaryOperator::boIs || op == QgsExpressionNodeBinaryOperator::boIsNot )
2316 if ( node->opRight()->nodeType() == QgsExpressionNode::ntLiteral )
2318 const QgsExpressionNodeLiteral *rightLit =
static_cast<const QgsExpressionNodeLiteral *
>( node->opRight() );
2319 if ( rightLit->value().isNull() )
2322 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2323 elem.appendChild( leftElem );
2325 if ( op == QgsExpressionNodeBinaryOperator::boIsNot )
2327 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2328 notElem.appendChild( elem );
2336 op = ( op == QgsExpressionNodeBinaryOperator::boIs ? QgsExpressionNodeBinaryOperator::boEQ : QgsExpressionNodeBinaryOperator::boNE );
2342 if ( !mErrorMessage.isEmpty() )
2343 return QDomElement();
2346 QString opText = binaryOperatorToTagName( op );
2347 if ( opText.isEmpty() )
2351 mErrorMessage = QObject::tr(
"Binary operator %1 not implemented yet" ).arg( node->text() );
2352 return QDomElement();
2355 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2357 if ( op == QgsExpressionNodeBinaryOperator::boLike || op == QgsExpressionNodeBinaryOperator::boILike )
2359 if ( op == QgsExpressionNodeBinaryOperator::boILike )
2360 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2363 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2364 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2366 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2368 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2371 boElem.appendChild( leftElem );
2372 boElem.appendChild( rightElem );
2377 QDomElement QgsOgcUtilsExprToFilter::expressionLiteralToOgcFilter(
const QgsExpressionNodeLiteral *node )
2380 switch ( node->value().type() )
2383 value = QString::number( node->value().toInt() );
2385 case QVariant::Double:
2388 case QVariant::String:
2389 value = node->value().toString();
2393 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->value().type() );
2394 return QDomElement();
2397 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2398 litElem.appendChild( mDoc.createTextNode( value ) );
2403 QDomElement QgsOgcUtilsExprToFilter::expressionColumnRefToOgcFilter(
const QgsExpressionNodeColumnRef *node )
2405 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2406 propElem.appendChild( mDoc.createTextNode( node->name() ) );
2412 QDomElement QgsOgcUtilsExprToFilter::expressionInOperatorToOgcFilter(
const QgsExpressionNodeInOperator *node )
2414 if ( node->list()->list().size() == 1 )
2417 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2420 Q_FOREACH ( QgsExpressionNode *n, node->list()->list() )
2423 if ( !mErrorMessage.isEmpty() )
2424 return QDomElement();
2426 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2427 eqElem.appendChild( leftNode.cloneNode() );
2428 eqElem.appendChild( listNode );
2430 orElem.appendChild( eqElem );
2433 if ( node->isNotIn() )
2435 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2436 notElem.appendChild( orElem );
2443 static const QMap<QString, QString> BINARY_SPATIAL_OPS_MAP
2445 { QStringLiteral(
"disjoint" ), QStringLiteral(
"Disjoint" ) },
2446 { QStringLiteral(
"intersects" ), QStringLiteral(
"Intersects" )},
2447 { QStringLiteral(
"touches" ), QStringLiteral(
"Touches" ) },
2448 { QStringLiteral(
"crosses" ), QStringLiteral(
"Crosses" ) },
2449 { QStringLiteral(
"contains" ), QStringLiteral(
"Contains" ) },
2450 { QStringLiteral(
"overlaps" ), QStringLiteral(
"Overlaps" ) },
2451 { QStringLiteral(
"within" ), QStringLiteral(
"Within" ) }
2454 static bool isBinarySpatialOperator(
const QString &fnName )
2456 return BINARY_SPATIAL_OPS_MAP.contains( fnName );
2459 static QString tagNameForSpatialOperator(
const QString &fnName )
2461 return BINARY_SPATIAL_OPS_MAP.value( fnName );
2464 static bool isGeometryColumn(
const QgsExpressionNode *node )
2466 if ( node->nodeType() != QgsExpressionNode::ntFunction )
2469 const QgsExpressionNodeFunction *fn =
static_cast<const QgsExpressionNodeFunction *
>( node );
2470 QgsExpressionFunction *fd = QgsExpression::Functions()[fn->fnIndex()];
2471 return fd->name() == QLatin1String(
"$geometry" );
2474 static QgsGeometry geometryFromConstExpr(
const QgsExpressionNode *node )
2479 if ( node->nodeType() == QgsExpressionNode::ntFunction )
2481 const QgsExpressionNodeFunction *fnNode =
static_cast<const QgsExpressionNodeFunction *
>( node );
2482 QgsExpressionFunction *fnDef = QgsExpression::Functions()[fnNode->fnIndex()];
2483 if ( fnDef->name() == QLatin1String(
"geom_from_wkt" ) )
2485 const QList<QgsExpressionNode *> &args = fnNode->args()->list();
2486 if ( args[0]->nodeType() == QgsExpressionNode::ntLiteral )
2488 QString wkt =
static_cast<const QgsExpressionNodeLiteral *
>( args[0] )->value().toString();
2497 QDomElement QgsOgcUtilsExprToFilter::expressionFunctionToOgcFilter(
const QgsExpressionNodeFunction *node )
2499 QgsExpressionFunction *fd = QgsExpression::Functions()[node->fnIndex()];
2501 if ( fd->name() == QLatin1String(
"intersects_bbox" ) )
2503 QList<QgsExpressionNode *> argNodes = node->args()->list();
2504 Q_ASSERT( argNodes.count() == 2 );
2506 QgsGeometry geom = geometryFromConstExpr( argNodes[1] );
2507 if ( !geom.isNull() && isGeometryColumn( argNodes[0] ) )
2517 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2518 geomProperty.appendChild( mDoc.createTextNode( mGeometryName ) );
2520 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":BBOX" );
2521 funcElem.appendChild( geomProperty );
2522 funcElem.appendChild( elemBox );
2527 mErrorMessage = QObject::tr(
"<BBOX> is currently supported only in form: bbox($geometry, geomFromWKT('…'))" );
2528 return QDomElement();
2532 if ( isBinarySpatialOperator( fd->name() ) )
2534 QList<QgsExpressionNode *> argNodes = node->args()->list();
2535 Q_ASSERT( argNodes.count() == 2 );
2537 QgsExpressionNode *otherNode =
nullptr;
2538 if ( isGeometryColumn( argNodes[0] ) )
2539 otherNode = argNodes[1];
2540 else if ( isGeometryColumn( argNodes[1] ) )
2541 otherNode = argNodes[0];
2544 mErrorMessage = QObject::tr(
"Unable to translate spatial operator: at least one must refer to geometry." );
2545 return QDomElement();
2548 QDomElement otherGeomElem;
2551 if ( otherNode->nodeType() != QgsExpressionNode::ntFunction )
2553 mErrorMessage = QObject::tr(
"spatial operator: the other operator must be a geometry constructor function" );
2554 return QDomElement();
2557 const QgsExpressionNodeFunction *otherFn =
static_cast<const QgsExpressionNodeFunction *
>( otherNode );
2558 QgsExpressionFunction *otherFnDef = QgsExpression::Functions()[otherFn->fnIndex()];
2559 if ( otherFnDef->name() == QLatin1String(
"geom_from_wkt" ) )
2561 QgsExpressionNode *firstFnArg = otherFn->args()->list()[0];
2562 if ( firstFnArg->nodeType() != QgsExpressionNode::ntLiteral )
2564 mErrorMessage = QObject::tr(
"geom_from_wkt: argument must be string literal" );
2565 return QDomElement();
2567 QString wkt =
static_cast<const QgsExpressionNodeLiteral *
>( firstFnArg )->value().toString();
2570 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2573 else if ( otherFnDef->name() == QLatin1String(
"geom_from_gml" ) )
2575 QgsExpressionNode *firstFnArg = otherFn->args()->list()[0];
2576 if ( firstFnArg->nodeType() != QgsExpressionNode::ntLiteral )
2578 mErrorMessage = QObject::tr(
"geom_from_gml: argument must be string literal" );
2579 return QDomElement();
2582 QDomDocument geomDoc;
2583 QString gml =
static_cast<const QgsExpressionNodeLiteral *
>( firstFnArg )->value().toString();
2584 if ( !geomDoc.setContent( gml,
true ) )
2586 mErrorMessage = QObject::tr(
"geom_from_gml: unable to parse XML" );
2587 return QDomElement();
2590 QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(), true );
2591 otherGeomElem = geomNode.toElement();
2595 mErrorMessage = QObject::tr(
"spatial operator: unknown geometry constructor function" );
2596 return QDomElement();
2601 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + tagNameForSpatialOperator( fd->name() ) );
2602 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2603 geomProperty.appendChild( mDoc.createTextNode( mGeometryName ) );
2604 funcElem.appendChild( geomProperty );
2605 funcElem.appendChild( otherGeomElem );
2609 if ( fd->params() == 0 )
2611 mErrorMessage = QObject::tr(
"Special columns/constants are not supported." );
2612 return QDomElement();
2616 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
2617 funcElem.setAttribute( QStringLiteral(
"name" ), fd->name() );
2618 Q_FOREACH ( QgsExpressionNode *n, node->args()->list() )
2621 if ( !mErrorMessage.isEmpty() )
2622 return QDomElement();
2624 funcElem.appendChild( childElem );
2635 const QList<QgsOgcUtils::LayerProperties> &layerProperties,
2636 bool honourAxisOrientation,
2637 bool invertAxisOrientation,
2638 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename )
2641 , mGMLVersion( gmlVersion )
2642 , mFilterVersion( filterVersion )
2643 , mLayerProperties( layerProperties )
2644 , mHonourAxisOrientation( honourAxisOrientation )
2645 , mInvertAxisOrientation( invertAxisOrientation )
2646 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
2647 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
2649 , mMapUnprefixedTypenameToPrefixedTypename( mapUnprefixedTypenameToPrefixedTypename )
2658 return toOgcFilter( static_cast<const QgsSQLStatement::NodeUnaryOperator *>( node ) );
2660 return toOgcFilter( static_cast<const QgsSQLStatement::NodeBinaryOperator *>( node ) );
2662 return toOgcFilter( static_cast<const QgsSQLStatement::NodeInOperator *>( node ) );
2664 return toOgcFilter( static_cast<const QgsSQLStatement::NodeBetweenOperator *>( node ) );
2666 return toOgcFilter( static_cast<const QgsSQLStatement::NodeFunction *>( node ) );
2668 return toOgcFilter( static_cast<const QgsSQLStatement::NodeLiteral *>( node ) );
2670 return toOgcFilter( static_cast<const QgsSQLStatement::NodeColumnRef *>( node ) );
2672 return toOgcFilter( static_cast<const QgsSQLStatement::NodeSelect *>( node ) );
2675 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
2676 return QDomElement();
2685 if ( !mErrorMessage.isEmpty() )
2686 return QDomElement();
2689 switch ( node->
op() )
2692 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2697 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
2698 mDoc.removeChild( operandElem );
2702 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
2703 return QDomElement();
2707 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
2708 uoElem.appendChild( operandElem );
2713 return QDomElement();
2723 if ( !mErrorMessage.isEmpty() )
2724 return QDomElement();
2734 if ( rightLit->
value().isNull() )
2737 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2738 elem.appendChild( leftElem );
2742 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2743 notElem.appendChild( elem );
2757 if ( !mErrorMessage.isEmpty() )
2758 return QDomElement();
2763 opText = QStringLiteral(
"Or" );
2765 opText = QStringLiteral(
"And" );
2767 opText = QStringLiteral(
"PropertyIsEqualTo" );
2769 opText = QStringLiteral(
"PropertyIsNotEqualTo" );
2771 opText = QStringLiteral(
"PropertyIsLessThanOrEqualTo" );
2773 opText = QStringLiteral(
"PropertyIsGreaterThanOrEqualTo" );
2775 opText = QStringLiteral(
"PropertyIsLessThan" );
2777 opText = QStringLiteral(
"PropertyIsGreaterThan" );
2779 opText = QStringLiteral(
"PropertyIsLike" );
2781 opText = QStringLiteral(
"PropertyIsLike" );
2783 if ( opText.isEmpty() )
2787 return QDomElement();
2790 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2795 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2798 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2799 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2801 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2803 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2806 boElem.appendChild( leftElem );
2807 boElem.appendChild( rightElem );
2815 switch ( node->
value().type() )
2818 value = QString::number( node->
value().toInt() );
2820 case QVariant::LongLong:
2821 value = QString::number( node->
value().toLongLong() );
2823 case QVariant::Double:
2826 case QVariant::String:
2827 value = node->
value().toString();
2831 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2832 return QDomElement();
2835 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2836 litElem.appendChild( mDoc.createTextNode( value ) );
2843 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2844 if ( node->
tableName().isEmpty() || mLayerProperties.size() == 1 )
2845 propElem.appendChild( mDoc.createTextNode( node->
name() ) );
2848 QString tableName( mMapTableAliasToNames[node->
tableName()] );
2849 if ( mMapUnprefixedTypenameToPrefixedTypename.contains( tableName ) )
2850 tableName = mMapUnprefixedTypenameToPrefixedTypename[tableName];
2851 propElem.appendChild( mDoc.createTextNode( tableName +
"/" + node->
name() ) );
2858 if ( node->
list()->
list().size() == 1 )
2861 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2867 if ( !mErrorMessage.isEmpty() )
2868 return QDomElement();
2870 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2871 eqElem.appendChild( leftNode.cloneNode() );
2872 eqElem.appendChild( listNode );
2874 orElem.appendChild( eqElem );
2879 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2880 notElem.appendChild( orElem );
2889 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsBetween" );
2891 QDomElement lowerBoundary = mDoc.createElement( mFilterPrefix +
":LowerBoundary" );
2893 elem.appendChild( lowerBoundary );
2894 QDomElement upperBoundary = mDoc.createElement( mFilterPrefix +
":UpperBoundary" );
2896 elem.appendChild( upperBoundary );
2900 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2901 notElem.appendChild( elem );
2908 static QString mapBinarySpatialToOgc(
const QString &name )
2910 QString nameCompare( name );
2911 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QStringLiteral(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2912 nameCompare = name.mid( 3 );
2913 QStringList spatialOps;
2914 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
2915 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
2916 Q_FOREACH ( QString op, spatialOps )
2918 if ( nameCompare.compare( op, Qt::CaseInsensitive ) == 0 )
2924 static QString mapTernarySpatialToOgc(
const QString &name )
2926 QString nameCompare( name );
2927 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QStringLiteral(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2928 nameCompare = name.mid( 3 );
2929 if ( nameCompare.compare( QLatin1String(
"DWithin" ), Qt::CaseInsensitive ) == 0 )
2930 return QStringLiteral(
"DWithin" );
2931 if ( nameCompare.compare( QLatin1String(
"Beyond" ), Qt::CaseInsensitive ) == 0 )
2932 return QStringLiteral(
"Beyond" );
2936 QString QgsOgcUtilsSQLStatementToFilter::getGeometryColumnSRSName(
const QgsSQLStatement::Node *node )
2946 if ( prop.
mName.compare( mMapTableAliasToNames[col->
tableName()], Qt::CaseInsensitive ) == 0 &&
2953 if ( !mLayerProperties.empty() &&
2954 mLayerProperties.at( 0 ).mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2956 return mLayerProperties.at( 0 ).mSRSName;
2962 QList<QgsSQLStatement::Node *> args,
2963 bool lastArgIsSRSName,
2965 bool &axisInversion )
2967 srsName = mCurrentSRSName;
2968 axisInversion = mInvertAxisOrientation;
2970 if ( lastArgIsSRSName )
2975 mErrorMessage = QObject::tr(
"%1: Last argument must be string or integer literal" ).arg( mainNode->
name() );
2979 if ( lit->
value().type() == QVariant::Int )
2983 srsName =
"EPSG:" + QString::number( lit->
value().toInt() );
2987 srsName =
"urn:ogc:def:crs:EPSG::" + QString::number( lit->
value().toInt() );
2992 srsName = lit->
value().toString();
2993 if ( srsName.startsWith( QLatin1String(
"EPSG:" ), Qt::CaseInsensitive ) )
2999 if ( !srsName.isEmpty() )
3005 axisInversion = !axisInversion;
3015 if ( node->
name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 )
3017 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
3018 if ( args.size() != 1 && args.size() != 2 )
3020 mErrorMessage = QObject::tr(
"Function %1 should have 1 or 2 arguments" ).arg( node->
name() );
3021 return QDomElement();
3027 mErrorMessage = QObject::tr(
"%1: First argument must be string literal" ).arg( node->
name() );
3028 return QDomElement();
3033 if ( ! processSRSName( node, args, args.size() == 2, srsName, axisInversion ) )
3035 return QDomElement();
3041 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
3043 if ( geomElem.isNull() )
3045 mErrorMessage = QObject::tr(
"%1: invalid WKT" ).arg( node->
name() );
3046 return QDomElement();
3053 if ( node->
name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 )
3055 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
3056 if ( args.size() != 4 && args.size() != 5 )
3058 mErrorMessage = QObject::tr(
"Function %1 should have 4 or 5 arguments" ).arg( node->
name() );
3059 return QDomElement();
3064 for (
int i = 0; i < 4; i++ )
3069 mErrorMessage = QObject::tr(
"%1: Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
3070 return QDomElement();
3074 if ( lit->
value().type() == QVariant::Int )
3075 val = lit->
value().toInt();
3076 else if ( lit->
value().type() == QVariant::LongLong )
3077 val = lit->
value().toLongLong();
3078 else if ( lit->
value().type() == QVariant::Double )
3079 val = lit->
value().toDouble();
3082 mErrorMessage = QObject::tr(
"%1 Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
3083 return QDomElement();
3097 if ( ! processSRSName( node, args, args.size() == 5, srsName, axisInversion ) )
3099 return QDomElement();
3110 if ( node->
name().compare( QLatin1String(
"ST_GeomFromGML" ), Qt::CaseInsensitive ) == 0 )
3112 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
3113 if ( args.size() != 1 )
3115 mErrorMessage = QObject::tr(
"Function %1 should have 1 argument" ).arg( node->
name() );
3116 return QDomElement();
3122 mErrorMessage = QObject::tr(
"%1: Argument must be string literal" ).arg( node->
name() );
3123 return QDomElement();
3126 QDomDocument geomDoc;
3128 if ( !geomDoc.setContent( gml,
true ) )
3130 mErrorMessage = QObject::tr(
"ST_GeomFromGML: unable to parse XML" );
3131 return QDomElement();
3134 QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(), true );
3136 return geomNode.toElement();
3140 QString ogcName( mapBinarySpatialToOgc( node->
name() ) );
3141 if ( !ogcName.isEmpty() )
3143 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
3144 if ( args.size() != 2 )
3146 mErrorMessage = QObject::tr(
"Function %1 should have 2 arguments" ).arg( node->
name() );
3147 return QDomElement();
3150 for (
int i = 0; i < 2; i ++ )
3153 ( static_cast<const QgsSQLStatement::NodeFunction *>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
3154 static_cast<const QgsSQLStatement::NodeFunction *>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
3156 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
3163 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + ogcName );
3167 if ( !mErrorMessage.isEmpty() )
3169 mCurrentSRSName.clear();
3170 return QDomElement();
3173 funcElem.appendChild( childElem );
3176 mCurrentSRSName.clear();
3180 ogcName = mapTernarySpatialToOgc( node->
name() );
3181 if ( !ogcName.isEmpty() )
3183 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
3184 if ( args.size() != 3 )
3186 mErrorMessage = QObject::tr(
"Function %1 should have 3 arguments" ).arg( node->
name() );
3187 return QDomElement();
3190 for (
int i = 0; i < 2; i ++ )
3193 ( static_cast<const QgsSQLStatement::NodeFunction *>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
3194 static_cast<const QgsSQLStatement::NodeFunction *>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
3196 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
3201 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + node->
name().mid( 3 ) );
3202 for (
int i = 0; i < 2; i++ )
3205 if ( !mErrorMessage.isEmpty() )
3207 mCurrentSRSName.clear();
3208 return QDomElement();
3211 funcElem.appendChild( childElem );
3213 mCurrentSRSName.clear();
3218 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() );
3219 return QDomElement();
3222 if ( lit->
value().isNull() )
3224 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() );
3225 return QDomElement();
3228 QString unit( QStringLiteral(
"m" ) );
3229 switch ( lit->
value().type() )
3232 distance = QString::number( lit->
value().toInt() );
3234 case QVariant::LongLong:
3235 distance = QString::number( lit->
value().toLongLong() );
3237 case QVariant::Double:
3240 case QVariant::String:
3242 distance = lit->
value().toString();
3243 for (
int i = 0; i < distance.size(); i++ )
3245 if ( !( ( distance[i] >=
'0' && distance[i] <=
'9' ) || distance[i] ==
'-' || distance[i] ==
'.' || distance[i] ==
'e' || distance[i] ==
'E' ) )
3247 unit = distance.mid( i ).trimmed();
3248 distance = distance.mid( 0, i );
3256 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( lit->
value().type() );
3257 return QDomElement();
3260 QDomElement distanceElem = mDoc.createElement( mFilterPrefix +
":Distance" );
3262 distanceElem.setAttribute( QStringLiteral(
"uom" ), unit );
3264 distanceElem.setAttribute( QStringLiteral(
"unit" ), unit );
3265 distanceElem.appendChild( mDoc.createTextNode( distance ) );
3266 funcElem.appendChild( distanceElem );
3271 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
3272 funcElem.setAttribute( QStringLiteral(
"name" ), node->
name() );
3276 if ( !mErrorMessage.isEmpty() )
3277 return QDomElement();
3279 funcElem.appendChild( childElem );
3285 const QString &leftTable )
3293 QList<QDomElement> listElem;
3294 Q_FOREACH (
const QString &columnName, node->
usingColumns() )
3296 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
3297 QDomElement propElem1 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3298 propElem1.appendChild( mDoc.createTextNode( leftTable +
"/" + columnName ) );
3299 eqElem.appendChild( propElem1 );
3300 QDomElement propElem2 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3301 propElem2.appendChild( mDoc.createTextNode( node->
tableDef()->
name() +
"/" + columnName ) );
3302 eqElem.appendChild( propElem2 );
3303 listElem.append( eqElem );
3306 if ( listElem.size() == 1 )
3310 else if ( listElem.size() > 1 )
3312 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3313 Q_FOREACH (
const QDomElement &elem, listElem )
3315 andElem.appendChild( elem );
3320 return QDomElement();
3325 if ( node->
alias().isEmpty() )
3327 mMapTableAliasToNames[ node->
name()] = node->
name();
3331 mMapTableAliasToNames[ node->
alias()] = node->
name();
3337 QList<QDomElement> listElem;
3340 ( node->
tables().size() != 1 || !node->
joins().empty() ) )
3342 mErrorMessage = QObject::tr(
"Joins are only supported with WFS 2.0" );
3343 return QDomElement();
3357 QList< QgsSQLStatement::NodeTableDef *> nodeTables = node->
tables();
3358 QString leftTable = nodeTables.at( nodeTables.length() - 1 )->name();
3361 QDomElement joinElem =
toOgcFilter( join, leftTable );
3362 if ( !mErrorMessage.isEmpty() )
3363 return QDomElement();
3364 listElem.append( joinElem );
3369 if ( node->
where() )
3372 if ( !mErrorMessage.isEmpty() )
3373 return QDomElement();
3374 listElem.append( whereElem );
3378 if ( listElem.size() == 1 )
3382 else if ( listElem.size() > 1 )
3384 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3385 Q_FOREACH (
const QDomElement &elem, listElem )
3387 andElem.appendChild( elem );
3392 return QDomElement();
QgsSQLStatement::NodeList * list() const
Values list.
A rectangle specified with double values.
Internal use by QgsOgcUtils.
QgsSQLStatement::Node * onExpr() const
On expression. Will be nullptr if usingColumns() is not empty.
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 fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length...
QgsWkbTypes::Type wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
A class to represent a 2D point.
QgsSQLStatement::NodeTableDef * tableDef() const
Table definition.
QgsSQLStatement::Node * operand() const
Operand.
QgsSQLStatement::Node * where() const
Return 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[]
QString errorMessage() const
Return the error message.
bool GMLNamespaceUsed() const
Return whether the gml: namespace is used.
QDomElement expressionNodeToOgcFilter(const QgsExpressionNode *node)
Convert an expression to a OGC filter.
A geometry is the spatial representation of a feature.
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.
Binary logical/arithmetical operator (AND, OR, =, +, ...)
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
QString name() const
Return 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.
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
Return whether the gml: namespace is used.
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.
QString name() const
Table name.
QString alias() const
Table alias.
QgsSQLStatement::NodeList * args() const
Return arguments.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
void setYMinimum(double y)
Set the minimum y value.
Literal value (integer, integer64, double, string)
QString errorMessage() const
Return the error message.
QString name() const
The name of the column.
QList< QgsSQLStatement::NodeTableDef * > tables() const
Return the list of tables.
Internal use by QgsOgcUtils.
Unary logicial/arithmetical operator ( NOT, - )
QgsSQLStatement::BinaryOperator op() const
Operator.
const QgsSQLStatement::Node * rootNode() const
Returns root node of the statement. Root node is null is parsing has failed.
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.
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).
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
Return the list of joins.
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.
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
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()
Return list.
static QDomElement expressionToOgcExpression(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates an OGC expression XML element.
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 QgsExpression * expressionFromOgcFilter(const QDomElement &element)
Parse XML with OGC filter into QGIS expression.
static QDomElement geometryToGML(const QgsGeometry &geometry, QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, const QString &srsName, bool invertAxisOrientation, const QString &gmlIdBase, int precision=17)
Exports the geometry to GML.
static 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).
QString mGeometryAttribute
Geometry attribute name.
static QColor colorFromOgcFill(const QDomElement &fillElement)
Parse XML with OGC fill into QColor.
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.
'x IN (y, z)' operator
QgsSQLStatement::Node * node() const
Variable at the left of IN.
The QgsOgcUtils class provides various utility functions for conversion between OGC (Open Geospatial ...
QgsSQLStatement::Node * opLeft() const
Left operand.
QgsSQLStatement::Node * opRight() const
Right operand.
void setXMinimum(double x)
Set the minimum x value.
virtual QgsSQLStatement::NodeType nodeType() const =0
Abstract virtual that returns the type of this node.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.