30 #include <QStringList>
31 #include <QTextStream>
35 #include <netinet/in.h>
41 #define GML_NAMESPACE QStringLiteral( "http://www.opengis.net/gml" )
42 #define GML32_NAMESPACE QStringLiteral( "http://www.opengis.net/gml/3.2" )
43 #define OGC_NAMESPACE QStringLiteral( "http://www.opengis.net/ogc" )
44 #define FES_NAMESPACE QStringLiteral( "http://www.opengis.net/fes/2.0" )
50 const QString &srsName,
51 bool honourAxisOrientation,
52 bool invertAxisOrientation )
55 , mGMLVersion( gmlVersion )
56 , mFilterVersion( filterVersion )
59 , mInvertAxisOrientation( invertAxisOrientation )
60 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
61 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
65 if ( !mSrsName.isEmpty() )
71 mInvertAxisOrientation = !mInvertAxisOrientation;
78 QDomElement geometryTypeElement = geometryNode.toElement();
79 QString geomType = geometryTypeElement.tagName();
82 if ( !( geomType == QLatin1String(
"Point" ) || geomType == QLatin1String(
"LineString" ) || geomType == QLatin1String(
"Polygon" ) ||
83 geomType == QLatin1String(
"MultiPoint" ) || geomType == QLatin1String(
"MultiLineString" ) || geomType == QLatin1String(
"MultiPolygon" ) ||
84 geomType == QLatin1String(
"Box" ) || geomType == QLatin1String(
"Envelope" ) ) )
86 QDomNode geometryChild = geometryNode.firstChild();
87 if ( geometryChild.isNull() )
91 geometryTypeElement = geometryChild.toElement();
92 geomType = geometryTypeElement.tagName();
95 if ( !( geomType == QLatin1String(
"Point" ) || geomType == QLatin1String(
"LineString" ) || geomType == QLatin1String(
"Polygon" ) ||
96 geomType == QLatin1String(
"MultiPoint" ) || geomType == QLatin1String(
"MultiLineString" ) || geomType == QLatin1String(
"MultiPolygon" ) ||
97 geomType == QLatin1String(
"Box" ) || geomType == QLatin1String(
"Envelope" ) ) )
100 if ( geomType == QLatin1String(
"Point" ) )
102 geometry = geometryFromGMLPoint( geometryTypeElement );
104 else if ( geomType == QLatin1String(
"LineString" ) )
106 geometry = geometryFromGMLLineString( geometryTypeElement );
108 else if ( geomType == QLatin1String(
"Polygon" ) )
110 geometry = geometryFromGMLPolygon( geometryTypeElement );
112 else if ( geomType == QLatin1String(
"MultiPoint" ) )
114 geometry = geometryFromGMLMultiPoint( geometryTypeElement );
116 else if ( geomType == QLatin1String(
"MultiLineString" ) )
118 geometry = geometryFromGMLMultiLineString( geometryTypeElement );
120 else if ( geomType == QLatin1String(
"MultiPolygon" ) )
122 geometry = geometryFromGMLMultiPolygon( geometryTypeElement );
124 else if ( geomType == QLatin1String(
"Box" ) )
128 else if ( geomType == QLatin1String(
"Envelope" ) )
142 if ( geometryTypeElement.hasAttribute( QStringLiteral(
"srsName" ) ) )
144 geomSrs.
createFromString( geometryTypeElement.attribute( QStringLiteral(
"srsName" ) ) );
151 if ( result != QgsGeometry::OperationResult::Success )
153 QgsDebugMsgLevel( QStringLiteral(
"Error transforming geometry: %1" ).arg( result ), 2 );
170 QString xml = QStringLiteral(
"<tmp xmlns=\"%1\" xmlns:gml=\"%1\">%2</tmp>" ).arg(
GML_NAMESPACE, xmlString );
172 if ( !doc.setContent( xml,
true ) )
175 return geometryFromGML( doc.documentElement().firstChildElement(), context );
179 QgsGeometry QgsOgcUtils::geometryFromGMLPoint(
const QDomElement &geometryElement )
183 QDomNodeList coordList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
184 if ( !coordList.isEmpty() )
186 QDomElement coordElement = coordList.at( 0 ).toElement();
187 if ( readGMLCoordinates( pointCoordinate, coordElement ) != 0 )
194 QDomNodeList posList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pos" ) );
195 if ( posList.size() < 1 )
199 QDomElement posElement = posList.at( 0 ).toElement();
200 if ( readGMLPositions( pointCoordinate, posElement ) != 0 )
206 if ( pointCoordinate.empty() )
211 QgsPolylineXY::const_iterator point_it = pointCoordinate.constBegin();
212 char e = htonl( 1 ) != 1;
213 double x = point_it->x();
214 double y = point_it->y();
215 int size = 1 +
sizeof( int ) + 2 *
sizeof(
double );
218 unsigned char *wkb =
new unsigned char[size];
221 memcpy( &( wkb )[wkbPosition], &e, 1 );
223 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
224 wkbPosition +=
sizeof( int );
225 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
226 wkbPosition +=
sizeof( double );
227 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
234 QgsGeometry QgsOgcUtils::geometryFromGMLLineString(
const QDomElement &geometryElement )
238 QDomNodeList coordList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
239 if ( !coordList.isEmpty() )
241 QDomElement coordElement = coordList.at( 0 ).toElement();
242 if ( readGMLCoordinates( lineCoordinates, coordElement ) != 0 )
249 QDomNodeList posList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
250 if ( posList.size() < 1 )
254 QDomElement posElement = posList.at( 0 ).toElement();
255 if ( readGMLPositions( lineCoordinates, posElement ) != 0 )
261 char e = htonl( 1 ) != 1;
262 int size = 1 + 2 *
sizeof( int ) + lineCoordinates.size() * 2 *
sizeof( double );
265 unsigned char *wkb =
new unsigned char[size];
269 int nPoints = lineCoordinates.size();
272 memcpy( &( wkb )[wkbPosition], &e, 1 );
274 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
275 wkbPosition +=
sizeof( int );
276 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
277 wkbPosition +=
sizeof( int );
279 QgsPolylineXY::const_iterator iter;
280 for ( iter = lineCoordinates.constBegin(); iter != lineCoordinates.constEnd(); ++iter )
284 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
285 wkbPosition +=
sizeof( double );
286 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
287 wkbPosition +=
sizeof( double );
295 QgsGeometry QgsOgcUtils::geometryFromGMLPolygon(
const QDomElement &geometryElement )
302 QDomNodeList outerBoundaryList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"outerBoundaryIs" ) );
303 if ( !outerBoundaryList.isEmpty() )
305 QDomElement coordinatesElement = outerBoundaryList.at( 0 ).firstChild().firstChild().toElement();
306 if ( coordinatesElement.isNull() )
310 if ( readGMLCoordinates( exteriorPointList, coordinatesElement ) != 0 )
314 ringCoordinates.push_back( exteriorPointList );
317 QDomNodeList innerBoundaryList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"innerBoundaryIs" ) );
318 for (
int i = 0; i < innerBoundaryList.size(); ++i )
321 coordinatesElement = innerBoundaryList.at( i ).firstChild().firstChild().toElement();
322 if ( coordinatesElement.isNull() )
326 if ( readGMLCoordinates( interiorPointList, coordinatesElement ) != 0 )
330 ringCoordinates.push_back( interiorPointList );
336 QDomNodeList exteriorList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"exterior" ) );
337 if ( exteriorList.size() < 1 )
341 QDomElement posElement = exteriorList.at( 0 ).firstChild().firstChild().toElement();
342 if ( posElement.isNull() )
346 if ( readGMLPositions( exteriorPointList, posElement ) != 0 )
350 ringCoordinates.push_back( exteriorPointList );
353 QDomNodeList interiorList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"interior" ) );
354 for (
int i = 0; i < interiorList.size(); ++i )
357 QDomElement posElement = interiorList.at( i ).firstChild().firstChild().toElement();
358 if ( posElement.isNull() )
363 if ( readGMLPositions( interiorPointList, posElement ) )
367 ringCoordinates.push_back( interiorPointList );
372 int nrings = ringCoordinates.size();
377 for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
379 npoints += it->size();
381 int size = 1 + 2 *
sizeof( int ) + nrings *
sizeof(
int ) + 2 * npoints *
sizeof( double );
384 unsigned char *wkb =
new unsigned char[size];
387 char e = htonl( 1 ) != 1;
389 int nPointsInRing = 0;
393 memcpy( &( wkb )[wkbPosition], &e, 1 );
395 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
396 wkbPosition +=
sizeof( int );
397 memcpy( &( wkb )[wkbPosition], &nrings,
sizeof(
int ) );
398 wkbPosition +=
sizeof( int );
399 for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
401 nPointsInRing = it->size();
402 memcpy( &( wkb )[wkbPosition], &nPointsInRing,
sizeof(
int ) );
403 wkbPosition +=
sizeof( int );
405 QgsPolylineXY::const_iterator iter;
406 for ( iter = it->begin(); iter != it->end(); ++iter )
411 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
412 wkbPosition +=
sizeof( double );
413 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
414 wkbPosition +=
sizeof( double );
423 QgsGeometry QgsOgcUtils::geometryFromGMLMultiPoint(
const QDomElement &geometryElement )
427 QDomNodeList pointMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pointMember" ) );
428 if ( pointMemberList.size() < 1 )
432 QDomNodeList pointNodeList;
434 QDomNodeList coordinatesList;
435 QDomNodeList posList;
436 for (
int i = 0; i < pointMemberList.size(); ++i )
439 pointNodeList = pointMemberList.at( i ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"Point" ) );
440 if ( pointNodeList.size() < 1 )
445 coordinatesList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
446 if ( !coordinatesList.isEmpty() )
448 currentPoint.clear();
449 if ( readGMLCoordinates( currentPoint, coordinatesList.at( 0 ).toElement() ) != 0 )
453 if ( currentPoint.empty() )
457 pointList.push_back( ( *currentPoint.begin() ) );
463 posList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pos" ) );
464 if ( posList.size() < 1 )
468 currentPoint.clear();
469 if ( readGMLPositions( currentPoint, posList.at( 0 ).toElement() ) != 0 )
473 if ( currentPoint.empty() )
477 pointList.push_back( ( *currentPoint.begin() ) );
481 int nPoints = pointList.size();
486 int size = 1 + 2 *
sizeof( int ) + pointList.size() * ( 2 *
sizeof( double ) + 1 +
sizeof(
int ) );
489 unsigned char *wkb =
new unsigned char[size];
492 char e = htonl( 1 ) != 1;
495 memcpy( &( wkb )[wkbPosition], &e, 1 );
497 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
498 wkbPosition +=
sizeof( int );
499 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
500 wkbPosition +=
sizeof( int );
502 for ( QgsPolylineXY::const_iterator it = pointList.constBegin(); it != pointList.constEnd(); ++it )
504 memcpy( &( wkb )[wkbPosition], &e, 1 );
506 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
507 wkbPosition +=
sizeof( int );
509 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
510 wkbPosition +=
sizeof( double );
512 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
513 wkbPosition +=
sizeof( double );
521 QgsGeometry QgsOgcUtils::geometryFromGMLMultiLineString(
const QDomElement &geometryElement )
532 QList< QgsPolylineXY > lineCoordinates;
533 QDomElement currentLineStringElement;
534 QDomNodeList currentCoordList;
535 QDomNodeList currentPosList;
537 QDomNodeList lineStringMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"lineStringMember" ) );
538 if ( !lineStringMemberList.isEmpty() )
540 for (
int i = 0; i < lineStringMemberList.size(); ++i )
542 QDomNodeList lineStringNodeList = lineStringMemberList.at( i ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LineString" ) );
543 if ( lineStringNodeList.size() < 1 )
547 currentLineStringElement = lineStringNodeList.at( 0 ).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 );
560 currentPosList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
561 if ( currentPosList.size() < 1 )
566 if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
570 lineCoordinates.push_back( currentPointList );
576 QDomNodeList lineStringList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LineString" ) );
577 if ( !lineStringList.isEmpty() )
579 for (
int i = 0; i < lineStringList.size(); ++i )
581 currentLineStringElement = lineStringList.at( i ).toElement();
582 currentCoordList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
583 if ( !currentCoordList.isEmpty() )
586 if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
590 lineCoordinates.push_back( currentPointList );
595 currentPosList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
596 if ( currentPosList.size() < 1 )
601 if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
605 lineCoordinates.push_back( currentPointList );
615 int nLines = lineCoordinates.size();
620 int size = ( lineCoordinates.size() + 1 ) * ( 1 + 2 *
sizeof(
int ) );
621 for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
623 size += it->size() * 2 *
sizeof( double );
627 unsigned char *wkb =
new unsigned char[size];
630 char e = htonl( 1 ) != 1;
634 memcpy( &( wkb )[wkbPosition], &e, 1 );
636 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
637 wkbPosition +=
sizeof( int );
638 memcpy( &( wkb )[wkbPosition], &nLines,
sizeof(
int ) );
639 wkbPosition +=
sizeof( int );
641 for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
643 memcpy( &( wkb )[wkbPosition], &e, 1 );
645 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
646 wkbPosition +=
sizeof( int );
647 nPoints = it->size();
648 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
649 wkbPosition +=
sizeof( int );
650 for ( QgsPolylineXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
655 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
656 wkbPosition +=
sizeof( double );
657 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
658 wkbPosition +=
sizeof( double );
667 QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon(
const QDomElement &geometryElement )
671 QDomElement currentPolygonMemberElement;
672 QDomNodeList polygonList;
673 QDomElement currentPolygonElement;
675 QDomNodeList outerBoundaryList;
676 QDomElement currentOuterBoundaryElement;
677 QDomNodeList innerBoundaryList;
678 QDomElement currentInnerBoundaryElement;
680 QDomNodeList exteriorList;
681 QDomElement currentExteriorElement;
682 QDomElement currentInteriorElement;
683 QDomNodeList interiorList;
685 QDomNodeList linearRingNodeList;
686 QDomElement currentLinearRingElement;
688 QDomNodeList currentCoordinateList;
689 QDomNodeList currentPosList;
691 QDomNodeList polygonMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"polygonMember" ) );
693 for (
int i = 0; i < polygonMemberList.size(); ++i )
695 currentPolygonList.resize( 0 );
696 currentPolygonMemberElement = polygonMemberList.at( i ).toElement();
697 polygonList = currentPolygonMemberElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"Polygon" ) );
698 if ( polygonList.size() < 1 )
702 currentPolygonElement = polygonList.at( 0 ).toElement();
705 outerBoundaryList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"outerBoundaryIs" ) );
706 if ( !outerBoundaryList.isEmpty() )
708 currentOuterBoundaryElement = outerBoundaryList.at( 0 ).toElement();
711 linearRingNodeList = currentOuterBoundaryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
712 if ( linearRingNodeList.size() < 1 )
716 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
717 currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
718 if ( currentCoordinateList.size() < 1 )
722 if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
726 currentPolygonList.push_back( ringCoordinates );
729 QDomNodeList innerBoundaryList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"innerBoundaryIs" ) );
730 for (
int j = 0; j < innerBoundaryList.size(); ++j )
733 currentInnerBoundaryElement = innerBoundaryList.at( j ).toElement();
734 linearRingNodeList = currentInnerBoundaryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
735 if ( linearRingNodeList.size() < 1 )
739 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
740 currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
741 if ( currentCoordinateList.size() < 1 )
745 if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
749 currentPolygonList.push_back( ringCoordinates );
755 exteriorList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"exterior" ) );
756 if ( exteriorList.size() < 1 )
761 currentExteriorElement = exteriorList.at( 0 ).toElement();
764 linearRingNodeList = currentExteriorElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
765 if ( linearRingNodeList.size() < 1 )
769 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
770 currentPosList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
771 if ( currentPosList.size() < 1 )
775 if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
779 currentPolygonList.push_back( ringPositions );
782 QDomNodeList interiorList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"interior" ) );
783 for (
int j = 0; j < interiorList.size(); ++j )
786 currentInteriorElement = interiorList.at( j ).toElement();
787 linearRingNodeList = currentInteriorElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
788 if ( linearRingNodeList.size() < 1 )
792 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
793 currentPosList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
794 if ( currentPosList.size() < 1 )
798 if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
802 currentPolygonList.push_back( ringPositions );
805 multiPolygonPoints.push_back( currentPolygonList );
808 int nPolygons = multiPolygonPoints.size();
812 int size = 1 + 2 *
sizeof( int );
814 for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
816 size += 1 + 2 *
sizeof( int );
817 for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
819 size +=
sizeof( int ) + 2 * iter->size() *
sizeof( double );
824 unsigned char *wkb =
new unsigned char[size];
826 char e = htonl( 1 ) != 1;
833 memcpy( &( wkb )[wkbPosition], &e, 1 );
835 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
836 wkbPosition +=
sizeof( int );
837 memcpy( &( wkb )[wkbPosition], &nPolygons,
sizeof(
int ) );
838 wkbPosition +=
sizeof( int );
842 for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
844 memcpy( &( wkb )[wkbPosition], &e, 1 );
846 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
847 wkbPosition +=
sizeof( int );
849 memcpy( &( wkb )[wkbPosition], &nRings,
sizeof(
int ) );
850 wkbPosition +=
sizeof( int );
851 for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
853 nPointsInRing = iter->size();
854 memcpy( &( wkb )[wkbPosition], &nPointsInRing,
sizeof(
int ) );
855 wkbPosition +=
sizeof( int );
856 for ( QgsPolylineXY::const_iterator iterator = iter->begin(); iterator != iter->end(); ++iterator )
860 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
861 wkbPosition +=
sizeof( double );
862 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
863 wkbPosition +=
sizeof( double );
873 bool QgsOgcUtils::readGMLCoordinates(
QgsPolylineXY &coords,
const QDomElement &elem )
875 QString coordSeparator = QStringLiteral(
"," );
876 QString tupelSeparator = QStringLiteral(
" " );
881 if ( elem.hasAttribute( QStringLiteral(
"cs" ) ) )
883 coordSeparator = elem.attribute( QStringLiteral(
"cs" ) );
885 if ( elem.hasAttribute( QStringLiteral(
"ts" ) ) )
887 tupelSeparator = elem.attribute( QStringLiteral(
"ts" ) );
890 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
891 QStringList tupels = elem.text().split( tupelSeparator, QString::SkipEmptyParts );
893 QStringList tupels = elem.text().split( tupelSeparator, Qt::SkipEmptyParts );
895 QStringList tuple_coords;
897 bool conversionSuccess;
899 QStringList::const_iterator it;
900 for ( it = tupels.constBegin(); it != tupels.constEnd(); ++it )
902 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
903 tuple_coords = ( *it ).split( coordSeparator, QString::SkipEmptyParts );
905 tuple_coords = ( *it ).split( coordSeparator, Qt::SkipEmptyParts );
907 if ( tuple_coords.size() < 2 )
911 x = tuple_coords.at( 0 ).toDouble( &conversionSuccess );
912 if ( !conversionSuccess )
916 y = tuple_coords.at( 1 ).toDouble( &conversionSuccess );
917 if ( !conversionSuccess )
930 QDomElement boxElem = boxNode.toElement();
931 if ( boxElem.tagName() != QLatin1String(
"Box" ) )
934 QDomElement bElem = boxElem.firstChild().toElement();
935 QString coordSeparator = QStringLiteral(
"," );
936 QString tupelSeparator = QStringLiteral(
" " );
937 if ( bElem.hasAttribute( QStringLiteral(
"cs" ) ) )
939 coordSeparator = bElem.attribute( QStringLiteral(
"cs" ) );
941 if ( bElem.hasAttribute( QStringLiteral(
"ts" ) ) )
943 tupelSeparator = bElem.attribute( QStringLiteral(
"ts" ) );
946 QString bString = bElem.text();
947 bool ok1, ok2, ok3, ok4;
948 double xmin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 0, 0 ).toDouble( &ok1 );
949 double ymin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 1, 1 ).toDouble( &ok2 );
950 double xmax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 0, 0 ).toDouble( &ok3 );
951 double ymax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 1, 1 ).toDouble( &ok4 );
953 if ( ok1 && ok2 && ok3 && ok4 )
962 bool QgsOgcUtils::readGMLPositions(
QgsPolylineXY &coords,
const QDomElement &elem )
966 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
967 QStringList pos = elem.text().split(
' ', QString::SkipEmptyParts );
969 QStringList pos = elem.text().split(
' ', Qt::SkipEmptyParts );
972 bool conversionSuccess;
973 int posSize = pos.size();
975 int srsDimension = 2;
976 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
978 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
979 if ( !conversionSuccess )
984 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
986 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
987 if ( !conversionSuccess )
993 for (
int i = 0; i < posSize / srsDimension; i++ )
995 x = pos.at( i * srsDimension ).toDouble( &conversionSuccess );
996 if ( !conversionSuccess )
1000 y = pos.at( i * srsDimension + 1 ).toDouble( &conversionSuccess );
1001 if ( !conversionSuccess )
1015 QDomElement envelopeElem = envelopeNode.toElement();
1016 if ( envelopeElem.tagName() != QLatin1String(
"Envelope" ) )
1019 QDomNodeList lowerCornerList = envelopeElem.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"lowerCorner" ) );
1020 if ( lowerCornerList.size() < 1 )
1023 QDomNodeList upperCornerList = envelopeElem.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"upperCorner" ) );
1024 if ( upperCornerList.size() < 1 )
1027 bool conversionSuccess;
1028 int srsDimension = 2;
1030 QDomElement elem = lowerCornerList.at( 0 ).toElement();
1031 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
1033 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
1034 if ( !conversionSuccess )
1039 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1041 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1042 if ( !conversionSuccess )
1047 QString bString = elem.text();
1049 double xmin = bString.section(
' ', 0, 0 ).toDouble( &conversionSuccess );
1050 if ( !conversionSuccess )
1052 double ymin = bString.section(
' ', 1, 1 ).toDouble( &conversionSuccess );
1053 if ( !conversionSuccess )
1056 elem = upperCornerList.at( 0 ).toElement();
1057 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
1059 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
1060 if ( !conversionSuccess )
1065 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1067 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1068 if ( !conversionSuccess )
1074 Q_UNUSED( srsDimension )
1076 bString = elem.text();
1077 double xmax = bString.section(
' ', 0, 0 ).toDouble( &conversionSuccess );
1078 if ( !conversionSuccess )
1080 double ymax = bString.section(
' ', 1, 1 ).toDouble( &conversionSuccess );
1081 if ( !conversionSuccess )
1096 const QString &srsName,
1097 bool invertAxisOrientation,
1102 return QDomElement();
1105 QDomElement boxElem = doc.createElement( QStringLiteral(
"gml:Box" ) );
1106 if ( !srsName.isEmpty() )
1108 boxElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1110 QDomElement coordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1111 coordElem.setAttribute( QStringLiteral(
"cs" ), QStringLiteral(
"," ) );
1112 coordElem.setAttribute( QStringLiteral(
"ts" ), QStringLiteral(
" " ) );
1114 QString coordString;
1123 QDomText coordText = doc.createTextNode( coordString );
1124 coordElem.appendChild( coordText );
1125 boxElem.appendChild( coordElem );
1136 const QString &srsName,
1137 bool invertAxisOrientation,
1142 return QDomElement();
1145 QDomElement envElem = doc.createElement( QStringLiteral(
"gml:Envelope" ) );
1146 if ( !srsName.isEmpty() )
1148 envElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1152 QDomElement lowerCornerElem = doc.createElement( QStringLiteral(
"gml:lowerCorner" ) );
1156 QDomText lowerCornerText = doc.createTextNode( posList );
1157 lowerCornerElem.appendChild( lowerCornerText );
1158 envElem.appendChild( lowerCornerElem );
1160 QDomElement upperCornerElem = doc.createElement( QStringLiteral(
"gml:upperCorner" ) );
1164 QDomText upperCornerText = doc.createTextNode( posList );
1165 upperCornerElem.appendChild( upperCornerText );
1166 envElem.appendChild( upperCornerElem );
1179 const QString &srsName,
1180 bool invertAxisOrientation,
1181 const QString &gmlIdBase,
1185 return QDomElement();
1188 QString cs = QStringLiteral(
"," );
1190 QString ts = QStringLiteral(
" " );
1192 QDomElement baseCoordElem;
1194 bool hasZValue =
false;
1196 QByteArray wkb( geometry.
asWkb() );
1206 return QDomElement();
1217 baseCoordElem = doc.createElement( QStringLiteral(
"gml:pos" ) );
1220 baseCoordElem = doc.createElement( QStringLiteral(
"gml:posList" ) );
1223 baseCoordElem.setAttribute( QStringLiteral(
"srsDimension" ), QStringLiteral(
"2" ) );
1228 baseCoordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1229 baseCoordElem.setAttribute( QStringLiteral(
"cs" ), cs );
1230 baseCoordElem.setAttribute( QStringLiteral(
"ts" ), ts );
1240 QDomElement pointElem = doc.createElement( QStringLiteral(
"gml:Point" ) );
1241 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1242 pointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1243 if ( !srsName.isEmpty() )
1244 pointElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1245 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1249 if ( invertAxisOrientation )
1255 coordElem.appendChild( coordText );
1256 pointElem.appendChild( coordElem );
1265 QDomElement multiPointElem = doc.createElement( QStringLiteral(
"gml:MultiPoint" ) );
1266 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1267 multiPointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1268 if ( !srsName.isEmpty() )
1269 multiPointElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1274 for (
int idx = 0; idx < nPoints; ++idx )
1276 QDomElement pointMemberElem = doc.createElement( QStringLiteral(
"gml:pointMember" ) );
1277 QDomElement pointElem = doc.createElement( QStringLiteral(
"gml:Point" ) );
1278 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1279 pointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( idx + 1 ) );
1280 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1285 if ( invertAxisOrientation )
1291 coordElem.appendChild( coordText );
1292 pointElem.appendChild( coordElem );
1296 wkbPtr +=
sizeof( double );
1298 pointMemberElem.appendChild( pointElem );
1299 multiPointElem.appendChild( pointMemberElem );
1301 return multiPointElem;
1309 QDomElement lineStringElem = doc.createElement( QStringLiteral(
"gml:LineString" ) );
1310 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1311 lineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1312 if ( !srsName.isEmpty() )
1313 lineStringElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1319 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1320 QString coordString;
1321 for (
int idx = 0; idx < nPoints; ++idx )
1329 if ( invertAxisOrientation )
1337 wkbPtr +=
sizeof( double );
1340 QDomText coordText = doc.createTextNode( coordString );
1341 coordElem.appendChild( coordText );
1342 lineStringElem.appendChild( coordElem );
1343 return lineStringElem;
1351 QDomElement multiLineStringElem = doc.createElement( QStringLiteral(
"gml:MultiLineString" ) );
1352 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1353 multiLineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1354 if ( !srsName.isEmpty() )
1355 multiLineStringElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1360 for (
int jdx = 0; jdx < nLines; jdx++ )
1362 QDomElement lineStringMemberElem = doc.createElement( QStringLiteral(
"gml:lineStringMember" ) );
1363 QDomElement lineStringElem = doc.createElement( QStringLiteral(
"gml:LineString" ) );
1364 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1365 lineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( jdx + 1 ) );
1372 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1373 QString coordString;
1374 for (
int idx = 0; idx < nPoints; idx++ )
1382 if ( invertAxisOrientation )
1391 wkbPtr +=
sizeof( double );
1394 QDomText coordText = doc.createTextNode( coordString );
1395 coordElem.appendChild( coordText );
1396 lineStringElem.appendChild( coordElem );
1397 lineStringMemberElem.appendChild( lineStringElem );
1398 multiLineStringElem.appendChild( lineStringMemberElem );
1400 return multiLineStringElem;
1408 QDomElement polygonElem = doc.createElement( QStringLiteral(
"gml:Polygon" ) );
1409 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1410 polygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1411 if ( !srsName.isEmpty() )
1412 polygonElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1418 if ( numRings == 0 )
1419 return QDomElement();
1421 int *ringNumPoints =
new int[numRings];
1423 for (
int idx = 0; idx < numRings; idx++ )
1425 QString boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:outerBoundaryIs" :
"gml:exterior";
1428 boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:innerBoundaryIs" :
"gml:interior";
1430 QDomElement boundaryElem = doc.createElement( boundaryName );
1431 QDomElement ringElem = doc.createElement( QStringLiteral(
"gml:LinearRing" ) );
1435 ringNumPoints[idx] = nPoints;
1437 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1438 QString coordString;
1439 for (
int jdx = 0; jdx < nPoints; jdx++ )
1447 if ( invertAxisOrientation )
1455 wkbPtr +=
sizeof( double );
1458 QDomText coordText = doc.createTextNode( coordString );
1459 coordElem.appendChild( coordText );
1460 ringElem.appendChild( coordElem );
1461 boundaryElem.appendChild( ringElem );
1462 polygonElem.appendChild( boundaryElem );
1464 delete [] ringNumPoints;
1473 QDomElement multiPolygonElem = doc.createElement( QStringLiteral(
"gml:MultiPolygon" ) );
1474 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1475 multiPolygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1476 if ( !srsName.isEmpty() )
1477 multiPolygonElem.setAttribute( QStringLiteral(
"srsName" ), srsName );
1480 wkbPtr >> numPolygons;
1482 for (
int kdx = 0; kdx < numPolygons; kdx++ )
1484 QDomElement polygonMemberElem = doc.createElement( QStringLiteral(
"gml:polygonMember" ) );
1485 QDomElement polygonElem = doc.createElement( QStringLiteral(
"gml:Polygon" ) );
1486 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1487 polygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( kdx + 1 ) );
1494 for (
int idx = 0; idx < numRings; idx++ )
1496 QString boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:outerBoundaryIs" :
"gml:exterior";
1499 boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:innerBoundaryIs" :
"gml:interior";
1501 QDomElement boundaryElem = doc.createElement( boundaryName );
1502 QDomElement ringElem = doc.createElement( QStringLiteral(
"gml:LinearRing" ) );
1507 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1508 QString coordString;
1509 for (
int jdx = 0; jdx < nPoints; jdx++ )
1517 if ( invertAxisOrientation )
1526 wkbPtr +=
sizeof( double );
1529 QDomText coordText = doc.createTextNode( coordString );
1530 coordElem.appendChild( coordText );
1531 ringElem.appendChild( coordElem );
1532 boundaryElem.appendChild( ringElem );
1533 polygonElem.appendChild( boundaryElem );
1534 polygonMemberElem.appendChild( polygonElem );
1535 multiPolygonElem.appendChild( polygonMemberElem );
1538 return multiPolygonElem;
1541 return QDomElement();
1547 return QDomElement();
1556 QDomElement QgsOgcUtils::createGMLCoordinates(
const QgsPolylineXY &points, QDomDocument &doc )
1558 QDomElement coordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1559 coordElem.setAttribute( QStringLiteral(
"cs" ), QStringLiteral(
"," ) );
1560 coordElem.setAttribute( QStringLiteral(
"ts" ), QStringLiteral(
" " ) );
1562 QString coordString;
1563 QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
1564 for ( ; pointIt != points.constEnd(); ++pointIt )
1566 if ( pointIt != points.constBegin() )
1575 QDomText coordText = doc.createTextNode( coordString );
1576 coordElem.appendChild( coordText );
1580 QDomElement QgsOgcUtils::createGMLPositions(
const QgsPolylineXY &points, QDomDocument &doc )
1582 QDomElement posElem = doc.createElement( QStringLiteral(
"gml:pos" ) );
1583 if ( points.size() > 1 )
1584 posElem = doc.createElement( QStringLiteral(
"gml:posList" ) );
1585 posElem.setAttribute( QStringLiteral(
"srsDimension" ), QStringLiteral(
"2" ) );
1587 QString coordString;
1588 QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
1589 for ( ; pointIt != points.constEnd(); ++pointIt )
1591 if ( pointIt != points.constBegin() )
1600 QDomText coordText = doc.createTextNode( coordString );
1601 posElem.appendChild( coordText );
1611 if ( fillElement.isNull() || !fillElement.hasChildNodes() )
1619 QDomElement cssElem = fillElement.firstChildElement( QStringLiteral(
"CssParameter" ) );
1620 while ( !cssElem.isNull() )
1622 cssName = cssElem.attribute( QStringLiteral(
"name" ), QStringLiteral(
"not_found" ) );
1623 if ( cssName != QLatin1String(
"not_found" ) )
1625 elemText = cssElem.text();
1626 if ( cssName == QLatin1String(
"fill" ) )
1628 color.setNamedColor( elemText );
1630 else if ( cssName == QLatin1String(
"fill-opacity" ) )
1633 double opacity = elemText.toDouble( &ok );
1636 color.setAlphaF( opacity );
1641 cssElem = cssElem.nextSiblingElement( QStringLiteral(
"CssParameter" ) );
1655 if ( element.isNull() || !element.hasChildNodes() )
1662 if ( element.firstChild().nodeType() == QDomNode::TextNode )
1672 QDomElement childElem = element.firstChildElement();
1673 while ( !childElem.isNull() )
1685 if ( !expr->d->mRootNode )
1687 expr->d->mRootNode = node;
1694 childElem = childElem.nextSiblingElement();
1698 expr->d->mExp = expr->
dump();
1724 static
int binaryOperatorFromTagName( const QString &tagName )
1727 return BINARY_OPERATORS_TAG_NAMES_MAP()->value( tagName, -1 );
1734 return QStringLiteral(
"PropertyIsLike" );
1736 return BINARY_OPERATORS_TAG_NAMES_MAP()->key( op, QString() );
1739 static bool isBinaryOperator(
const QString &tagName )
1741 return binaryOperatorFromTagName( tagName ) >= 0;
1745 static bool isSpatialOperator(
const QString &tagName )
1747 static QStringList spatialOps;
1748 if ( spatialOps.isEmpty() )
1750 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
1751 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
1754 return spatialOps.contains( tagName );
1761 errorMessage = utils.errorMessage();
1769 errorMessage = utils.errorMessage();
1777 errorMessage = utils.errorMessage();
1785 errorMessage = utils.errorMessage();
1793 errorMessage = utils.errorMessage();
1801 errorMessage = utils.errorMessage();
1809 errorMessage = utils.errorMessage();
1813 QgsExpressionNode *QgsOgcUtils::nodeIsBetweenFromOgcFilter( QDomElement &element, QString &errorMessage )
1817 errorMessage = utils.errorMessage();
1825 errorMessage = utils.errorMessage();
1836 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage );
1842 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage );
1850 const QString &srsName,
1851 bool honourAxisOrientation,
1852 bool invertAxisOrientation,
1853 QString *errorMessage )
1856 return QDomElement();
1866 if ( exprRootElem.isNull() )
1867 return QDomElement();
1869 QDomElement filterElem =
1871 doc.createElementNS(
FES_NAMESPACE, QStringLiteral(
"fes:Filter" ) ) :
1872 doc.createElementNS(
OGC_NAMESPACE, QStringLiteral(
"ogc:Filter" ) );
1875 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:gml" ) );
1880 filterElem.setAttributeNode( attr );
1882 filterElem.appendChild( exprRootElem );
1891 const QString &srsName,
1892 bool honourAxisOrientation,
1893 bool invertAxisOrientation,
1894 QString *errorMessage )
1903 return QDomElement();
1917 if ( !exprRootElem.isNull() )
1919 return exprRootElem;
1926 *errorMessage = QObject::tr(
"Node type not supported in expression translation: %1" ).arg( node->
nodeType() );
1930 return QDomElement();
1937 const QList<LayerProperties> &layerProperties,
1938 bool honourAxisOrientation,
1939 bool invertAxisOrientation,
1940 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename,
1941 QString *errorMessage )
1944 return QDomElement();
1947 layerProperties, honourAxisOrientation, invertAxisOrientation,
1948 mapUnprefixedTypenameToPrefixedTypename );
1952 if ( exprRootElem.isNull() )
1953 return QDomElement();
1955 QDomElement filterElem =
1957 doc.createElementNS(
FES_NAMESPACE, QStringLiteral(
"fes:Filter" ) ) :
1958 doc.createElementNS(
OGC_NAMESPACE, QStringLiteral(
"ogc:Filter" ) );
1961 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:gml" ) );
1966 filterElem.setAttributeNode( attr );
1968 filterElem.appendChild( exprRootElem );
1993 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
1994 return QDomElement();
2001 if ( !mErrorMessage.isEmpty() )
2002 return QDomElement();
2005 switch ( node->
op() )
2008 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2013 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
2014 mDoc.removeChild( operandElem );
2018 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
2019 return QDomElement();
2023 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
2024 uoElem.appendChild( operandElem );
2028 mErrorMessage = QObject::tr(
"Unary operator '%1' not implemented yet" ).arg( node->
text() );
2029 return QDomElement();
2039 if ( !mErrorMessage.isEmpty() )
2040 return QDomElement();
2050 if ( rightLit->
value().isNull() )
2053 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2054 elem.appendChild( leftElem );
2058 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2059 notElem.appendChild( elem );
2073 if ( !mErrorMessage.isEmpty() )
2074 return QDomElement();
2077 QString opText = binaryOperatorToTagName( op );
2078 if ( opText.isEmpty() )
2082 mErrorMessage = QObject::tr(
"Binary operator %1 not implemented yet" ).arg( node->
text() );
2083 return QDomElement();
2086 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2091 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2094 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2095 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2097 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2099 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2102 boElem.appendChild( leftElem );
2103 boElem.appendChild( rightElem );
2110 Q_UNUSED( expression )
2113 switch ( node->
value().type() )
2116 value = QString::number( node->
value().toInt() );
2118 case QVariant::Double:
2121 case QVariant::String:
2122 value = node->
value().toString();
2124 case QVariant::Date:
2125 value = node->
value().toDate().toString( Qt::ISODate );
2127 case QVariant::DateTime:
2128 value = node->
value().toDateTime().toString( Qt::ISODate );
2132 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2133 return QDomElement();
2136 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2137 litElem.appendChild( mDoc.createTextNode( value ) );
2144 Q_UNUSED( expression )
2146 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2147 propElem.appendChild( mDoc.createTextNode( node->
name() ) );
2155 if ( node->
list()->
list().size() == 1 )
2158 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2161 const auto constList = node->
list()->
list();
2165 if ( !mErrorMessage.isEmpty() )
2166 return QDomElement();
2168 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2169 eqElem.appendChild( leftNode.cloneNode() );
2170 eqElem.appendChild( listNode );
2172 orElem.appendChild( eqElem );
2177 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2178 notElem.appendChild( orElem );
2187 { QLatin1String(
"disjoint" ), QLatin1String(
"Disjoint" ) },
2188 { QLatin1String(
"intersects" ), QLatin1String(
"Intersects" )},
2189 { QLatin1String(
"touches" ), QLatin1String(
"Touches" ) },
2190 { QLatin1String(
"crosses" ), QLatin1String(
"Crosses" ) },
2191 { QLatin1String(
"contains" ), QLatin1String(
"Contains" ) },
2192 { QLatin1String(
"overlaps" ), QLatin1String(
"Overlaps" ) },
2193 { QLatin1String(
"within" ), QLatin1String(
"Within" ) }
2196 static
bool isBinarySpatialOperator( const QString &fnName )
2198 return BINARY_SPATIAL_OPS_MAP()->contains( fnName );
2201 static QString tagNameForSpatialOperator(
const QString &fnName )
2203 return BINARY_SPATIAL_OPS_MAP()->value( fnName );
2213 return fd->
name() == QLatin1String(
"$geometry" );
2225 if ( fnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2227 const QList<QgsExpressionNode *> &args = fnNode->
args()->
list();
2243 if ( fd->
name() == QLatin1String(
"intersects_bbox" ) )
2245 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2246 Q_ASSERT( argNodes.count() == 2 );
2248 QgsGeometry geom = geometryFromConstExpr( argNodes[1] );
2249 if ( !geom.
isNull() && isGeometryColumn( argNodes[0] ) )
2259 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2260 geomProperty.appendChild( mDoc.createTextNode( mGeometryName ) );
2262 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":BBOX" );
2263 funcElem.appendChild( geomProperty );
2264 funcElem.appendChild( elemBox );
2269 mErrorMessage = QObject::tr(
"<BBOX> is currently supported only in form: bbox($geometry, geomFromWKT('…'))" );
2270 return QDomElement();
2274 if ( isBinarySpatialOperator( fd->
name() ) )
2276 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2277 Q_ASSERT( argNodes.count() == 2 );
2280 if ( isGeometryColumn( argNodes[0] ) )
2281 otherNode = argNodes[1];
2282 else if ( isGeometryColumn( argNodes[1] ) )
2283 otherNode = argNodes[0];
2286 mErrorMessage = QObject::tr(
"Unable to translate spatial operator: at least one must refer to geometry." );
2287 return QDomElement();
2290 QDomElement otherGeomElem;
2295 mErrorMessage = QObject::tr(
"spatial operator: the other operator must be a geometry constructor function" );
2296 return QDomElement();
2301 if ( otherFnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2306 mErrorMessage = QObject::tr(
"geom_from_wkt: argument must be string literal" );
2307 return QDomElement();
2312 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2315 else if ( otherFnDef->
name() == QLatin1String(
"geom_from_gml" ) )
2320 mErrorMessage = QObject::tr(
"geom_from_gml: argument must be string literal" );
2321 return QDomElement();
2324 QDomDocument geomDoc;
2326 if ( !geomDoc.setContent( gml,
true ) )
2328 mErrorMessage = QObject::tr(
"geom_from_gml: unable to parse XML" );
2329 return QDomElement();
2332 QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(),
true );
2333 otherGeomElem = geomNode.toElement();
2337 mErrorMessage = QObject::tr(
"spatial operator: unknown geometry constructor function" );
2338 return QDomElement();
2343 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + tagNameForSpatialOperator( fd->
name() ) );
2344 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2345 geomProperty.appendChild( mDoc.createTextNode( mGeometryName ) );
2346 funcElem.appendChild( geomProperty );
2347 funcElem.appendChild( otherGeomElem );
2351 if ( fd->
isStatic( node, expression, context ) )
2353 QVariant result = fd->
run( node->
args(), context, expression, node );
2355 return expressionLiteralToOgcFilter( &literal, expression, context );
2360 mErrorMessage = QObject::tr(
"Special columns/constants are not supported." );
2361 return QDomElement();
2365 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
2366 funcElem.setAttribute( QStringLiteral(
"name" ), fd->
name() );
2367 const auto constList = node->
args()->
list();
2371 if ( !mErrorMessage.isEmpty() )
2372 return QDomElement();
2374 funcElem.appendChild( childElem );
2385 const QList<QgsOgcUtils::LayerProperties> &layerProperties,
2386 bool honourAxisOrientation,
2387 bool invertAxisOrientation,
2388 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename )
2391 , mGMLVersion( gmlVersion )
2392 , mFilterVersion( filterVersion )
2393 , mLayerProperties( layerProperties )
2394 , mHonourAxisOrientation( honourAxisOrientation )
2395 , mInvertAxisOrientation( invertAxisOrientation )
2396 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
2397 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
2399 , mMapUnprefixedTypenameToPrefixedTypename( mapUnprefixedTypenameToPrefixedTypename )
2425 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
2426 return QDomElement();
2435 if ( !mErrorMessage.isEmpty() )
2436 return QDomElement();
2439 switch ( node->
op() )
2442 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2447 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
2448 mDoc.removeChild( operandElem );
2452 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
2453 return QDomElement();
2457 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
2458 uoElem.appendChild( operandElem );
2463 return QDomElement();
2473 if ( !mErrorMessage.isEmpty() )
2474 return QDomElement();
2484 if ( rightLit->
value().isNull() )
2487 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2488 elem.appendChild( leftElem );
2492 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2493 notElem.appendChild( elem );
2507 if ( !mErrorMessage.isEmpty() )
2508 return QDomElement();
2513 opText = QStringLiteral(
"Or" );
2515 opText = QStringLiteral(
"And" );
2517 opText = QStringLiteral(
"PropertyIsEqualTo" );
2519 opText = QStringLiteral(
"PropertyIsNotEqualTo" );
2521 opText = QStringLiteral(
"PropertyIsLessThanOrEqualTo" );
2523 opText = QStringLiteral(
"PropertyIsGreaterThanOrEqualTo" );
2525 opText = QStringLiteral(
"PropertyIsLessThan" );
2527 opText = QStringLiteral(
"PropertyIsGreaterThan" );
2529 opText = QStringLiteral(
"PropertyIsLike" );
2531 opText = QStringLiteral(
"PropertyIsLike" );
2533 if ( opText.isEmpty() )
2537 return QDomElement();
2540 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2545 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2548 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2549 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2551 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2553 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2556 boElem.appendChild( leftElem );
2557 boElem.appendChild( rightElem );
2565 switch ( node->
value().type() )
2568 value = QString::number( node->
value().toInt() );
2570 case QVariant::LongLong:
2571 value = QString::number( node->
value().toLongLong() );
2573 case QVariant::Double:
2576 case QVariant::String:
2577 value = node->
value().toString();
2581 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2582 return QDomElement();
2585 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2586 litElem.appendChild( mDoc.createTextNode( value ) );
2593 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2594 if ( node->
tableName().isEmpty() || mLayerProperties.size() == 1 )
2595 propElem.appendChild( mDoc.createTextNode( node->
name() ) );
2598 QString tableName( mMapTableAliasToNames[node->
tableName()] );
2599 if ( mMapUnprefixedTypenameToPrefixedTypename.contains( tableName ) )
2600 tableName = mMapUnprefixedTypenameToPrefixedTypename[tableName];
2601 propElem.appendChild( mDoc.createTextNode( tableName +
"/" + node->
name() ) );
2608 if ( node->
list()->
list().size() == 1 )
2611 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2614 const auto constList = node->
list()->
list();
2618 if ( !mErrorMessage.isEmpty() )
2619 return QDomElement();
2621 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2622 eqElem.appendChild( leftNode.cloneNode() );
2623 eqElem.appendChild( listNode );
2625 orElem.appendChild( eqElem );
2630 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2631 notElem.appendChild( orElem );
2640 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsBetween" );
2642 QDomElement lowerBoundary = mDoc.createElement( mFilterPrefix +
":LowerBoundary" );
2644 elem.appendChild( lowerBoundary );
2645 QDomElement upperBoundary = mDoc.createElement( mFilterPrefix +
":UpperBoundary" );
2647 elem.appendChild( upperBoundary );
2651 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2652 notElem.appendChild( elem );
2659 static QString mapBinarySpatialToOgc(
const QString &name )
2661 QString nameCompare( name );
2662 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2663 nameCompare = name.mid( 3 );
2664 QStringList spatialOps;
2665 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
2666 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
2667 const auto constSpatialOps = spatialOps;
2668 for ( QString op : constSpatialOps )
2670 if ( nameCompare.compare( op, Qt::CaseInsensitive ) == 0 )
2676 static QString mapTernarySpatialToOgc(
const QString &name )
2678 QString nameCompare( name );
2679 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2680 nameCompare = name.mid( 3 );
2681 if ( nameCompare.compare( QLatin1String(
"DWithin" ), Qt::CaseInsensitive ) == 0 )
2682 return QStringLiteral(
"DWithin" );
2683 if ( nameCompare.compare( QLatin1String(
"Beyond" ), Qt::CaseInsensitive ) == 0 )
2684 return QStringLiteral(
"Beyond" );
2688 QString QgsOgcUtilsSQLStatementToFilter::getGeometryColumnSRSName(
const QgsSQLStatement::Node *node )
2696 const auto constMLayerProperties = mLayerProperties;
2699 if ( prop.mName.compare( mMapTableAliasToNames[col->
tableName()], Qt::CaseInsensitive ) == 0 &&
2700 prop.mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2702 return prop.mSRSName;
2706 if ( !mLayerProperties.empty() &&
2707 mLayerProperties.at( 0 ).mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2709 return mLayerProperties.at( 0 ).mSRSName;
2715 QList<QgsSQLStatement::Node *> args,
2716 bool lastArgIsSRSName,
2718 bool &axisInversion )
2720 srsName = mCurrentSRSName;
2721 axisInversion = mInvertAxisOrientation;
2723 if ( lastArgIsSRSName )
2728 mErrorMessage = QObject::tr(
"%1: Last argument must be string or integer literal" ).arg( mainNode->
name() );
2732 if ( lit->
value().type() == QVariant::Int )
2736 srsName =
"EPSG:" + QString::number( lit->
value().toInt() );
2740 srsName =
"urn:ogc:def:crs:EPSG::" + QString::number( lit->
value().toInt() );
2745 srsName = lit->
value().toString();
2746 if ( srsName.startsWith( QLatin1String(
"EPSG:" ), Qt::CaseInsensitive ) )
2752 if ( !srsName.isEmpty() )
2758 axisInversion = !axisInversion;
2768 if ( node->
name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 )
2770 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2771 if ( args.size() != 1 && args.size() != 2 )
2773 mErrorMessage = QObject::tr(
"Function %1 should have 1 or 2 arguments" ).arg( node->
name() );
2774 return QDomElement();
2780 mErrorMessage = QObject::tr(
"%1: First argument must be string literal" ).arg( node->
name() );
2781 return QDomElement();
2786 if ( ! processSRSName( node, args, args.size() == 2, srsName, axisInversion ) )
2788 return QDomElement();
2794 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2796 if ( geomElem.isNull() )
2798 mErrorMessage = QObject::tr(
"%1: invalid WKT" ).arg( node->
name() );
2799 return QDomElement();
2806 if ( node->
name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 )
2808 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2809 if ( args.size() != 4 && args.size() != 5 )
2811 mErrorMessage = QObject::tr(
"Function %1 should have 4 or 5 arguments" ).arg( node->
name() );
2812 return QDomElement();
2817 for (
int i = 0; i < 4; i++ )
2822 mErrorMessage = QObject::tr(
"%1: Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2823 return QDomElement();
2827 if ( lit->
value().type() == QVariant::Int )
2828 val = lit->
value().toInt();
2829 else if ( lit->
value().type() == QVariant::LongLong )
2830 val = lit->
value().toLongLong();
2831 else if ( lit->
value().type() == QVariant::Double )
2832 val = lit->
value().toDouble();
2835 mErrorMessage = QObject::tr(
"%1 Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2836 return QDomElement();
2850 if ( ! processSRSName( node, args, args.size() == 5, srsName, axisInversion ) )
2852 return QDomElement();
2859 QgsOgcUtils::rectangleToGMLEnvelope( &rect, mDoc, srsName, axisInversion, 15 );
2863 if ( node->
name().compare( QLatin1String(
"ST_GeomFromGML" ), Qt::CaseInsensitive ) == 0 )
2865 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2866 if ( args.size() != 1 )
2868 mErrorMessage = QObject::tr(
"Function %1 should have 1 argument" ).arg( node->
name() );
2869 return QDomElement();
2875 mErrorMessage = QObject::tr(
"%1: Argument must be string literal" ).arg( node->
name() );
2876 return QDomElement();
2879 QDomDocument geomDoc;
2881 if ( !geomDoc.setContent( gml,
true ) )
2883 mErrorMessage = QObject::tr(
"ST_GeomFromGML: unable to parse XML" );
2884 return QDomElement();
2887 QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(),
true );
2889 return geomNode.toElement();
2893 QString ogcName( mapBinarySpatialToOgc( node->
name() ) );
2894 if ( !ogcName.isEmpty() )
2896 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2897 if ( args.size() != 2 )
2899 mErrorMessage = QObject::tr(
"Function %1 should have 2 arguments" ).arg( node->
name() );
2900 return QDomElement();
2903 for (
int i = 0; i < 2; i ++ )
2906 (
static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
2907 static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
2909 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
2916 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + ogcName );
2917 const auto constArgs = args;
2921 if ( !mErrorMessage.isEmpty() )
2923 mCurrentSRSName.clear();
2924 return QDomElement();
2927 funcElem.appendChild( childElem );
2930 mCurrentSRSName.clear();
2934 ogcName = mapTernarySpatialToOgc( node->
name() );
2935 if ( !ogcName.isEmpty() )
2937 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2938 if ( args.size() != 3 )
2940 mErrorMessage = QObject::tr(
"Function %1 should have 3 arguments" ).arg( node->
name() );
2941 return QDomElement();
2944 for (
int i = 0; i < 2; i ++ )
2947 (
static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
2948 static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
2950 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
2955 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + node->
name().mid( 3 ) );
2956 for (
int i = 0; i < 2; i++ )
2959 if ( !mErrorMessage.isEmpty() )
2961 mCurrentSRSName.clear();
2962 return QDomElement();
2965 funcElem.appendChild( childElem );
2967 mCurrentSRSName.clear();
2972 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() );
2973 return QDomElement();
2976 if ( lit->
value().isNull() )
2978 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() );
2979 return QDomElement();
2982 QString unit( QStringLiteral(
"m" ) );
2983 switch ( lit->
value().type() )
2986 distance = QString::number( lit->
value().toInt() );
2988 case QVariant::LongLong:
2989 distance = QString::number( lit->
value().toLongLong() );
2991 case QVariant::Double:
2994 case QVariant::String:
2996 distance = lit->
value().toString();
2997 for (
int i = 0; i < distance.size(); i++ )
2999 if ( !( ( distance[i] >=
'0' && distance[i] <=
'9' ) || distance[i] ==
'-' || distance[i] ==
'.' || distance[i] ==
'e' || distance[i] ==
'E' ) )
3001 unit = distance.mid( i ).trimmed();
3002 distance = distance.mid( 0, i );
3010 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( lit->
value().type() );
3011 return QDomElement();
3014 QDomElement distanceElem = mDoc.createElement( mFilterPrefix +
":Distance" );
3016 distanceElem.setAttribute( QStringLiteral(
"uom" ), unit );
3018 distanceElem.setAttribute( QStringLiteral(
"unit" ), unit );
3019 distanceElem.appendChild( mDoc.createTextNode( distance ) );
3020 funcElem.appendChild( distanceElem );
3025 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
3026 funcElem.setAttribute( QStringLiteral(
"name" ), node->
name() );
3027 const auto constList = node->
args()->
list();
3031 if ( !mErrorMessage.isEmpty() )
3032 return QDomElement();
3034 funcElem.appendChild( childElem );
3040 const QString &leftTable )
3048 QList<QDomElement> listElem;
3050 for (
const QString &columnName : constUsingColumns )
3052 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
3053 QDomElement propElem1 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3054 propElem1.appendChild( mDoc.createTextNode( leftTable +
"/" + columnName ) );
3055 eqElem.appendChild( propElem1 );
3056 QDomElement propElem2 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3057 propElem2.appendChild( mDoc.createTextNode( node->
tableDef()->
name() +
"/" + columnName ) );
3058 eqElem.appendChild( propElem2 );
3059 listElem.append( eqElem );
3062 if ( listElem.size() == 1 )
3066 else if ( listElem.size() > 1 )
3068 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3069 const auto constListElem = listElem;
3070 for (
const QDomElement &elem : constListElem )
3072 andElem.appendChild( elem );
3077 return QDomElement();
3082 if ( node->
alias().isEmpty() )
3084 mMapTableAliasToNames[ node->
name()] = node->
name();
3088 mMapTableAliasToNames[ node->
alias()] = node->
name();
3094 QList<QDomElement> listElem;
3097 ( node->
tables().size() != 1 || !node->
joins().empty() ) )
3099 mErrorMessage = QObject::tr(
"Joins are only supported with WFS 2.0" );
3100 return QDomElement();
3104 const auto constTables = node->
tables();
3109 const auto constJoins = node->
joins();
3112 visit( join->tableDef() );
3116 QList< QgsSQLStatement::NodeTableDef *> nodeTables = node->
tables();
3117 QString leftTable = nodeTables.at( nodeTables.length() - 1 )->name();
3120 QDomElement joinElem =
toOgcFilter( join, leftTable );
3121 if ( !mErrorMessage.isEmpty() )
3122 return QDomElement();
3123 listElem.append( joinElem );
3124 leftTable = join->tableDef()->name();
3128 if ( node->
where() )
3131 if ( !mErrorMessage.isEmpty() )
3132 return QDomElement();
3133 listElem.append( whereElem );
3137 if ( listElem.size() == 1 )
3141 else if ( listElem.size() > 1 )
3143 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3144 const auto constListElem = listElem;
3145 for (
const QDomElement &elem : constListElem )
3147 andElem.appendChild( elem );
3152 return QDomElement();
3158 mPropertyName = QStringLiteral(
"PropertyName" );
3159 mPrefix = QStringLiteral(
"ogc" );
3163 mPropertyName = QStringLiteral(
"ValueReference" );
3164 mPrefix = QStringLiteral(
"fes" );
3170 if ( element.isNull() )
3174 if ( isBinaryOperator( element.tagName() ) )
3180 if ( isSpatialOperator( element.tagName() ) )
3186 if ( element.tagName() == QLatin1String(
"Not" ) )
3190 else if ( element.tagName() == QLatin1String(
"PropertyIsNull" ) )
3194 else if ( element.tagName() == QLatin1String(
"Literal" ) )
3198 else if ( element.tagName() == QLatin1String(
"Function" ) )
3202 else if ( element.tagName() == mPropertyName )
3206 else if ( element.tagName() == QLatin1String(
"PropertyIsBetween" ) )
3211 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() );
3217 if ( element.isNull() )
3220 int op = binaryOperatorFromTagName( element.tagName() );
3223 mErrorMessage = QObject::tr(
"'%1' binary operator not supported." ).arg( element.tagName() );
3227 if ( op ==
QgsExpressionNodeBinaryOperator::boLike && element.hasAttribute( QStringLiteral(
"matchCase" ) ) && element.attribute( QStringLiteral(
"matchCase" ) ) == QLatin1String(
"false" ) )
3232 QDomElement operandElem = element.firstChildElement();
3237 mErrorMessage = QObject::tr(
"invalid left operand for '%1' binary operator" ).arg( element.tagName() );
3241 std::unique_ptr<QgsExpressionNode> leftOp( expr->clone() );
3242 for ( operandElem = operandElem.nextSiblingElement(); !operandElem.isNull(); operandElem = operandElem.nextSiblingElement() )
3247 mErrorMessage = QObject::tr(
"invalid right operand for '%1' binary operator" ).arg( element.tagName() );
3254 if ( element.hasAttribute( QStringLiteral(
"wildCard" ) ) )
3256 wildCard = element.attribute( QStringLiteral(
"wildCard" ) );
3259 if ( element.hasAttribute( QStringLiteral(
"singleChar" ) ) )
3261 singleChar = element.attribute( QStringLiteral(
"singleChar" ) );
3263 QString escape = QStringLiteral(
"\\" );
3264 if ( element.hasAttribute( QStringLiteral(
"escape" ) ) )
3266 escape = element.attribute( QStringLiteral(
"escape" ) );
3268 if ( element.hasAttribute( QStringLiteral(
"escapeChar" ) ) )
3270 escape = element.attribute( QStringLiteral(
"escapeChar" ) );
3274 if ( !wildCard.isEmpty() && wildCard != QLatin1String(
"%" ) )
3276 oprValue.replace(
'%', QLatin1String(
"\\%" ) );
3277 if ( oprValue.startsWith( wildCard ) )
3279 oprValue.replace( 0, 1, QStringLiteral(
"%" ) );
3281 QRegExp rx(
"[^" + QRegExp::escape( escape ) +
"](" + QRegExp::escape( wildCard ) +
")" );
3283 while ( ( pos = rx.indexIn( oprValue, pos ) ) != -1 )
3285 oprValue.replace( pos + 1, 1, QStringLiteral(
"%" ) );
3288 oprValue.replace( escape + wildCard, wildCard );
3290 if ( !singleChar.isEmpty() && singleChar != QLatin1String(
"_" ) )
3292 oprValue.replace(
'_', QLatin1String(
"\\_" ) );
3293 if ( oprValue.startsWith( singleChar ) )
3295 oprValue.replace( 0, 1, QStringLiteral(
"_" ) );
3297 QRegExp rx(
"[^" + QRegExp::escape( escape ) +
"](" + QRegExp::escape( singleChar ) +
")" );
3299 while ( ( pos = rx.indexIn( oprValue, pos ) ) != -1 )
3301 oprValue.replace( pos + 1, 1, QStringLiteral(
"_" ) );
3304 oprValue.replace( escape + singleChar, singleChar );
3306 if ( !escape.isEmpty() && escape != QLatin1String(
"\\" ) )
3308 oprValue.replace( escape + escape, escape );
3316 if ( expr == leftOp )
3318 mErrorMessage = QObject::tr(
"only one operand for '%1' binary operator" ).arg( element.tagName() );
3332 QDomElement childElem = element.firstChildElement();
3334 while ( !childElem.isNull() && gml2Str.isEmpty() )
3336 if ( childElem.tagName() != mPropertyName )
3338 QTextStream gml2Stream( &gml2Str );
3339 childElem.save( gml2Stream, 0 );
3341 childElem = childElem.nextSiblingElement();
3343 if ( !gml2Str.isEmpty() )
3349 mErrorMessage = QObject::tr(
"No OGC Geometry found" );
3362 if ( element.isNull() || element.tagName() != mPropertyName )
3364 mErrorMessage = QObject::tr(
"%1:PropertyName expected, got %2" ).arg( mPrefix, element.tagName() );
3373 if ( element.isNull() || element.tagName() != QLatin1String(
"Literal" ) )
3375 mErrorMessage = QObject::tr(
"%1:Literal expected, got %2" ).arg( mPrefix, element.tagName() );
3379 std::unique_ptr<QgsExpressionNode> root;
3382 QDomNode childNode = element.firstChild();
3383 while ( !childNode.isNull() )
3385 std::unique_ptr<QgsExpressionNode> operand;
3387 if ( childNode.nodeType() == QDomNode::ElementNode )
3390 const QDomElement operandElem = childNode.toElement();
3394 mErrorMessage = QObject::tr(
"'%1' is an invalid or not supported content for %2:Literal" ).arg( operandElem.tagName(), mPrefix );
3401 QVariant value = childNode.nodeValue();
3403 bool converted =
false;
3408 QDomElement propertyNameElement = element.previousSiblingElement( mPropertyName );
3409 if ( propertyNameElement.isNull() || propertyNameElement.tagName() != mPropertyName )
3411 propertyNameElement = element.nextSiblingElement( mPropertyName );
3413 if ( !propertyNameElement.isNull() || propertyNameElement.tagName() == mPropertyName )
3415 const int fieldIndex = mLayer->
fields().
indexOf( propertyNameElement.firstChild().nodeValue() );
3416 if ( fieldIndex != -1 )
3429 const double d = value.toDouble( &ok );
3442 root = std::move( operand );
3449 childNode = childNode.nextSibling();
3453 return root.release();
3460 if ( element.tagName() != QLatin1String(
"Not" ) )
3463 const QDomElement operandElem = element.firstChildElement();
3467 mErrorMessage = QObject::tr(
"invalid operand for '%1' unary operator" ).arg( element.tagName() );
3477 if ( element.tagName() != QLatin1String(
"PropertyIsNull" ) )
3482 const QDomElement operandElem = element.firstChildElement();
3493 if ( element.isNull() || element.tagName() != QLatin1String(
"Function" ) )
3495 mErrorMessage = QObject::tr(
"%1:Function expected, got %2" ).arg( mPrefix, element.tagName() );
3503 if ( element.attribute( QStringLiteral(
"name" ) ) != funcDef->
name() )
3508 QDomElement operandElem = element.firstChildElement();
3509 while ( !operandElem.isNull() )
3516 args->append( op.release() );
3518 operandElem = operandElem.nextSiblingElement();
3530 std::unique_ptr<QgsExpressionNode> operand;
3531 std::unique_ptr<QgsExpressionNode> lowerBound;
3532 std::unique_ptr<QgsExpressionNode> upperBound;
3534 QDomElement operandElem = element.firstChildElement();
3535 while ( !operandElem.isNull() )
3537 if ( operandElem.tagName() == QLatin1String(
"LowerBoundary" ) )
3539 QDomElement lowerBoundElem = operandElem.firstChildElement();
3542 else if ( operandElem.tagName() == QLatin1String(
"UpperBoundary" ) )
3544 QDomElement upperBoundElem = operandElem.firstChildElement();
3553 if ( operand && lowerBound && upperBound )
3556 operandElem = operandElem.nextSiblingElement();
3559 if ( !operand || !lowerBound || !upperBound )
3561 mErrorMessage = QObject::tr(
"missing some required sub-elements in %1:PropertyIsBetween" ).arg( mPrefix );
3572 return mErrorMessage;