29 #include <QStringList> 30 #include <QTextStream> 34 #include <netinet/in.h> 40 #define GML_NAMESPACE QStringLiteral( "http://www.opengis.net/gml" ) 41 #define GML32_NAMESPACE QStringLiteral( "http://www.opengis.net/gml/3.2" ) 42 #define OGC_NAMESPACE QStringLiteral( "http://www.opengis.net/ogc" ) 43 #define 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 tuple_coords;
861 bool conversionSuccess;
863 QStringList::const_iterator it;
864 for ( it = tupels.constBegin(); it != tupels.constEnd(); ++it )
866 tuple_coords = ( *it ).split( coordSeparator, QString::SkipEmptyParts );
867 if ( tuple_coords.size() < 2 )
871 x = tuple_coords.at( 0 ).toDouble( &conversionSuccess );
872 if ( !conversionSuccess )
876 y = tuple_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();
1679 static int binaryOperatorFromTagName(
const QString &tagName )
1682 return BINARY_OPERATORS_TAG_NAMES_MAP()->value( tagName, -1 );
1689 return QStringLiteral(
"PropertyIsLike" );
1691 return BINARY_OPERATORS_TAG_NAMES_MAP()->key( op, QString() );
1694 static bool isBinaryOperator(
const QString &tagName )
1696 return binaryOperatorFromTagName( tagName ) >= 0;
1700 static bool isSpatialOperator(
const QString &tagName )
1702 static QStringList spatialOps;
1703 if ( spatialOps.isEmpty() )
1705 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
1706 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
1709 return spatialOps.contains( tagName );
1768 QgsExpressionNode *QgsOgcUtils::nodeIsBetweenFromOgcFilter( QDomElement &element, QString &errorMessage )
1790 return expressionToOgcFilter( exp, doc, GML_2_1_2, FILTER_OGC_1_0,
1791 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage );
1796 return expressionToOgcExpression( exp, doc, GML_2_1_2, FILTER_OGC_1_0,
1797 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage );
1805 const QString &srsName,
1806 bool honourAxisOrientation,
1807 bool invertAxisOrientation,
1808 QString *errorMessage )
1811 return QDomElement();
1817 QgsOgcUtilsExprToFilter utils( doc, gmlVersion, filterVersion, geometryName, srsName, honourAxisOrientation, invertAxisOrientation );
1821 if ( exprRootElem.isNull() )
1822 return QDomElement();
1824 QDomElement filterElem =
1825 ( filterVersion == FILTER_FES_2_0 ) ?
1826 doc.createElementNS(
FES_NAMESPACE, QStringLiteral(
"fes:Filter" ) ) :
1827 doc.createElementNS(
OGC_NAMESPACE, QStringLiteral(
"ogc:Filter" ) );
1830 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:gml" ) );
1831 if ( gmlVersion == GML_3_2_1 )
1835 filterElem.setAttributeNode( attr );
1837 filterElem.appendChild( exprRootElem );
1846 const QString &srsName,
1847 bool honourAxisOrientation,
1848 bool invertAxisOrientation,
1849 QString *errorMessage )
1858 return QDomElement();
1866 QgsOgcUtilsExprToFilter utils( doc, gmlVersion, filterVersion, geometryName, srsName, honourAxisOrientation, invertAxisOrientation );
1872 if ( !exprRootElem.isNull() )
1874 return exprRootElem;
1881 *errorMessage = QObject::tr(
"Node type not supported in expression translation: %1" ).arg( node->
nodeType() );
1885 return QDomElement();
1892 const QList<LayerProperties> &layerProperties,
1893 bool honourAxisOrientation,
1894 bool invertAxisOrientation,
1895 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename,
1896 QString *errorMessage )
1899 return QDomElement();
1902 layerProperties, honourAxisOrientation, invertAxisOrientation,
1903 mapUnprefixedTypenameToPrefixedTypename );
1907 if ( exprRootElem.isNull() )
1908 return QDomElement();
1910 QDomElement filterElem =
1911 ( filterVersion == FILTER_FES_2_0 ) ?
1912 doc.createElementNS(
FES_NAMESPACE, QStringLiteral(
"fes:Filter" ) ) :
1913 doc.createElementNS(
OGC_NAMESPACE, QStringLiteral(
"ogc:Filter" ) );
1916 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:gml" ) );
1917 if ( gmlVersion == GML_3_2_1 )
1921 filterElem.setAttributeNode( attr );
1923 filterElem.appendChild( exprRootElem );
1935 return expressionUnaryOperatorToOgcFilter( static_cast<const QgsExpressionNodeUnaryOperator *>( node ), expression, context );
1937 return expressionBinaryOperatorToOgcFilter( static_cast<const QgsExpressionNodeBinaryOperator *>( node ), expression, context );
1939 return expressionInOperatorToOgcFilter( static_cast<const QgsExpressionNodeInOperator *>( node ), expression, context );
1941 return expressionFunctionToOgcFilter( static_cast<const QgsExpressionNodeFunction *>( node ), expression, context );
1943 return expressionLiteralToOgcFilter( static_cast<const QgsExpressionNodeLiteral *>( node ), expression, context );
1945 return expressionColumnRefToOgcFilter( static_cast<const QgsExpressionNodeColumnRef *>( node ), expression, context );
1948 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
1949 return QDomElement();
1956 if ( !mErrorMessage.isEmpty() )
1957 return QDomElement();
1960 switch ( node->
op() )
1963 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
1968 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
1969 mDoc.removeChild( operandElem );
1973 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
1974 return QDomElement();
1978 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
1979 uoElem.appendChild( operandElem );
1983 mErrorMessage = QObject::tr(
"Unary operator '%1' not implemented yet" ).arg( node->
text() );
1984 return QDomElement();
1994 if ( !mErrorMessage.isEmpty() )
1995 return QDomElement();
2005 if ( rightLit->
value().isNull() )
2008 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2009 elem.appendChild( leftElem );
2013 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2014 notElem.appendChild( elem );
2028 if ( !mErrorMessage.isEmpty() )
2029 return QDomElement();
2032 QString opText = binaryOperatorToTagName( op );
2033 if ( opText.isEmpty() )
2037 mErrorMessage = QObject::tr(
"Binary operator %1 not implemented yet" ).arg( node->
text() );
2038 return QDomElement();
2041 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2046 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2049 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2050 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2052 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2054 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2057 boElem.appendChild( leftElem );
2058 boElem.appendChild( rightElem );
2065 Q_UNUSED( expression )
2068 switch ( node->
value().type() )
2071 value = QString::number( node->
value().toInt() );
2073 case QVariant::Double:
2076 case QVariant::String:
2077 value = node->
value().toString();
2079 case QVariant::Date:
2080 value = node->
value().toDate().toString( Qt::ISODate );
2082 case QVariant::DateTime:
2083 value = node->
value().toDateTime().toString( Qt::ISODate );
2087 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2088 return QDomElement();
2091 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2092 litElem.appendChild( mDoc.createTextNode( value ) );
2099 Q_UNUSED( expression )
2101 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2102 propElem.appendChild( mDoc.createTextNode( node->
name() ) );
2110 if ( node->
list()->
list().size() == 1 )
2113 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2116 const auto constList = node->
list()->
list();
2120 if ( !mErrorMessage.isEmpty() )
2121 return QDomElement();
2123 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2124 eqElem.appendChild( leftNode.cloneNode() );
2125 eqElem.appendChild( listNode );
2127 orElem.appendChild( eqElem );
2132 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2133 notElem.appendChild( orElem );
2142 { QLatin1String(
"disjoint" ), QLatin1String(
"Disjoint" ) },
2143 { QLatin1String(
"intersects" ), QLatin1String(
"Intersects" )},
2144 { QLatin1String(
"touches" ), QLatin1String(
"Touches" ) },
2145 { QLatin1String(
"crosses" ), QLatin1String(
"Crosses" ) },
2146 { QLatin1String(
"contains" ), QLatin1String(
"Contains" ) },
2147 { QLatin1String(
"overlaps" ), QLatin1String(
"Overlaps" ) },
2148 { QLatin1String(
"within" ), QLatin1String(
"Within" ) }
2151 static bool isBinarySpatialOperator(
const QString &fnName )
2153 return BINARY_SPATIAL_OPS_MAP()->contains( fnName );
2156 static QString tagNameForSpatialOperator(
const QString &fnName )
2158 return BINARY_SPATIAL_OPS_MAP()->value( fnName );
2168 return fd->
name() == QLatin1String(
"$geometry" );
2180 if ( fnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2182 const QList<QgsExpressionNode *> &args = fnNode->
args()->
list();
2198 if ( fd->
name() == QLatin1String(
"intersects_bbox" ) )
2200 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2201 Q_ASSERT( argNodes.count() == 2 );
2203 QgsGeometry geom = geometryFromConstExpr( argNodes[1] );
2204 if ( !geom.isNull() && isGeometryColumn( argNodes[0] ) )
2214 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2215 geomProperty.appendChild( mDoc.createTextNode( mGeometryName ) );
2217 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":BBOX" );
2218 funcElem.appendChild( geomProperty );
2219 funcElem.appendChild( elemBox );
2224 mErrorMessage = QObject::tr(
"<BBOX> is currently supported only in form: bbox($geometry, geomFromWKT('…'))" );
2225 return QDomElement();
2229 if ( isBinarySpatialOperator( fd->
name() ) )
2231 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2232 Q_ASSERT( argNodes.count() == 2 );
2235 if ( isGeometryColumn( argNodes[0] ) )
2236 otherNode = argNodes[1];
2237 else if ( isGeometryColumn( argNodes[1] ) )
2238 otherNode = argNodes[0];
2241 mErrorMessage = QObject::tr(
"Unable to translate spatial operator: at least one must refer to geometry." );
2242 return QDomElement();
2245 QDomElement otherGeomElem;
2250 mErrorMessage = QObject::tr(
"spatial operator: the other operator must be a geometry constructor function" );
2251 return QDomElement();
2256 if ( otherFnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2261 mErrorMessage = QObject::tr(
"geom_from_wkt: argument must be string literal" );
2262 return QDomElement();
2267 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2270 else if ( otherFnDef->
name() == QLatin1String(
"geom_from_gml" ) )
2275 mErrorMessage = QObject::tr(
"geom_from_gml: argument must be string literal" );
2276 return QDomElement();
2279 QDomDocument geomDoc;
2281 if ( !geomDoc.setContent( gml,
true ) )
2283 mErrorMessage = QObject::tr(
"geom_from_gml: unable to parse XML" );
2284 return QDomElement();
2287 QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(), true );
2288 otherGeomElem = geomNode.toElement();
2292 mErrorMessage = QObject::tr(
"spatial operator: unknown geometry constructor function" );
2293 return QDomElement();
2298 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + tagNameForSpatialOperator( fd->
name() ) );
2299 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2300 geomProperty.appendChild( mDoc.createTextNode( mGeometryName ) );
2301 funcElem.appendChild( geomProperty );
2302 funcElem.appendChild( otherGeomElem );
2306 if ( fd->
isStatic( node, expression, context ) )
2308 QVariant result = fd->
run( node->
args(), context, expression, node );
2310 return expressionLiteralToOgcFilter( &literal, expression, context );
2315 mErrorMessage = QObject::tr(
"Special columns/constants are not supported." );
2316 return QDomElement();
2320 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
2321 funcElem.setAttribute( QStringLiteral(
"name" ), fd->
name() );
2322 const auto constList = node->
args()->
list();
2326 if ( !mErrorMessage.isEmpty() )
2327 return QDomElement();
2329 funcElem.appendChild( childElem );
2340 const QList<QgsOgcUtils::LayerProperties> &layerProperties,
2341 bool honourAxisOrientation,
2342 bool invertAxisOrientation,
2343 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename )
2346 , mGMLVersion( gmlVersion )
2347 , mFilterVersion( filterVersion )
2348 , mLayerProperties( layerProperties )
2349 , mHonourAxisOrientation( honourAxisOrientation )
2350 , mInvertAxisOrientation( invertAxisOrientation )
2351 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
2352 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
2354 , mMapUnprefixedTypenameToPrefixedTypename( mapUnprefixedTypenameToPrefixedTypename )
2363 return toOgcFilter( static_cast<const QgsSQLStatement::NodeUnaryOperator *>( node ) );
2365 return toOgcFilter( static_cast<const QgsSQLStatement::NodeBinaryOperator *>( node ) );
2367 return toOgcFilter( static_cast<const QgsSQLStatement::NodeInOperator *>( node ) );
2369 return toOgcFilter( static_cast<const QgsSQLStatement::NodeBetweenOperator *>( node ) );
2371 return toOgcFilter( static_cast<const QgsSQLStatement::NodeFunction *>( node ) );
2373 return toOgcFilter( static_cast<const QgsSQLStatement::NodeLiteral *>( node ) );
2375 return toOgcFilter( static_cast<const QgsSQLStatement::NodeColumnRef *>( node ) );
2377 return toOgcFilter( static_cast<const QgsSQLStatement::NodeSelect *>( node ) );
2380 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
2381 return QDomElement();
2390 if ( !mErrorMessage.isEmpty() )
2391 return QDomElement();
2394 switch ( node->
op() )
2397 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2402 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
2403 mDoc.removeChild( operandElem );
2407 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
2408 return QDomElement();
2412 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
2413 uoElem.appendChild( operandElem );
2418 return QDomElement();
2428 if ( !mErrorMessage.isEmpty() )
2429 return QDomElement();
2439 if ( rightLit->
value().isNull() )
2442 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2443 elem.appendChild( leftElem );
2447 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2448 notElem.appendChild( elem );
2462 if ( !mErrorMessage.isEmpty() )
2463 return QDomElement();
2468 opText = QStringLiteral(
"Or" );
2470 opText = QStringLiteral(
"And" );
2472 opText = QStringLiteral(
"PropertyIsEqualTo" );
2474 opText = QStringLiteral(
"PropertyIsNotEqualTo" );
2476 opText = QStringLiteral(
"PropertyIsLessThanOrEqualTo" );
2478 opText = QStringLiteral(
"PropertyIsGreaterThanOrEqualTo" );
2480 opText = QStringLiteral(
"PropertyIsLessThan" );
2482 opText = QStringLiteral(
"PropertyIsGreaterThan" );
2484 opText = QStringLiteral(
"PropertyIsLike" );
2486 opText = QStringLiteral(
"PropertyIsLike" );
2488 if ( opText.isEmpty() )
2492 return QDomElement();
2495 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2500 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2503 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2504 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2506 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2508 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2511 boElem.appendChild( leftElem );
2512 boElem.appendChild( rightElem );
2520 switch ( node->
value().type() )
2523 value = QString::number( node->
value().toInt() );
2525 case QVariant::LongLong:
2526 value = QString::number( node->
value().toLongLong() );
2528 case QVariant::Double:
2531 case QVariant::String:
2532 value = node->
value().toString();
2536 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2537 return QDomElement();
2540 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2541 litElem.appendChild( mDoc.createTextNode( value ) );
2548 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2549 if ( node->
tableName().isEmpty() || mLayerProperties.size() == 1 )
2550 propElem.appendChild( mDoc.createTextNode( node->
name() ) );
2553 QString tableName( mMapTableAliasToNames[node->
tableName()] );
2554 if ( mMapUnprefixedTypenameToPrefixedTypename.contains( tableName ) )
2555 tableName = mMapUnprefixedTypenameToPrefixedTypename[tableName];
2556 propElem.appendChild( mDoc.createTextNode( tableName +
"/" + node->
name() ) );
2563 if ( node->
list()->
list().size() == 1 )
2566 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2569 const auto constList = node->
list()->
list();
2573 if ( !mErrorMessage.isEmpty() )
2574 return QDomElement();
2576 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2577 eqElem.appendChild( leftNode.cloneNode() );
2578 eqElem.appendChild( listNode );
2580 orElem.appendChild( eqElem );
2585 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2586 notElem.appendChild( orElem );
2595 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsBetween" );
2597 QDomElement lowerBoundary = mDoc.createElement( mFilterPrefix +
":LowerBoundary" );
2599 elem.appendChild( lowerBoundary );
2600 QDomElement upperBoundary = mDoc.createElement( mFilterPrefix +
":UpperBoundary" );
2602 elem.appendChild( upperBoundary );
2606 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2607 notElem.appendChild( elem );
2614 static QString mapBinarySpatialToOgc(
const QString &name )
2616 QString nameCompare( name );
2617 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2618 nameCompare = name.mid( 3 );
2619 QStringList spatialOps;
2620 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
2621 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
2622 const auto constSpatialOps = spatialOps;
2623 for ( QString op : constSpatialOps )
2625 if ( nameCompare.compare( op, Qt::CaseInsensitive ) == 0 )
2631 static QString mapTernarySpatialToOgc(
const QString &name )
2633 QString nameCompare( name );
2634 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2635 nameCompare = name.mid( 3 );
2636 if ( nameCompare.compare( QLatin1String(
"DWithin" ), Qt::CaseInsensitive ) == 0 )
2637 return QStringLiteral(
"DWithin" );
2638 if ( nameCompare.compare( QLatin1String(
"Beyond" ), Qt::CaseInsensitive ) == 0 )
2639 return QStringLiteral(
"Beyond" );
2643 QString QgsOgcUtilsSQLStatementToFilter::getGeometryColumnSRSName(
const QgsSQLStatement::Node *node )
2651 const auto constMLayerProperties = mLayerProperties;
2654 if ( prop.mName.compare( mMapTableAliasToNames[col->
tableName()], Qt::CaseInsensitive ) == 0 &&
2655 prop.mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2657 return prop.mSRSName;
2661 if ( !mLayerProperties.empty() &&
2662 mLayerProperties.at( 0 ).mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2664 return mLayerProperties.at( 0 ).mSRSName;
2670 QList<QgsSQLStatement::Node *> args,
2671 bool lastArgIsSRSName,
2673 bool &axisInversion )
2675 srsName = mCurrentSRSName;
2676 axisInversion = mInvertAxisOrientation;
2678 if ( lastArgIsSRSName )
2683 mErrorMessage = QObject::tr(
"%1: Last argument must be string or integer literal" ).arg( mainNode->
name() );
2687 if ( lit->
value().type() == QVariant::Int )
2691 srsName =
"EPSG:" + QString::number( lit->
value().toInt() );
2695 srsName =
"urn:ogc:def:crs:EPSG::" + QString::number( lit->
value().toInt() );
2700 srsName = lit->
value().toString();
2701 if ( srsName.startsWith( QLatin1String(
"EPSG:" ), Qt::CaseInsensitive ) )
2707 if ( !srsName.isEmpty() )
2713 axisInversion = !axisInversion;
2723 if ( node->
name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 )
2725 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2726 if ( args.size() != 1 && args.size() != 2 )
2728 mErrorMessage = QObject::tr(
"Function %1 should have 1 or 2 arguments" ).arg( node->
name() );
2729 return QDomElement();
2735 mErrorMessage = QObject::tr(
"%1: First argument must be string literal" ).arg( node->
name() );
2736 return QDomElement();
2741 if ( ! processSRSName( node, args, args.size() == 2, srsName, axisInversion ) )
2743 return QDomElement();
2749 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2751 if ( geomElem.isNull() )
2753 mErrorMessage = QObject::tr(
"%1: invalid WKT" ).arg( node->
name() );
2754 return QDomElement();
2761 if ( node->
name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 )
2763 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2764 if ( args.size() != 4 && args.size() != 5 )
2766 mErrorMessage = QObject::tr(
"Function %1 should have 4 or 5 arguments" ).arg( node->
name() );
2767 return QDomElement();
2772 for (
int i = 0; i < 4; i++ )
2777 mErrorMessage = QObject::tr(
"%1: Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2778 return QDomElement();
2782 if ( lit->
value().type() == QVariant::Int )
2783 val = lit->
value().toInt();
2784 else if ( lit->
value().type() == QVariant::LongLong )
2785 val = lit->
value().toLongLong();
2786 else if ( lit->
value().type() == QVariant::Double )
2787 val = lit->
value().toDouble();
2790 mErrorMessage = QObject::tr(
"%1 Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2791 return QDomElement();
2805 if ( ! processSRSName( node, args, args.size() == 5, srsName, axisInversion ) )
2807 return QDomElement();
2818 if ( node->
name().compare( QLatin1String(
"ST_GeomFromGML" ), Qt::CaseInsensitive ) == 0 )
2820 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2821 if ( args.size() != 1 )
2823 mErrorMessage = QObject::tr(
"Function %1 should have 1 argument" ).arg( node->
name() );
2824 return QDomElement();
2830 mErrorMessage = QObject::tr(
"%1: Argument must be string literal" ).arg( node->
name() );
2831 return QDomElement();
2834 QDomDocument geomDoc;
2836 if ( !geomDoc.setContent( gml,
true ) )
2838 mErrorMessage = QObject::tr(
"ST_GeomFromGML: unable to parse XML" );
2839 return QDomElement();
2842 QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(), true );
2844 return geomNode.toElement();
2848 QString ogcName( mapBinarySpatialToOgc( node->
name() ) );
2849 if ( !ogcName.isEmpty() )
2851 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2852 if ( args.size() != 2 )
2854 mErrorMessage = QObject::tr(
"Function %1 should have 2 arguments" ).arg( node->
name() );
2855 return QDomElement();
2858 for (
int i = 0; i < 2; i ++ )
2861 ( static_cast<const QgsSQLStatement::NodeFunction *>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
2862 static_cast<const QgsSQLStatement::NodeFunction *>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
2864 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
2871 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + ogcName );
2872 const auto constArgs = args;
2876 if ( !mErrorMessage.isEmpty() )
2878 mCurrentSRSName.clear();
2879 return QDomElement();
2882 funcElem.appendChild( childElem );
2885 mCurrentSRSName.clear();
2889 ogcName = mapTernarySpatialToOgc( node->
name() );
2890 if ( !ogcName.isEmpty() )
2892 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2893 if ( args.size() != 3 )
2895 mErrorMessage = QObject::tr(
"Function %1 should have 3 arguments" ).arg( node->
name() );
2896 return QDomElement();
2899 for (
int i = 0; i < 2; i ++ )
2902 ( static_cast<const QgsSQLStatement::NodeFunction *>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
2903 static_cast<const QgsSQLStatement::NodeFunction *>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
2905 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
2910 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + node->
name().mid( 3 ) );
2911 for (
int i = 0; i < 2; i++ )
2914 if ( !mErrorMessage.isEmpty() )
2916 mCurrentSRSName.clear();
2917 return QDomElement();
2920 funcElem.appendChild( childElem );
2922 mCurrentSRSName.clear();
2927 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() );
2928 return QDomElement();
2931 if ( lit->
value().isNull() )
2933 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() );
2934 return QDomElement();
2937 QString unit( QStringLiteral(
"m" ) );
2938 switch ( lit->
value().type() )
2941 distance = QString::number( lit->
value().toInt() );
2943 case QVariant::LongLong:
2944 distance = QString::number( lit->
value().toLongLong() );
2946 case QVariant::Double:
2949 case QVariant::String:
2951 distance = lit->
value().toString();
2952 for (
int i = 0; i < distance.size(); i++ )
2954 if ( !( ( distance[i] >=
'0' && distance[i] <=
'9' ) || distance[i] ==
'-' || distance[i] ==
'.' || distance[i] ==
'e' || distance[i] ==
'E' ) )
2956 unit = distance.mid( i ).trimmed();
2957 distance = distance.mid( 0, i );
2965 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( lit->
value().type() );
2966 return QDomElement();
2969 QDomElement distanceElem = mDoc.createElement( mFilterPrefix +
":Distance" );
2971 distanceElem.setAttribute( QStringLiteral(
"uom" ), unit );
2973 distanceElem.setAttribute( QStringLiteral(
"unit" ), unit );
2974 distanceElem.appendChild( mDoc.createTextNode( distance ) );
2975 funcElem.appendChild( distanceElem );
2980 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
2981 funcElem.setAttribute( QStringLiteral(
"name" ), node->
name() );
2982 const auto constList = node->
args()->
list();
2986 if ( !mErrorMessage.isEmpty() )
2987 return QDomElement();
2989 funcElem.appendChild( childElem );
2995 const QString &leftTable )
3003 QList<QDomElement> listElem;
3005 for (
const QString &columnName : constUsingColumns )
3007 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
3008 QDomElement propElem1 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3009 propElem1.appendChild( mDoc.createTextNode( leftTable +
"/" + columnName ) );
3010 eqElem.appendChild( propElem1 );
3011 QDomElement propElem2 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3012 propElem2.appendChild( mDoc.createTextNode( node->
tableDef()->
name() +
"/" + columnName ) );
3013 eqElem.appendChild( propElem2 );
3014 listElem.append( eqElem );
3017 if ( listElem.size() == 1 )
3021 else if ( listElem.size() > 1 )
3023 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3024 const auto constListElem = listElem;
3025 for (
const QDomElement &elem : constListElem )
3027 andElem.appendChild( elem );
3032 return QDomElement();
3037 if ( node->
alias().isEmpty() )
3039 mMapTableAliasToNames[ node->
name()] = node->
name();
3043 mMapTableAliasToNames[ node->
alias()] = node->
name();
3049 QList<QDomElement> listElem;
3052 ( node->
tables().size() != 1 || !node->
joins().empty() ) )
3054 mErrorMessage = QObject::tr(
"Joins are only supported with WFS 2.0" );
3055 return QDomElement();
3059 const auto constTables = node->
tables();
3064 const auto constJoins = node->
joins();
3067 visit( join->tableDef() );
3071 QList< QgsSQLStatement::NodeTableDef *> nodeTables = node->
tables();
3072 QString leftTable = nodeTables.at( nodeTables.length() - 1 )->name();
3075 QDomElement joinElem =
toOgcFilter( join, leftTable );
3076 if ( !mErrorMessage.isEmpty() )
3077 return QDomElement();
3078 listElem.append( joinElem );
3079 leftTable = join->tableDef()->name();
3083 if ( node->
where() )
3086 if ( !mErrorMessage.isEmpty() )
3087 return QDomElement();
3088 listElem.append( whereElem );
3092 if ( listElem.size() == 1 )
3096 else if ( listElem.size() > 1 )
3098 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3099 const auto constListElem = listElem;
3100 for (
const QDomElement &elem : constListElem )
3102 andElem.appendChild( elem );
3107 return QDomElement();
3113 mPropertyName = QStringLiteral(
"PropertyName" );
3114 mPrefix = QStringLiteral(
"ogc" );
3118 mPropertyName = QStringLiteral(
"ValueReference" );
3119 mPrefix = QStringLiteral(
"fes" );
3125 if ( element.isNull() )
3129 if ( isBinaryOperator( element.tagName() ) )
3135 if ( isSpatialOperator( element.tagName() ) )
3141 if ( element.tagName() == QLatin1String(
"Not" ) )
3145 else if ( element.tagName() == QLatin1String(
"PropertyIsNull" ) )
3149 else if ( element.tagName() == QLatin1String(
"Literal" ) )
3153 else if ( element.tagName() == QLatin1String(
"Function" ) )
3157 else if ( element.tagName() == mPropertyName )
3161 else if ( element.tagName() == QLatin1String(
"PropertyIsBetween" ) )
3166 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() );
3172 if ( element.isNull() )
3175 int op = binaryOperatorFromTagName( element.tagName() );
3178 mErrorMessage = QObject::tr(
"'%1' binary operator not supported." ).arg( element.tagName() );
3182 if ( op ==
QgsExpressionNodeBinaryOperator::boLike && element.hasAttribute( QStringLiteral(
"matchCase" ) ) && element.attribute( QStringLiteral(
"matchCase" ) ) == QLatin1String(
"false" ) )
3187 QDomElement operandElem = element.firstChildElement();
3192 mErrorMessage = QObject::tr(
"invalid left operand for '%1' binary operator" ).arg( element.tagName() );
3196 std::unique_ptr<QgsExpressionNode> leftOp( expr->clone() );
3197 for ( operandElem = operandElem.nextSiblingElement(); !operandElem.isNull(); operandElem = operandElem.nextSiblingElement() )
3202 mErrorMessage = QObject::tr(
"invalid right operand for '%1' binary operator" ).arg( element.tagName() );
3209 if ( element.hasAttribute( QStringLiteral(
"wildCard" ) ) )
3211 wildCard = element.attribute( QStringLiteral(
"wildCard" ) );
3214 if ( element.hasAttribute( QStringLiteral(
"singleChar" ) ) )
3216 singleChar = element.attribute( QStringLiteral(
"singleChar" ) );
3218 QString escape = QStringLiteral(
"\\" );
3219 if ( element.hasAttribute( QStringLiteral(
"escape" ) ) )
3221 escape = element.attribute( QStringLiteral(
"escape" ) );
3223 if ( element.hasAttribute( QStringLiteral(
"escapeChar" ) ) )
3225 escape = element.attribute( QStringLiteral(
"escapeChar" ) );
3229 if ( !wildCard.isEmpty() && wildCard != QLatin1String(
"%" ) )
3231 oprValue.replace(
'%', QLatin1String(
"\\%" ) );
3232 if ( oprValue.startsWith( wildCard ) )
3234 oprValue.replace( 0, 1, QStringLiteral(
"%" ) );
3236 QRegExp rx(
"[^" + QRegExp::escape( escape ) +
"](" + QRegExp::escape( wildCard ) +
")" );
3238 while ( ( pos = rx.indexIn( oprValue, pos ) ) != -1 )
3240 oprValue.replace( pos + 1, 1, QStringLiteral(
"%" ) );
3243 oprValue.replace( escape + wildCard, wildCard );
3245 if ( !singleChar.isEmpty() && singleChar != QLatin1String(
"_" ) )
3247 oprValue.replace(
'_', QLatin1String(
"\\_" ) );
3248 if ( oprValue.startsWith( singleChar ) )
3250 oprValue.replace( 0, 1, QStringLiteral(
"_" ) );
3252 QRegExp rx(
"[^" + QRegExp::escape( escape ) +
"](" + QRegExp::escape( singleChar ) +
")" );
3254 while ( ( pos = rx.indexIn( oprValue, pos ) ) != -1 )
3256 oprValue.replace( pos + 1, 1, QStringLiteral(
"_" ) );
3259 oprValue.replace( escape + singleChar, singleChar );
3261 if ( !escape.isEmpty() && escape != QLatin1String(
"\\" ) )
3263 oprValue.replace( escape + escape, escape );
3268 expr.reset(
new QgsExpressionNodeBinaryOperator( static_cast< QgsExpressionNodeBinaryOperator::BinaryOperator >( op ), expr.release(), opRight.release() ) );
3271 if ( expr == leftOp )
3273 mErrorMessage = QObject::tr(
"only one operand for '%1' binary operator" ).arg( element.tagName() );
3287 QDomElement childElem = element.firstChildElement();
3289 while ( !childElem.isNull() && gml2Str.isEmpty() )
3291 if ( childElem.tagName() != mPropertyName )
3293 QTextStream gml2Stream( &gml2Str );
3294 childElem.save( gml2Stream, 0 );
3296 childElem = childElem.nextSiblingElement();
3298 if ( !gml2Str.isEmpty() )
3304 mErrorMessage = QObject::tr(
"No OGC Geometry found" );
3317 if ( element.isNull() || element.tagName() != mPropertyName )
3319 mErrorMessage = QObject::tr(
"%1:PropertyName expected, got %2" ).arg( mPrefix, element.tagName() );
3328 if ( element.isNull() || element.tagName() != QLatin1String(
"Literal" ) )
3330 mErrorMessage = QObject::tr(
"%1:Literal expected, got %2" ).arg( mPrefix, element.tagName() );
3334 std::unique_ptr<QgsExpressionNode> root;
3337 QDomNode childNode = element.firstChild();
3338 while ( !childNode.isNull() )
3340 std::unique_ptr<QgsExpressionNode> operand;
3342 if ( childNode.nodeType() == QDomNode::ElementNode )
3345 const QDomElement operandElem = childNode.toElement();
3349 mErrorMessage = QObject::tr(
"'%1' is an invalid or not supported content for %2:Literal" ).arg( operandElem.tagName(), mPrefix );
3356 QVariant value = childNode.nodeValue();
3358 bool converted =
false;
3363 QDomElement propertyNameElement = element.previousSiblingElement( mPropertyName );
3364 if ( propertyNameElement.isNull() || propertyNameElement.tagName() != mPropertyName )
3366 propertyNameElement = element.nextSiblingElement( mPropertyName );
3368 if ( !propertyNameElement.isNull() || propertyNameElement.tagName() == mPropertyName )
3370 const int fieldIndex = mLayer->
fields().
indexOf( propertyNameElement.firstChild().nodeValue() );
3371 if ( fieldIndex != -1 )
3384 const double d = value.toDouble( &ok );
3397 root = std::move( operand );
3404 childNode = childNode.nextSibling();
3408 return root.release();
3415 if ( element.tagName() != QLatin1String(
"Not" ) )
3418 const QDomElement operandElem = element.firstChildElement();
3422 mErrorMessage = QObject::tr(
"invalid operand for '%1' unary operator" ).arg( element.tagName() );
3432 if ( element.tagName() != QLatin1String(
"PropertyIsNull" ) )
3437 const QDomElement operandElem = element.firstChildElement();
3448 if ( element.isNull() || element.tagName() != QLatin1String(
"Function" ) )
3450 mErrorMessage = QObject::tr(
"%1:Function expected, got %2" ).arg( mPrefix, element.tagName() );
3458 if ( element.attribute( QStringLiteral(
"name" ) ) != funcDef->
name() )
3463 QDomElement operandElem = element.firstChildElement();
3464 while ( !operandElem.isNull() )
3471 args->append( op.release() );
3473 operandElem = operandElem.nextSiblingElement();
3485 std::unique_ptr<QgsExpressionNode> operand;
3486 std::unique_ptr<QgsExpressionNode> lowerBound;
3487 std::unique_ptr<QgsExpressionNode> upperBound;
3489 QDomElement operandElem = element.firstChildElement();
3490 while ( !operandElem.isNull() )
3492 if ( operandElem.tagName() == QLatin1String(
"LowerBoundary" ) )
3494 QDomElement lowerBoundElem = operandElem.firstChildElement();
3497 else if ( operandElem.tagName() == QLatin1String(
"UpperBoundary" ) )
3499 QDomElement upperBoundElem = operandElem.firstChildElement();
3508 if ( operand && lowerBound && upperBound )
3511 operandElem = operandElem.nextSiblingElement();
3514 if ( !operand || !lowerBound || !upperBound )
3516 mErrorMessage = QObject::tr(
"missing some required sub-elements in %1:PropertyIsBetween" ).arg( mPrefix );
3527 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, =, +, ...)
QMap< QString, QString > QgsStringMap
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.
Q_GLOBAL_STATIC_WITH_ARGS(IntMap, BINARY_OPERATORS_TAG_NAMES_MAP,({ { QLatin1String("Or"), QgsExpressionNodeBinaryOperator::boOr }, { QLatin1String("And"), QgsExpressionNodeBinaryOperator::boAnd }, { QLatin1String("PropertyIsEqualTo"), QgsExpressionNodeBinaryOperator::boEQ }, { QLatin1String("PropertyIsNotEqualTo"), QgsExpressionNodeBinaryOperator::boNE }, { QLatin1String("PropertyIsLessThanOrEqualTo"), QgsExpressionNodeBinaryOperator::boLE }, { QLatin1String("PropertyIsGreaterThanOrEqualTo"), QgsExpressionNodeBinaryOperator::boGE }, { QLatin1String("PropertyIsLessThan"), QgsExpressionNodeBinaryOperator::boLT }, { QLatin1String("PropertyIsGreaterThan"), QgsExpressionNodeBinaryOperator::boGT }, { QLatin1String("PropertyIsLike"), QgsExpressionNodeBinaryOperator::boLike }, { QLatin1String("Add"), QgsExpressionNodeBinaryOperator::boPlus }, { QLatin1String("Sub"), QgsExpressionNodeBinaryOperator::boMinus }, { QLatin1String("Mul"), QgsExpressionNodeBinaryOperator::boMul }, { QLatin1String("Div"), QgsExpressionNodeBinaryOperator::boDiv }, })) static int binaryOperatorFromTagName(const QString &tagName)
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).
QMap< QString, int > IntMap
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.