37#include <QRegularExpression> 
   43#include <netinet/in.h> 
   49#define GML_NAMESPACE QStringLiteral( "http://www.opengis.net/gml" ) 
   50#define GML32_NAMESPACE QStringLiteral( "http://www.opengis.net/gml/3.2" ) 
   51#define OGC_NAMESPACE QStringLiteral( "http://www.opengis.net/ogc" ) 
   52#define FES_NAMESPACE QStringLiteral( "http://www.opengis.net/fes/2.0" ) 
   53#define SE_NAMESPACE QStringLiteral( "http://www.opengis.net/se" ) 
   58    const QString &namespacePrefix,
 
   59    const QString &namespaceURI,
 
   62    bool honourAxisOrientation,
 
   63    bool invertAxisOrientation,
 
   64    const QMap<QString, QString> &fieldNameToXPathMap,
 
   65    const QMap<QString, QString> &namespacePrefixToUriMap )
 
   68  , mGMLVersion( gmlVersion )
 
   69  , mFilterVersion( filterVersion )
 
   70  , mNamespacePrefix( namespacePrefix )
 
   71  , mNamespaceURI( namespaceURI )
 
   74  , mInvertAxisOrientation( invertAxisOrientation )
 
   75  , mFieldNameToXPathMap( fieldNameToXPathMap )
 
   76  , mNamespacePrefixToUriMap( namespacePrefixToUriMap )
 
   77  , mFilterPrefix( ( filterVersion == 
QgsOgcUtils::FILTER_FES_2_0 ) ? 
"fes" : 
"ogc" )
 
   78  , mPropertyName( ( filterVersion == 
QgsOgcUtils::FILTER_FES_2_0 ) ? 
"ValueReference" : 
"PropertyName" )
 
   82  if ( !mSrsName.isEmpty() )
 
   88      mInvertAxisOrientation = !mInvertAxisOrientation;
 
 
   95  QDomElement geometryTypeElement = geometryNode.toElement();
 
   96  QString geomType = geometryTypeElement.tagName();
 
   99  if ( !( geomType == QLatin1String( 
"Point" ) || geomType == QLatin1String( 
"LineString" ) || geomType == QLatin1String( 
"Polygon" ) ||
 
  100          geomType == QLatin1String( 
"MultiPoint" ) || geomType == QLatin1String( 
"MultiLineString" ) || geomType == QLatin1String( 
"MultiPolygon" ) ||
 
  101          geomType == QLatin1String( 
"Box" ) || geomType == QLatin1String( 
"Envelope" ) || geomType == QLatin1String( 
"MultiCurve" ) ) )
 
  103    const QDomNode geometryChild = geometryNode.firstChild();
 
  104    if ( geometryChild.isNull() )
 
  108    geometryTypeElement = geometryChild.toElement();
 
  109    geomType = geometryTypeElement.tagName();
 
  112  if ( !( geomType == QLatin1String( 
"Point" ) || geomType == QLatin1String( 
"LineString" ) || geomType == QLatin1String( 
"Polygon" ) ||
 
  113          geomType == QLatin1String( 
"MultiPoint" ) || geomType == QLatin1String( 
"MultiLineString" ) || geomType == QLatin1String( 
"MultiPolygon" ) ||
 
  114          geomType == QLatin1String( 
"Box" ) || geomType == QLatin1String( 
"Envelope" )  || geomType == QLatin1String( 
"MultiCurve" ) ) )
 
  117  if ( geomType == QLatin1String( 
"Point" ) )
 
  119    geometry = geometryFromGMLPoint( geometryTypeElement );
 
  121  else if ( geomType == QLatin1String( 
"LineString" ) )
 
  123    geometry = geometryFromGMLLineString( geometryTypeElement );
 
  125  else if ( geomType == QLatin1String( 
"Polygon" ) )
 
  127    geometry = geometryFromGMLPolygon( geometryTypeElement );
 
  129  else if ( geomType == QLatin1String( 
"MultiPoint" ) )
 
  131    geometry = geometryFromGMLMultiPoint( geometryTypeElement );
 
  133  else if ( geomType == QLatin1String( 
"MultiLineString" ) )
 
  135    geometry = geometryFromGMLMultiLineString( geometryTypeElement );
 
  137  else if ( geomType == QLatin1String( 
"MultiCurve" ) )
 
  139    geometry = geometryFromGMLMultiCurve( geometryTypeElement );
 
  141  else if ( geomType == QLatin1String( 
"MultiPolygon" ) )
 
  143    geometry = geometryFromGMLMultiPolygon( geometryTypeElement );
 
  145  else if ( geomType == QLatin1String( 
"Box" ) )
 
  149  else if ( geomType == QLatin1String( 
"Envelope" ) )
 
  155    QgsDebugMsgLevel( QStringLiteral( 
"Unknown geometry type %1" ).arg( geomType ), 2 );
 
  164    if ( geometryTypeElement.hasAttribute( QStringLiteral( 
"srsName" ) ) )
 
  166      QString 
srsName { geometryTypeElement.attribute( QStringLiteral( 
"srsName" ) ) };
 
  169      const bool ignoreAxisOrientation { 
srsName.startsWith( QLatin1String( 
"http://www.opengis.net/gml/srs/" ) ) || 
srsName.startsWith( QLatin1String( 
"EPSG:" ) ) };
 
  173      if ( 
srsName.startsWith( QLatin1String( 
"http://www.opengis.net/gml/srs/" ) ) )
 
  175        const auto parts { 
srsName.split( QRegularExpression( QStringLiteral( R
"raw(/|#|\.)raw" ) ) ) }; 
  176        if ( parts.length() == 10 )
 
  178          srsName = QStringLiteral( 
"http://www.opengis.net/def/crs/%1/0/%2" ).arg( parts[ 7 ].toUpper(), parts[ 9 ] );
 
 
  211  const QString xml = QStringLiteral( 
"<tmp xmlns=\"%1\" xmlns:gml=\"%1\">%2</tmp>" ).arg( 
GML_NAMESPACE, xmlString );
 
  213  if ( !doc.setContent( xml, 
true ) )
 
  216  return geometryFromGML( doc.documentElement().firstChildElement(), context );
 
 
  220QgsGeometry QgsOgcUtils::geometryFromGMLPoint( 
const QDomElement &geometryElement )
 
  224  const QDomNodeList coordList = geometryElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"coordinates" ) );
 
  225  if ( !coordList.isEmpty() )
 
  227    const QDomElement coordElement = coordList.at( 0 ).toElement();
 
  228    if ( readGMLCoordinates( pointCoordinate, coordElement ) != 0 )
 
  235    const QDomNodeList posList = geometryElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"pos" ) );
 
  236    if ( posList.size() < 1 )
 
  240    const QDomElement posElement = posList.at( 0 ).toElement();
 
  241    if ( readGMLPositions( pointCoordinate, posElement ) != 0 )
 
  247  if ( pointCoordinate.empty() )
 
  252  const bool hasZ { !std::isnan( pointCoordinate.first().z() ) };
 
  253  QgsPolyline::const_iterator point_it = pointCoordinate.constBegin();
 
  254  const char e = 
static_cast<char>( htonl( 1 ) != 1 );
 
  255  const double x = point_it->x();
 
  256  const double y = point_it->y();
 
  257  const int size = 1 + 
static_cast<int>( 
sizeof( int ) ) + ( hasZ ? 3 : 2 ) * 
static_cast<int>( 
sizeof( 
double ) );
 
  260  unsigned char *wkb = 
new unsigned char[size];
 
  263  memcpy( &( wkb )[wkbPosition], &e, 1 );
 
  265  memcpy( &( wkb )[wkbPosition], &type, 
sizeof( 
int ) );
 
  266  wkbPosition += 
sizeof( int );
 
  267  memcpy( &( wkb )[wkbPosition], &x, 
sizeof( 
double ) );
 
  268  wkbPosition += 
sizeof( double );
 
  269  memcpy( &( wkb )[wkbPosition], &y, 
sizeof( 
double ) );
 
  273    wkbPosition += 
sizeof( double );
 
  274    double z = point_it->z();
 
  275    memcpy( &( wkb )[wkbPosition], &z, 
sizeof( 
double ) );
 
  283QgsGeometry QgsOgcUtils::geometryFromGMLLineString( 
const QDomElement &geometryElement )
 
  287  const QDomNodeList coordList = geometryElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"coordinates" ) );
 
  288  if ( !coordList.isEmpty() )
 
  290    const QDomElement coordElement = coordList.at( 0 ).toElement();
 
  291    if ( readGMLCoordinates( lineCoordinates, coordElement ) != 0 )
 
  298    const QDomNodeList posList = geometryElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"posList" ) );
 
  299    if ( posList.size() < 1 )
 
  303    const QDomElement posElement = posList.at( 0 ).toElement();
 
  304    if ( readGMLPositions( lineCoordinates, posElement ) != 0 )
 
  310  const bool hasZ { !std::isnan( lineCoordinates.first().z() ) };
 
  312  char e = 
static_cast<char>( htonl( 1 ) != 1 );
 
  313  const int size = 1 + 2 * 
static_cast<int>( 
sizeof( int ) + lineCoordinates.size() ) * ( hasZ ? 3 : 2 ) * static_cast<int>( sizeof( double ) );
 
  316  unsigned char *wkb = 
new unsigned char[size];
 
  320  int nPoints = lineCoordinates.size();
 
  323  memcpy( &( wkb )[wkbPosition], &e, 1 );
 
  325  memcpy( &( wkb )[wkbPosition], &type, 
sizeof( 
int ) );
 
  326  wkbPosition += 
sizeof( int );
 
  327  memcpy( &( wkb )[wkbPosition], &nPoints, 
sizeof( 
int ) );
 
  328  wkbPosition += 
sizeof( int );
 
  330  QgsPolyline::const_iterator iter;
 
  331  for ( iter = lineCoordinates.constBegin(); iter != lineCoordinates.constEnd(); ++iter )
 
  335    memcpy( &( wkb )[wkbPosition], &x, 
sizeof( 
double ) );
 
  336    wkbPosition += 
sizeof( double );
 
  337    memcpy( &( wkb )[wkbPosition], &y, 
sizeof( 
double ) );
 
  338    wkbPosition += 
sizeof( double );
 
  342      double z = iter->z();
 
  343      memcpy( &( wkb )[wkbPosition], &z, 
sizeof( 
double ) );
 
  344      wkbPosition += 
sizeof( double );
 
  354QgsGeometry QgsOgcUtils::geometryFromGMLPolygon( 
const QDomElement &geometryElement )
 
  361  const QDomNodeList outerBoundaryList = geometryElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"outerBoundaryIs" ) );
 
  362  if ( !outerBoundaryList.isEmpty() ) 
 
  364    QDomElement coordinatesElement = outerBoundaryList.at( 0 ).firstChild().firstChild().toElement();
 
  365    if ( coordinatesElement.isNull() )
 
  369    if ( readGMLCoordinates( exteriorPointList, coordinatesElement ) != 0 )
 
  373    ringCoordinates.push_back( exteriorPointList );
 
  376    const QDomNodeList innerBoundaryList = geometryElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"innerBoundaryIs" ) );
 
  377    for ( 
int i = 0; i < innerBoundaryList.size(); ++i )
 
  380      coordinatesElement = innerBoundaryList.at( i ).firstChild().firstChild().toElement();
 
  381      if ( coordinatesElement.isNull() )
 
  385      if ( readGMLCoordinates( interiorPointList, coordinatesElement ) != 0 )
 
  389      ringCoordinates.push_back( interiorPointList );
 
  395    const QDomNodeList exteriorList = geometryElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"exterior" ) );
 
  396    if ( exteriorList.size() < 1 ) 
 
  400    const QDomElement posElement = exteriorList.at( 0 ).firstChild().firstChild().toElement();
 
  401    if ( posElement.isNull() )
 
  405    if ( readGMLPositions( exteriorPointList, posElement ) != 0 )
 
  409    ringCoordinates.push_back( exteriorPointList );
 
  412    const QDomNodeList interiorList = geometryElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"interior" ) );
 
  413    for ( 
int i = 0; i < interiorList.size(); ++i )
 
  416      const QDomElement posElement = interiorList.at( i ).firstChild().firstChild().toElement();
 
  417      if ( posElement.isNull() )
 
  422      if ( readGMLPositions( interiorPointList, posElement ) )
 
  426      ringCoordinates.push_back( interiorPointList );
 
  431  int nrings = ringCoordinates.size();
 
  436  for ( QgsMultiPolyline::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
 
  438    npoints += it->size();
 
  441  const bool hasZ { !std::isnan( ringCoordinates.first().first().z() ) };
 
  443  const int size = 1 + 2 * 
static_cast<int>( 
sizeof( int ) ) + nrings * 
static_cast<int>( 
sizeof( int ) ) + ( hasZ ? 3 : 2 ) * npoints * 
static_cast<int>( 
sizeof( 
double ) );
 
  446  unsigned char *wkb = 
new unsigned char[size];
 
  449  char e = 
static_cast<char>( htonl( 1 ) != 1 );
 
  451  int nPointsInRing = 0;
 
  455  memcpy( &( wkb )[wkbPosition], &e, 1 );
 
  457  memcpy( &( wkb )[wkbPosition], &type, 
sizeof( 
int ) );
 
  458  wkbPosition += 
sizeof( int );
 
  459  memcpy( &( wkb )[wkbPosition], &nrings, 
sizeof( 
int ) );
 
  460  wkbPosition += 
sizeof( int );
 
  461  for ( QgsMultiPolyline::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
 
  463    nPointsInRing = it->size();
 
  464    memcpy( &( wkb )[wkbPosition], &nPointsInRing, 
sizeof( 
int ) );
 
  465    wkbPosition += 
sizeof( int );
 
  467    QgsPolyline::const_iterator iter;
 
  468    for ( iter = it->begin(); iter != it->end(); ++iter )
 
  473      memcpy( &( wkb )[wkbPosition], &x, 
sizeof( 
double ) );
 
  474      wkbPosition += 
sizeof( double );
 
  475      memcpy( &( wkb )[wkbPosition], &y, 
sizeof( 
double ) );
 
  476      wkbPosition += 
sizeof( double );
 
  481        memcpy( &( wkb )[wkbPosition], &z, 
sizeof( 
double ) );
 
  482        wkbPosition += 
sizeof( double );
 
  492QgsGeometry QgsOgcUtils::geometryFromGMLMultiPoint( 
const QDomElement &geometryElement )
 
  496  const QDomNodeList pointMemberList = geometryElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"pointMember" ) );
 
  497  if ( pointMemberList.size() < 1 )
 
  501  QDomNodeList pointNodeList;
 
  503  QDomNodeList coordinatesList;
 
  504  QDomNodeList posList;
 
  505  for ( 
int i = 0; i < pointMemberList.size(); ++i )
 
  508    pointNodeList = pointMemberList.at( i ).toElement().elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"Point" ) );
 
  509    if ( pointNodeList.size() < 1 )
 
  514    coordinatesList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"coordinates" ) );
 
  515    if ( !coordinatesList.isEmpty() )
 
  517      currentPoint.clear();
 
  518      if ( readGMLCoordinates( currentPoint, coordinatesList.at( 0 ).toElement() ) != 0 )
 
  522      if ( currentPoint.empty() )
 
  526      pointList.push_back( ( *currentPoint.begin() ) );
 
  532      posList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"pos" ) );
 
  533      if ( posList.size() < 1 )
 
  537      currentPoint.clear();
 
  538      if ( readGMLPositions( currentPoint, posList.at( 0 ).toElement() ) != 0 )
 
  542      if ( currentPoint.empty() )
 
  546      pointList.push_back( ( *currentPoint.begin() ) );
 
  550  int nPoints = pointList.size(); 
 
  554  const bool hasZ { !std::isnan( pointList.first().z() ) };
 
  557  const int size = 1 + 2 * 
static_cast<int>( 
sizeof( int ) ) + 
static_cast<int>( pointList.size() ) * ( ( hasZ ? 3 : 2 ) * static_cast<int>( sizeof( double ) ) + 1 + static_cast<int>( sizeof( int ) ) );
 
  560  unsigned char *wkb = 
new unsigned char[size];
 
  563  char e = 
static_cast<char>( htonl( 1 ) != 1 );
 
  566  memcpy( &( wkb )[wkbPosition], &e, 1 );
 
  568  memcpy( &( wkb )[wkbPosition], &type, 
sizeof( 
int ) );
 
  569  wkbPosition += 
sizeof( int );
 
  570  memcpy( &( wkb )[wkbPosition], &nPoints, 
sizeof( 
int ) );
 
  571  wkbPosition += 
sizeof( int );
 
  573  for ( QgsPolyline::const_iterator it = pointList.constBegin(); it != pointList.constEnd(); ++it )
 
  575    memcpy( &( wkb )[wkbPosition], &e, 1 );
 
  577    memcpy( &( wkb )[wkbPosition], &pointType, 
sizeof( 
int ) );
 
  578    wkbPosition += 
sizeof( int );
 
  580    memcpy( &( wkb )[wkbPosition], &x, 
sizeof( 
double ) );
 
  581    wkbPosition += 
sizeof( double );
 
  583    memcpy( &( wkb )[wkbPosition], &y, 
sizeof( 
double ) );
 
  584    wkbPosition += 
sizeof( double );
 
  589      memcpy( &( wkb )[wkbPosition], &z, 
sizeof( 
double ) );
 
  590      wkbPosition += 
sizeof( double );
 
  599QgsGeometry QgsOgcUtils::geometryFromGMLMultiLineString( 
const QDomElement &geometryElement )
 
  611  QList< QgsPolyline > lineCoordinates; 
 
  612  QDomElement currentLineStringElement;
 
  613  QDomNodeList currentCoordList;
 
  614  QDomNodeList currentPosList;
 
  616  const QDomNodeList lineStringMemberList = geometryElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"lineStringMember" ) );
 
  617  if ( !lineStringMemberList.isEmpty() ) 
 
  619    for ( 
int i = 0; i < lineStringMemberList.size(); ++i )
 
  621      const QDomNodeList lineStringNodeList = lineStringMemberList.at( i ).toElement().elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"LineString" ) );
 
  622      if ( lineStringNodeList.size() < 1 )
 
  626      currentLineStringElement = lineStringNodeList.at( 0 ).toElement();
 
  627      currentCoordList = currentLineStringElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"coordinates" ) );
 
  628      if ( !currentCoordList.isEmpty() )
 
  631        if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
 
  635        lineCoordinates.push_back( currentPointList );
 
  639        currentPosList = currentLineStringElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"posList" ) );
 
  640        if ( currentPosList.size() < 1 )
 
  645        if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
 
  649        lineCoordinates.push_back( currentPointList );
 
  655    const QDomNodeList lineStringList = geometryElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"LineString" ) );
 
  656    if ( !lineStringList.isEmpty() ) 
 
  658      for ( 
int i = 0; i < lineStringList.size(); ++i )
 
  660        currentLineStringElement = lineStringList.at( i ).toElement();
 
  661        currentCoordList = currentLineStringElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"coordinates" ) );
 
  662        if ( !currentCoordList.isEmpty() )
 
  665          if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
 
  669          lineCoordinates.push_back( currentPointList );
 
  674          currentPosList = currentLineStringElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"posList" ) );
 
  675          if ( currentPosList.size() < 1 )
 
  680          if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
 
  684          lineCoordinates.push_back( currentPointList );
 
  694  int nLines = lineCoordinates.size();
 
  698  const bool hasZ { !std::isnan( lineCoordinates.first().first().z() ) };
 
  699  const int coordSize { hasZ ? 3 : 2 };
 
  702  int size = 
static_cast<int>( lineCoordinates.size() + 1 ) * ( 1 + 2 * 
sizeof( 
int ) );
 
  703  for ( QList< QgsPolyline >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
 
  705    size += it->size() * coordSize * 
sizeof( double );
 
  709  unsigned char *wkb = 
new unsigned char[size];
 
  712  char e = 
static_cast<char>( htonl( 1 ) != 1 );
 
  716  memcpy( &( wkb )[wkbPosition], &e, 1 );
 
  718  memcpy( &( wkb )[wkbPosition], &type, 
sizeof( 
int ) );
 
  719  wkbPosition += 
sizeof( int );
 
  720  memcpy( &( wkb )[wkbPosition], &nLines, 
sizeof( 
int ) );
 
  721  wkbPosition += 
sizeof( int );
 
  723  for ( QList< QgsPolyline >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
 
  725    memcpy( &( wkb )[wkbPosition], &e, 1 );
 
  727    memcpy( &( wkb )[wkbPosition], &lineType, 
sizeof( 
int ) );
 
  728    wkbPosition += 
sizeof( int );
 
  729    nPoints = it->size();
 
  730    memcpy( &( wkb )[wkbPosition], &nPoints, 
sizeof( 
int ) );
 
  731    wkbPosition += 
sizeof( int );
 
  732    for ( QgsPolyline::const_iterator iter = it->begin(); iter != it->end(); ++iter )
 
  737      memcpy( &( wkb )[wkbPosition], &x, 
sizeof( 
double ) );
 
  738      wkbPosition += 
sizeof( double );
 
  739      memcpy( &( wkb )[wkbPosition], &y, 
sizeof( 
double ) );
 
  740      wkbPosition += 
sizeof( double );
 
  745        memcpy( &( wkb )[wkbPosition], &z, 
sizeof( 
double ) );
 
  746        wkbPosition += 
sizeof( double );
 
  756QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon( 
const QDomElement &geometryElement )
 
  759  QVector<QgsMultiPolyline> multiPolygonPoints;
 
  760  QDomElement currentPolygonMemberElement;
 
  761  QDomNodeList polygonList;
 
  762  QDomElement currentPolygonElement;
 
  764  QDomNodeList outerBoundaryList;
 
  765  QDomElement currentOuterBoundaryElement;
 
  766  QDomElement currentInnerBoundaryElement;
 
  768  QDomNodeList exteriorList;
 
  769  QDomElement currentExteriorElement;
 
  770  QDomElement currentInteriorElement;
 
  772  QDomNodeList linearRingNodeList;
 
  773  QDomElement currentLinearRingElement;
 
  775  QDomNodeList currentCoordinateList;
 
  776  QDomNodeList currentPosList;
 
  778  const QDomNodeList polygonMemberList = geometryElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"polygonMember" ) );
 
  780  for ( 
int i = 0; i < polygonMemberList.size(); ++i )
 
  782    currentPolygonList.resize( 0 ); 
 
  783    currentPolygonMemberElement = polygonMemberList.at( i ).toElement();
 
  784    polygonList = currentPolygonMemberElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"Polygon" ) );
 
  785    if ( polygonList.size() < 1 )
 
  789    currentPolygonElement = polygonList.at( 0 ).toElement();
 
  792    outerBoundaryList = currentPolygonElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"outerBoundaryIs" ) );
 
  793    if ( !outerBoundaryList.isEmpty() )
 
  795      currentOuterBoundaryElement = outerBoundaryList.at( 0 ).toElement();
 
  798      linearRingNodeList = currentOuterBoundaryElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"LinearRing" ) );
 
  799      if ( linearRingNodeList.size() < 1 )
 
  803      currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
 
  804      currentCoordinateList = currentLinearRingElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"coordinates" ) );
 
  805      if ( currentCoordinateList.size() < 1 )
 
  809      if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
 
  813      currentPolygonList.push_back( ringCoordinates );
 
  816      const QDomNodeList innerBoundaryList = currentPolygonElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"innerBoundaryIs" ) );
 
  817      for ( 
int j = 0; j < innerBoundaryList.size(); ++j )
 
  820        currentInnerBoundaryElement = innerBoundaryList.at( j ).toElement();
 
  821        linearRingNodeList = currentInnerBoundaryElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"LinearRing" ) );
 
  822        if ( linearRingNodeList.size() < 1 )
 
  826        currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
 
  827        currentCoordinateList = currentLinearRingElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"coordinates" ) );
 
  828        if ( currentCoordinateList.size() < 1 )
 
  832        if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
 
  836        currentPolygonList.push_back( ringCoordinates );
 
  842      exteriorList = currentPolygonElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"exterior" ) );
 
  843      if ( exteriorList.size() < 1 )
 
  848      currentExteriorElement = exteriorList.at( 0 ).toElement();
 
  851      linearRingNodeList = currentExteriorElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"LinearRing" ) );
 
  852      if ( linearRingNodeList.size() < 1 )
 
  856      currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
 
  857      currentPosList = currentLinearRingElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"posList" ) );
 
  858      if ( currentPosList.size() < 1 )
 
  862      if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
 
  866      currentPolygonList.push_back( ringPositions );
 
  869      const QDomNodeList interiorList = currentPolygonElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"interior" ) );
 
  870      for ( 
int j = 0; j < interiorList.size(); ++j )
 
  873        currentInteriorElement = interiorList.at( j ).toElement();
 
  874        linearRingNodeList = currentInteriorElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"LinearRing" ) );
 
  875        if ( linearRingNodeList.size() < 1 )
 
  879        currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
 
  880        currentPosList = currentLinearRingElement.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"posList" ) );
 
  881        if ( currentPosList.size() < 1 )
 
  885        if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
 
  889        currentPolygonList.push_back( ringPositions );
 
  892    multiPolygonPoints.push_back( currentPolygonList );
 
  895  int nPolygons = multiPolygonPoints.size();
 
  899  const bool hasZ { !std::isnan( multiPolygonPoints.first().first().first().z() ) };
 
  901  int size = 1 + 2 * 
sizeof( int );
 
  904  for ( 
auto it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
 
  906    size += 1 + 2 * 
sizeof( int );
 
  907    for ( 
auto iter = it->begin(); iter != it->end(); ++iter )
 
  909      size += 
static_cast<int>( 
sizeof( int ) ) + ( hasZ ? 3 : 2 ) * 
static_cast<int>( iter->size() * 
sizeof( double ) );
 
  914  unsigned char *wkb = 
new unsigned char[size];
 
  916  char e = 
static_cast<char>( htonl( 1 ) != 1 );
 
  923  memcpy( &( wkb )[wkbPosition], &e, 1 );
 
  925  memcpy( &( wkb )[wkbPosition], &type, 
sizeof( 
int ) );
 
  926  wkbPosition += 
sizeof( int );
 
  927  memcpy( &( wkb )[wkbPosition], &nPolygons, 
sizeof( 
int ) );
 
  928  wkbPosition += 
sizeof( int );
 
  932  for ( 
auto it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
 
  934    memcpy( &( wkb )[wkbPosition], &e, 1 );
 
  936    memcpy( &( wkb )[wkbPosition], &type, 
sizeof( 
int ) );
 
  937    wkbPosition += 
sizeof( int );
 
  939    memcpy( &( wkb )[wkbPosition], &nRings, 
sizeof( 
int ) );
 
  940    wkbPosition += 
sizeof( int );
 
  941    for ( 
auto iter = it->begin(); iter != it->end(); ++iter )
 
  943      nPointsInRing = iter->size();
 
  944      memcpy( &( wkb )[wkbPosition], &nPointsInRing, 
sizeof( 
int ) );
 
  945      wkbPosition += 
sizeof( int );
 
  946      for ( 
auto iterator = iter->begin(); iterator != iter->end(); ++iterator )
 
  950        memcpy( &( wkb )[wkbPosition], &x, 
sizeof( 
double ) );
 
  951        wkbPosition += 
sizeof( double );
 
  952        memcpy( &( wkb )[wkbPosition], &y, 
sizeof( 
double ) );
 
  953        wkbPosition += 
sizeof( double );
 
  956          double z = iterator->z();
 
  957          memcpy( &( wkb )[wkbPosition], &z, 
sizeof( 
double ) );
 
  958          wkbPosition += 
sizeof( double );
 
  969QDomElement QgsOgcUtils::filterElement( QDomDocument &doc, GMLVersion gmlVersion, FilterVersion filterVersion, 
bool GMLUsed )
 
  971  QDomElement filterElem =
 
  973    doc.createElementNS( 
FES_NAMESPACE, QStringLiteral( 
"fes:Filter" ) ) :
 
  974    doc.createElementNS( 
OGC_NAMESPACE, QStringLiteral( 
"ogc:Filter" ) );
 
  978    QDomAttr attr = doc.createAttribute( QStringLiteral( 
"xmlns:gml" ) );
 
  983    filterElem.setAttributeNode( attr );
 
  989bool QgsOgcUtils::readGMLCoordinates( 
QgsPolyline &coords, 
const QDomElement &elem )
 
  991  QString coordSeparator = QStringLiteral( 
"," );
 
  992  QString tupleSeparator = QStringLiteral( 
" " );
 
  997  if ( elem.hasAttribute( QStringLiteral( 
"cs" ) ) )
 
  999    coordSeparator = elem.attribute( QStringLiteral( 
"cs" ) );
 
 1001  if ( elem.hasAttribute( QStringLiteral( 
"ts" ) ) )
 
 1003    tupleSeparator = elem.attribute( QStringLiteral( 
"ts" ) );
 
 1006  const QStringList tupels = elem.text().split( tupleSeparator, Qt::SkipEmptyParts );
 
 1007  QStringList tuple_coords;
 
 1009  bool conversionSuccess;
 
 1011  QStringList::const_iterator it;
 
 1012  for ( it = tupels.constBegin(); it != tupels.constEnd(); ++it )
 
 1014    tuple_coords = ( *it ).split( coordSeparator, Qt::SkipEmptyParts );
 
 1015    if ( tuple_coords.size() < 2 )
 
 1019    x = tuple_coords.at( 0 ).toDouble( &conversionSuccess );
 
 1020    if ( !conversionSuccess )
 
 1024    y = tuple_coords.at( 1 ).toDouble( &conversionSuccess );
 
 1025    if ( !conversionSuccess )
 
 1029    if ( tuple_coords.size() > 2 )
 
 1031      z = tuple_coords.at( 2 ).toDouble( &conversionSuccess );
 
 1032      if ( !conversionSuccess )
 
 1039      z = std::numeric_limits<double>::quiet_NaN();
 
 1041    coords.append( 
QgsPoint( x, y, z ) );
 
 1050  const QDomElement boxElem = boxNode.toElement();
 
 1051  if ( boxElem.tagName() != QLatin1String( 
"Box" ) )
 
 1054  const QDomElement bElem = boxElem.firstChild().toElement();
 
 1055  QString coordSeparator = QStringLiteral( 
"," );
 
 1056  QString tupleSeparator = QStringLiteral( 
" " );
 
 1057  if ( bElem.hasAttribute( QStringLiteral( 
"cs" ) ) )
 
 1059    coordSeparator = bElem.attribute( QStringLiteral( 
"cs" ) );
 
 1061  if ( bElem.hasAttribute( QStringLiteral( 
"ts" ) ) )
 
 1063    tupleSeparator = bElem.attribute( QStringLiteral( 
"ts" ) );
 
 1066  const QString bString = bElem.text();
 
 1067  bool ok1, ok2, ok3, ok4;
 
 1068  const double xmin = bString.section( tupleSeparator, 0, 0 ).section( coordSeparator, 0, 0 ).toDouble( &ok1 );
 
 1069  const double ymin = bString.section( tupleSeparator, 0, 0 ).section( coordSeparator, 1, 1 ).toDouble( &ok2 );
 
 1070  const double xmax = bString.section( tupleSeparator, 1, 1 ).section( coordSeparator, 0, 0 ).toDouble( &ok3 );
 
 1071  const double ymax = bString.section( tupleSeparator, 1, 1 ).section( coordSeparator, 1, 1 ).toDouble( &ok4 );
 
 1073  if ( ok1 && ok2 && ok3 && ok4 )
 
 
 1082bool QgsOgcUtils::readGMLPositions( 
QgsPolyline &coords, 
const QDomElement &elem )
 
 1086  const QStringList pos = elem.text().split( 
' ', Qt::SkipEmptyParts );
 
 1088  bool conversionSuccess;
 
 1089  const int posSize = pos.size();
 
 1091  int srsDimension = 2;
 
 1092  if ( elem.hasAttribute( QStringLiteral( 
"srsDimension" ) ) )
 
 1094    srsDimension = elem.attribute( QStringLiteral( 
"srsDimension" ) ).toInt( &conversionSuccess );
 
 1095    if ( !conversionSuccess )
 
 1100  else if ( elem.hasAttribute( QStringLiteral( 
"dimension" ) ) )
 
 1102    srsDimension = elem.attribute( QStringLiteral( 
"dimension" ) ).toInt( &conversionSuccess );
 
 1103    if ( !conversionSuccess )
 
 1109  for ( 
int i = 0; i < posSize / srsDimension; i++ )
 
 1111    x = pos.at( i * srsDimension ).toDouble( &conversionSuccess );
 
 1112    if ( !conversionSuccess )
 
 1116    y = pos.at( i * srsDimension + 1 ).toDouble( &conversionSuccess );
 
 1117    if ( !conversionSuccess )
 
 1121    if ( srsDimension > 2 )
 
 1123      z = pos.at( i * srsDimension + 2 ).toDouble( &conversionSuccess );
 
 1124      if ( !conversionSuccess )
 
 1131      z = std::numeric_limits<double>::quiet_NaN();
 
 1133    coords.append( 
QgsPoint( x, y, z ) );
 
 1143  const QDomElement envelopeElem = envelopeNode.toElement();
 
 1144  if ( envelopeElem.tagName() != QLatin1String( 
"Envelope" ) )
 
 1147  const QDomNodeList lowerCornerList = envelopeElem.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"lowerCorner" ) );
 
 1148  if ( lowerCornerList.size() < 1 )
 
 1151  const QDomNodeList upperCornerList = envelopeElem.elementsByTagNameNS( 
GML_NAMESPACE, QStringLiteral( 
"upperCorner" ) );
 
 1152  if ( upperCornerList.size() < 1 )
 
 1155  bool conversionSuccess;
 
 1156  int srsDimension = 2;
 
 1158  QDomElement elem = lowerCornerList.at( 0 ).toElement();
 
 1159  if ( elem.hasAttribute( QStringLiteral( 
"srsDimension" ) ) )
 
 1161    srsDimension = elem.attribute( QStringLiteral( 
"srsDimension" ) ).toInt( &conversionSuccess );
 
 1162    if ( !conversionSuccess )
 
 1167  else if ( elem.hasAttribute( QStringLiteral( 
"dimension" ) ) )
 
 1169    srsDimension = elem.attribute( QStringLiteral( 
"dimension" ) ).toInt( &conversionSuccess );
 
 1170    if ( !conversionSuccess )
 
 1175  QString bString = elem.text();
 
 1177  const double xmin = bString.section( 
' ', 0, 0 ).toDouble( &conversionSuccess );
 
 1178  if ( !conversionSuccess )
 
 1180  const double ymin = bString.section( 
' ', 1, 1 ).toDouble( &conversionSuccess );
 
 1181  if ( !conversionSuccess )
 
 1184  elem = upperCornerList.at( 0 ).toElement();
 
 1185  if ( elem.hasAttribute( QStringLiteral( 
"srsDimension" ) ) )
 
 1187    srsDimension = elem.attribute( QStringLiteral( 
"srsDimension" ) ).toInt( &conversionSuccess );
 
 1188    if ( !conversionSuccess )
 
 1193  else if ( elem.hasAttribute( QStringLiteral( 
"dimension" ) ) )
 
 1195    srsDimension = elem.attribute( QStringLiteral( 
"dimension" ) ).toInt( &conversionSuccess );
 
 1196    if ( !conversionSuccess )
 
 1202  Q_UNUSED( srsDimension )
 
 1204  bString = elem.text();
 
 1205  const double xmax = bString.section( 
' ', 0, 0 ).toDouble( &conversionSuccess );
 
 1206  if ( !conversionSuccess )
 
 1208  const double ymax = bString.section( 
' ', 1, 1 ).toDouble( &conversionSuccess );
 
 1209  if ( !conversionSuccess )
 
 
 1225    bool invertAxisOrientation,
 
 1230    return QDomElement();
 
 1233  QDomElement boxElem = doc.createElement( QStringLiteral( 
"gml:Box" ) );
 
 1236    boxElem.setAttribute( QStringLiteral( 
"srsName" ), 
srsName );
 
 1238  QDomElement coordElem = doc.createElement( QStringLiteral( 
"gml:coordinates" ) );
 
 1239  coordElem.setAttribute( QStringLiteral( 
"cs" ), QStringLiteral( 
"," ) );
 
 1240  coordElem.setAttribute( QStringLiteral( 
"ts" ), QStringLiteral( 
" " ) );
 
 1242  QString coordString;
 
 1251  const QDomText coordText = doc.createTextNode( coordString );
 
 1252  coordElem.appendChild( coordText );
 
 1253  boxElem.appendChild( coordElem );
 
 
 1265    bool invertAxisOrientation,
 
 1270    return QDomElement();
 
 1273  QDomElement envElem = doc.createElement( QStringLiteral( 
"gml:Envelope" ) );
 
 1276    envElem.setAttribute( QStringLiteral( 
"srsName" ), 
srsName );
 
 1280  QDomElement lowerCornerElem = doc.createElement( QStringLiteral( 
"gml:lowerCorner" ) );
 
 1284  const QDomText lowerCornerText = doc.createTextNode( posList );
 
 1285  lowerCornerElem.appendChild( lowerCornerText );
 
 1286  envElem.appendChild( lowerCornerElem );
 
 1288  QDomElement upperCornerElem = doc.createElement( QStringLiteral( 
"gml:upperCorner" ) );
 
 1292  const QDomText upperCornerText = doc.createTextNode( posList );
 
 1293  upperCornerElem.appendChild( upperCornerText );
 
 1294  envElem.appendChild( upperCornerElem );
 
 
 1308                                        bool invertAxisOrientation,
 
 1309                                        const QString &gmlIdBase,
 
 1313    return QDomElement();
 
 1316  QString cs = QStringLiteral( 
"," );
 
 1318  const QString ts = QStringLiteral( 
" " );
 
 1320  QDomElement baseCoordElem;
 
 1322  bool hasZValue = 
false;
 
 1324  const QByteArray wkb( geometry.
asWkb() );
 
 1334    return QDomElement();
 
 1347        baseCoordElem = doc.createElement( QStringLiteral( 
"gml:pos" ) );
 
 1350        baseCoordElem = doc.createElement( QStringLiteral( 
"gml:posList" ) );
 
 1357    baseCoordElem = doc.createElement( QStringLiteral( 
"gml:coordinates" ) );
 
 1358    baseCoordElem.setAttribute( QStringLiteral( 
"cs" ), cs );
 
 1359    baseCoordElem.setAttribute( QStringLiteral( 
"ts" ), ts );
 
 1373        QDomElement pointElem = doc.createElement( QStringLiteral( 
"gml:Point" ) );
 
 1374        if ( gmlVersion == 
GML_3_2_1 && !gmlIdBase.isEmpty() )
 
 1375          pointElem.setAttribute( QStringLiteral( 
"gml:id" ), gmlIdBase );
 
 1377          pointElem.setAttribute( QStringLiteral( 
"srsName" ), 
srsName );
 
 1378        QDomElement coordElem = baseCoordElem.cloneNode().toElement();
 
 1382        if ( invertAxisOrientation )
 
 1396        const QDomText coordText = doc.createTextNode( coordString );
 
 1398        coordElem.appendChild( coordText );
 
 1400          coordElem.setAttribute( QStringLiteral( 
"srsDimension" ), hasZValue ? QStringLiteral( 
"3" ) : QStringLiteral( 
"2" ) );
 
 1401        pointElem.appendChild( coordElem );
 
 1411        QDomElement multiPointElem = doc.createElement( QStringLiteral( 
"gml:MultiPoint" ) );
 
 1412        if ( gmlVersion == 
GML_3_2_1 && !gmlIdBase.isEmpty() )
 
 1413          multiPointElem.setAttribute( QStringLiteral( 
"gml:id" ), gmlIdBase );
 
 1415          multiPointElem.setAttribute( QStringLiteral( 
"srsName" ), 
srsName );
 
 1420        for ( 
int idx = 0; idx < nPoints; ++idx )
 
 1422          QDomElement pointMemberElem = doc.createElement( QStringLiteral( 
"gml:pointMember" ) );
 
 1423          QDomElement pointElem = doc.createElement( QStringLiteral( 
"gml:Point" ) );
 
 1424          if ( gmlVersion == 
GML_3_2_1 && !gmlIdBase.isEmpty() )
 
 1425            pointElem.setAttribute( QStringLiteral( 
"gml:id" ), gmlIdBase + QStringLiteral( 
".%1" ).arg( idx + 1 ) );
 
 1426          QDomElement coordElem = baseCoordElem.cloneNode().toElement();
 
 1432          if ( invertAxisOrientation )
 
 1446          const QDomText coordText = doc.createTextNode( coordString );
 
 1448          coordElem.appendChild( coordText );
 
 1450            coordElem.setAttribute( QStringLiteral( 
"srsDimension" ), hasZValue ? QStringLiteral( 
"3" ) : QStringLiteral( 
"2" ) );
 
 1451          pointElem.appendChild( coordElem );
 
 1454          pointMemberElem.appendChild( pointElem );
 
 1455          multiPointElem.appendChild( pointMemberElem );
 
 1457        return multiPointElem;
 
 1466        QDomElement lineStringElem = doc.createElement( QStringLiteral( 
"gml:LineString" ) );
 
 1467        if ( gmlVersion == 
GML_3_2_1 && !gmlIdBase.isEmpty() )
 
 1468          lineStringElem.setAttribute( QStringLiteral( 
"gml:id" ), gmlIdBase );
 
 1470          lineStringElem.setAttribute( QStringLiteral( 
"srsName" ), 
srsName );
 
 1476        QDomElement coordElem = baseCoordElem.cloneNode().toElement();
 
 1477        QString coordString;
 
 1478        for ( 
int idx = 0; idx < nPoints; ++idx )
 
 1487          if ( invertAxisOrientation )
 
 1501        const QDomText coordText = doc.createTextNode( coordString );
 
 1502        coordElem.appendChild( coordText );
 
 1504          coordElem.setAttribute( QStringLiteral( 
"srsDimension" ), hasZValue ? QStringLiteral( 
"3" ) : QStringLiteral( 
"2" ) );
 
 1505        lineStringElem.appendChild( coordElem );
 
 1506        return lineStringElem;
 
 1515        QDomElement multiLineStringElem = doc.createElement( QStringLiteral( 
"gml:MultiLineString" ) );
 
 1516        if ( gmlVersion == 
GML_3_2_1 && !gmlIdBase.isEmpty() )
 
 1517          multiLineStringElem.setAttribute( QStringLiteral( 
"gml:id" ), gmlIdBase );
 
 1519          multiLineStringElem.setAttribute( QStringLiteral( 
"srsName" ), 
srsName );
 
 1524        for ( 
int jdx = 0; jdx < nLines; jdx++ )
 
 1526          QDomElement lineStringMemberElem = doc.createElement( QStringLiteral( 
"gml:lineStringMember" ) );
 
 1527          QDomElement lineStringElem = doc.createElement( QStringLiteral( 
"gml:LineString" ) );
 
 1528          if ( gmlVersion == 
GML_3_2_1 && !gmlIdBase.isEmpty() )
 
 1529            lineStringElem.setAttribute( QStringLiteral( 
"gml:id" ), gmlIdBase + QStringLiteral( 
".%1" ).arg( jdx + 1 ) );
 
 1536          QDomElement coordElem = baseCoordElem.cloneNode().toElement();
 
 1537          QString coordString;
 
 1538          for ( 
int idx = 0; idx < nPoints; idx++ )
 
 1547            if ( invertAxisOrientation )
 
 1562          const QDomText coordText = doc.createTextNode( coordString );
 
 1563          coordElem.appendChild( coordText );
 
 1565            coordElem.setAttribute( QStringLiteral( 
"srsDimension" ), hasZValue ? QStringLiteral( 
"3" ) : QStringLiteral( 
"2" ) );
 
 1566          lineStringElem.appendChild( coordElem );
 
 1567          lineStringMemberElem.appendChild( lineStringElem );
 
 1568          multiLineStringElem.appendChild( lineStringMemberElem );
 
 1570        return multiLineStringElem;
 
 1579        QDomElement polygonElem = doc.createElement( QStringLiteral( 
"gml:Polygon" ) );
 
 1580        if ( gmlVersion == 
GML_3_2_1 && !gmlIdBase.isEmpty() )
 
 1581          polygonElem.setAttribute( QStringLiteral( 
"gml:id" ), gmlIdBase );
 
 1583          polygonElem.setAttribute( QStringLiteral( 
"srsName" ), 
srsName );
 
 1589        if ( numRings == 0 ) 
 
 1590          return QDomElement();
 
 1592        for ( 
int idx = 0; idx < numRings; idx++ )
 
 1594          QString boundaryName = ( gmlVersion == 
GML_2_1_2 ) ? 
"gml:outerBoundaryIs" : 
"gml:exterior";
 
 1597            boundaryName = ( gmlVersion == 
GML_2_1_2 ) ? 
"gml:innerBoundaryIs" : 
"gml:interior";
 
 1599          QDomElement boundaryElem = doc.createElement( boundaryName );
 
 1600          QDomElement ringElem = doc.createElement( QStringLiteral( 
"gml:LinearRing" ) );
 
 1605          QDomElement coordElem = baseCoordElem.cloneNode().toElement();
 
 1606          QString coordString;
 
 1607          for ( 
int jdx = 0; jdx < nPoints; jdx++ )
 
 1616            if ( invertAxisOrientation )
 
 1630          const QDomText coordText = doc.createTextNode( coordString );
 
 1631          coordElem.appendChild( coordText );
 
 1633            coordElem.setAttribute( QStringLiteral( 
"srsDimension" ), hasZValue ? QStringLiteral( 
"3" ) : QStringLiteral( 
"2" ) );
 
 1634          ringElem.appendChild( coordElem );
 
 1635          boundaryElem.appendChild( ringElem );
 
 1636          polygonElem.appendChild( boundaryElem );
 
 1648        QDomElement multiPolygonElem = doc.createElement( QStringLiteral( 
"gml:MultiPolygon" ) );
 
 1649        if ( gmlVersion == 
GML_3_2_1 && !gmlIdBase.isEmpty() )
 
 1650          multiPolygonElem.setAttribute( QStringLiteral( 
"gml:id" ), gmlIdBase );
 
 1652          multiPolygonElem.setAttribute( QStringLiteral( 
"srsName" ), 
srsName );
 
 1655        wkbPtr >> numPolygons;
 
 1657        for ( 
int kdx = 0; kdx < numPolygons; kdx++ )
 
 1659          QDomElement polygonMemberElem = doc.createElement( QStringLiteral( 
"gml:polygonMember" ) );
 
 1660          QDomElement polygonElem = doc.createElement( QStringLiteral( 
"gml:Polygon" ) );
 
 1661          if ( gmlVersion == 
GML_3_2_1 && !gmlIdBase.isEmpty() )
 
 1662            polygonElem.setAttribute( QStringLiteral( 
"gml:id" ), gmlIdBase + QStringLiteral( 
".%1" ).arg( kdx + 1 ) );
 
 1669          for ( 
int idx = 0; idx < numRings; idx++ )
 
 1671            QString boundaryName = ( gmlVersion == 
GML_2_1_2 ) ? 
"gml:outerBoundaryIs" : 
"gml:exterior";
 
 1674              boundaryName = ( gmlVersion == 
GML_2_1_2 ) ? 
"gml:innerBoundaryIs" : 
"gml:interior";
 
 1676            QDomElement boundaryElem = doc.createElement( boundaryName );
 
 1677            QDomElement ringElem = doc.createElement( QStringLiteral( 
"gml:LinearRing" ) );
 
 1682            QDomElement coordElem = baseCoordElem.cloneNode().toElement();
 
 1683            QString coordString;
 
 1684            for ( 
int jdx = 0; jdx < nPoints; jdx++ )
 
 1693              if ( invertAxisOrientation )
 
 1708            const QDomText coordText = doc.createTextNode( coordString );
 
 1709            coordElem.appendChild( coordText );
 
 1711              coordElem.setAttribute( QStringLiteral( 
"srsDimension" ), hasZValue ? QStringLiteral( 
"3" ) : QStringLiteral( 
"2" ) );
 
 1712            ringElem.appendChild( coordElem );
 
 1713            boundaryElem.appendChild( ringElem );
 
 1714            polygonElem.appendChild( boundaryElem );
 
 1715            polygonMemberElem.appendChild( polygonElem );
 
 1716            multiPolygonElem.appendChild( polygonMemberElem );
 
 1719        return multiPolygonElem;
 
 1722        return QDomElement();
 
 1728    return QDomElement();
 
 
 1737QDomElement QgsOgcUtils::createGMLCoordinates( 
const QgsPolylineXY &points, QDomDocument &doc )
 
 1739  QDomElement coordElem = doc.createElement( QStringLiteral( 
"gml:coordinates" ) );
 
 1740  coordElem.setAttribute( QStringLiteral( 
"cs" ), QStringLiteral( 
"," ) );
 
 1741  coordElem.setAttribute( QStringLiteral( 
"ts" ), QStringLiteral( 
" " ) );
 
 1743  QString coordString;
 
 1744  QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
 
 1745  for ( ; pointIt != points.constEnd(); ++pointIt )
 
 1747    if ( pointIt != points.constBegin() )
 
 1756  const QDomText coordText = doc.createTextNode( coordString );
 
 1757  coordElem.appendChild( coordText );
 
 1761QDomElement QgsOgcUtils::createGMLPositions( 
const QgsPolylineXY &points, QDomDocument &doc )
 
 1763  QDomElement posElem = doc.createElement( QStringLiteral( 
"gml:pos" ) );
 
 1764  if ( points.size() > 1 )
 
 1765    posElem = doc.createElement( QStringLiteral( 
"gml:posList" ) );
 
 1766  posElem.setAttribute( QStringLiteral( 
"srsDimension" ), QStringLiteral( 
"2" ) );
 
 1768  QString coordString;
 
 1769  QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
 
 1770  for ( ; pointIt != points.constEnd(); ++pointIt )
 
 1772    if ( pointIt != points.constBegin() )
 
 1781  const QDomText coordText = doc.createTextNode( coordString );
 
 1782  posElem.appendChild( coordText );
 
 1792  if ( fillElement.isNull() || !fillElement.hasChildNodes() )
 
 1800  QDomElement cssElem = fillElement.firstChildElement( QStringLiteral( 
"CssParameter" ) );
 
 1801  while ( !cssElem.isNull() )
 
 1803    cssName = cssElem.attribute( QStringLiteral( 
"name" ), QStringLiteral( 
"not_found" ) );
 
 1804    if ( cssName != QLatin1String( 
"not_found" ) )
 
 1806      elemText = cssElem.text();
 
 1807      if ( cssName == QLatin1String( 
"fill" ) )
 
 1809        color.setNamedColor( elemText );
 
 1811      else if ( cssName == QLatin1String( 
"fill-opacity" ) )
 
 1814        const double opacity = elemText.toDouble( &ok );
 
 1817          color.setAlphaF( opacity );
 
 1822    cssElem = cssElem.nextSiblingElement( QStringLiteral( 
"CssParameter" ) );
 
 
 1836  if ( element.isNull() || !element.hasChildNodes() )
 
 1843  if ( element.firstChild().nodeType() == QDomNode::TextNode )
 
 1853  QDomElement childElem = element.firstChildElement();
 
 1854  while ( !childElem.isNull() )
 
 1866    if ( !expr->d->mRootNode )
 
 1868      expr->d->mRootNode.reset( node );
 
 1875    childElem = childElem.nextSiblingElement();
 
 1879  expr->d->mExp = expr->
dump();
 
 
 1905static 
int binaryOperatorFromTagName( const QString &tagName )
 
 1908  return BINARY_OPERATORS_TAG_NAMES_MAP()->value( tagName, -1 );
 
 
 1915    return QStringLiteral( 
"PropertyIsLike" );
 
 1917  return BINARY_OPERATORS_TAG_NAMES_MAP()->key( op, QString() );
 
 1920static bool isBinaryOperator( 
const QString &tagName )
 
 1922  return binaryOperatorFromTagName( tagName ) >= 0;
 
 1926static bool isSpatialOperator( 
const QString &tagName )
 
 1928  static QStringList spatialOps;
 
 1929  if ( spatialOps.isEmpty() )
 
 1931    spatialOps << QStringLiteral( 
"BBOX" ) << QStringLiteral( 
"Intersects" ) << QStringLiteral( 
"Contains" ) << QStringLiteral( 
"Crosses" ) << QStringLiteral( 
"Equals" )
 
 1932               << QStringLiteral( 
"Disjoint" ) << QStringLiteral( 
"Overlaps" ) << QStringLiteral( 
"Touches" ) << QStringLiteral( 
"Within" );
 
 1935  return spatialOps.contains( tagName );
 
 1942  errorMessage = utils.errorMessage();
 
 1950  errorMessage = utils.errorMessage();
 
 1958  errorMessage = utils.errorMessage();
 
 1966  errorMessage = utils.errorMessage();
 
 1974  errorMessage = utils.errorMessage();
 
 1982  errorMessage = utils.errorMessage();
 
 1990  errorMessage = utils.errorMessage();
 
 1994QgsExpressionNode *QgsOgcUtils::nodeIsBetweenFromOgcFilter( QDomElement &element, QString &errorMessage )
 
 1998  errorMessage = utils.errorMessage();
 
 2006  errorMessage = utils.errorMessage();
 
 2017                                QStringLiteral( 
"geometry" ), QString(), 
false, 
false, errorMessage );
 
 
 2023                                    QStringLiteral( 
"geometry" ), QString(), 
false, 
false, errorMessage, requiresFilterElement );
 
 
 2028  return doc.createElementNS( 
SE_NAMESPACE, QStringLiteral( 
"se:ElseFilter" ) );
 
 
 2036    const QString &namespacePrefix,
 
 2037    const QString &namespaceURI,
 
 2040    bool honourAxisOrientation,
 
 2041    bool invertAxisOrientation,
 
 2042    QString *errorMessage,
 
 2043    const QMap<QString, QString> &fieldNameToXPathMap,
 
 2044    const QMap<QString, QString> &namespacePrefixToUriMap )
 
 2047    return QDomElement();
 
 2053  QgsOgcUtilsExprToFilter utils( doc, gmlVersion, filterVersion, namespacePrefix, namespaceURI, 
geometryName, 
srsName, honourAxisOrientation, invertAxisOrientation, fieldNameToXPathMap, namespacePrefixToUriMap );
 
 2057  if ( exprRootElem.isNull() )
 
 2058    return QDomElement();
 
 2060  QDomElement filterElem = filterElement( doc, gmlVersion, filterVersion, utils.
GMLNamespaceUsed() );
 
 2062  if ( !namespacePrefix.isEmpty() && !namespaceURI.isEmpty() )
 
 2064    QDomAttr attr = doc.createAttribute( QStringLiteral( 
"xmlns:" ) + namespacePrefix );
 
 2065    attr.setValue( namespaceURI );
 
 2066    filterElem.setAttributeNode( attr );
 
 2069  filterElem.appendChild( exprRootElem );
 
 
 2079    bool honourAxisOrientation,
 
 2080    bool invertAxisOrientation,
 
 2081    QString *errorMessage,
 
 2082    bool requiresFilterElement,
 
 2083    const QMap<QString, QString> &fieldNameToXPathMap,
 
 2084    const QMap<QString, QString> &namespacePrefixToUriMap )
 
 2093    return QDomElement();
 
 2102      QgsOgcUtilsExprToFilter utils( doc, gmlVersion, filterVersion, QString(), QString(), 
geometryName, 
srsName, honourAxisOrientation, invertAxisOrientation, fieldNameToXPathMap, namespacePrefixToUriMap );
 
 2108      if ( !exprRootElem.isNull() )
 
 2110        if ( requiresFilterElement )
 
 2112          QDomElement filterElem = filterElement( doc, gmlVersion, filterVersion, utils.
GMLNamespaceUsed() );
 
 2114          filterElem.appendChild( exprRootElem );
 
 2117        return exprRootElem;
 
 2124        *errorMessage = QObject::tr( 
"Node type not supported in expression translation: %1" ).arg( node->
nodeType() );
 
 2128  return QDomElement();
 
 
 2135    const QList<LayerProperties> &layerProperties,
 
 2136    bool honourAxisOrientation,
 
 2137    bool invertAxisOrientation,
 
 2138    const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename,
 
 2139    QString *errorMessage,
 
 2140    const QMap<QString, QString> &fieldNameToXPathMap,
 
 2141    const QMap<QString, QString> &namespacePrefixToUriMap )
 
 2144    return QDomElement();
 
 2147                                         layerProperties, honourAxisOrientation, invertAxisOrientation,
 
 2148                                         mapUnprefixedTypenameToPrefixedTypename, fieldNameToXPathMap, namespacePrefixToUriMap );
 
 2152  if ( exprRootElem.isNull() )
 
 2153    return QDomElement();
 
 2155  QDomElement filterElem = filterElement( doc, gmlVersion, filterVersion, utils.
GMLNamespaceUsed() );
 
 2157  QSet<QString> setNamespaceURI;
 
 2160    if ( !props.mNamespacePrefix.isEmpty() && !props.mNamespaceURI.isEmpty() &&
 
 2161         !setNamespaceURI.contains( props.mNamespaceURI ) )
 
 2163      setNamespaceURI.insert( props.mNamespaceURI );
 
 2164      QDomAttr attr = doc.createAttribute( QStringLiteral( 
"xmlns:" ) + props.mNamespacePrefix );
 
 2165      attr.setValue( props.mNamespaceURI );
 
 2166      filterElem.setAttributeNode( attr );
 
 2169  filterElem.appendChild( exprRootElem );
 
 
 2194      mErrorMessage = QObject::tr( 
"Node type not supported: %1" ).arg( node->
nodeType() );
 
 2195      return QDomElement();
 
 
 2202  if ( !mErrorMessage.isEmpty() )
 
 2203    return QDomElement();
 
 2206  switch ( node->
op() )
 
 2209      uoElem = mDoc.createElement( mFilterPrefix + 
":Literal" );
 
 2214        uoElem.appendChild( mDoc.createTextNode( 
"-" + operandElem.text() ) );
 
 2215        mDoc.removeChild( operandElem );
 
 2219        mErrorMessage = QObject::tr( 
"This use of unary operator not implemented yet" );
 
 2220        return QDomElement();
 
 2224      uoElem = mDoc.createElement( mFilterPrefix + 
":Not" );
 
 2225      uoElem.appendChild( operandElem );
 
 2229      mErrorMessage = QObject::tr( 
"Unary operator '%1' not implemented yet" ).arg( node->
text() );
 
 2230      return QDomElement();
 
 2240  if ( !mErrorMessage.isEmpty() )
 
 2241    return QDomElement();
 
 2254        QDomElement elem = mDoc.createElement( mFilterPrefix + 
":PropertyIsNull" );
 
 2255        elem.appendChild( leftElem );
 
 2259          QDomElement notElem = mDoc.createElement( mFilterPrefix + 
":Not" );
 
 2260          notElem.appendChild( elem );
 
 2274  if ( !mErrorMessage.isEmpty() )
 
 2275    return QDomElement();
 
 2278  const QString opText = binaryOperatorToTagName( op );
 
 2279  if ( opText.isEmpty() )
 
 2283    mErrorMessage = QObject::tr( 
"Binary operator %1 not implemented yet" ).arg( node->
text() );
 
 2284    return QDomElement();
 
 2287  QDomElement boElem = mDoc.createElement( mFilterPrefix + 
":" + opText );
 
 2292      boElem.setAttribute( QStringLiteral( 
"matchCase" ), QStringLiteral( 
"false" ) );
 
 2295    boElem.setAttribute( QStringLiteral( 
"wildCard" ), QStringLiteral( 
"%" ) );
 
 2296    boElem.setAttribute( QStringLiteral( 
"singleChar" ), QStringLiteral( 
"_" ) );
 
 2298      boElem.setAttribute( QStringLiteral( 
"escape" ), QStringLiteral( 
"\\" ) );
 
 2300      boElem.setAttribute( QStringLiteral( 
"escapeChar" ), QStringLiteral( 
"\\" ) );
 
 2303  boElem.appendChild( leftElem );
 
 2304  boElem.appendChild( rightElem );
 
 2311  Q_UNUSED( expression )
 
 2314  switch ( node->
value().userType() )
 
 2316    case QMetaType::Type::Int:
 
 2317      value = QString::number( node->
value().toInt() );
 
 2319    case QMetaType::Type::Double:
 
 2322    case QMetaType::Type::QString:
 
 2323      value = node->
value().toString();
 
 2325    case QMetaType::Type::QDate:
 
 2326      value = node->
value().toDate().toString( Qt::ISODate );
 
 2328    case QMetaType::Type::QDateTime:
 
 2329      value = node->
value().toDateTime().toString( Qt::ISODate );
 
 2333      mErrorMessage = QObject::tr( 
"Literal type not supported: %1" ).arg( 
static_cast<QMetaType::Type
>( node->
value().userType() ) );
 
 2334      return QDomElement();
 
 2337  QDomElement litElem = mDoc.createElement( mFilterPrefix + 
":Literal" );
 
 2338  litElem.appendChild( mDoc.createTextNode( value ) );
 
 2345  Q_UNUSED( expression )
 
 2347  QDomElement propElem = mDoc.createElement( mFilterPrefix + 
":" + mPropertyName );
 
 2348  if ( !mFieldNameToXPathMap.isEmpty() )
 
 2350    const auto iterFieldName = mFieldNameToXPathMap.constFind( node->
name() );
 
 2351    if ( iterFieldName != mFieldNameToXPathMap.constEnd() )
 
 2353      const QString xpath( *iterFieldName );
 
 2355      if ( !mNamespacePrefixToUriMap.isEmpty() )
 
 2357        const QStringList parts = xpath.split( 
'/' );
 
 2358        QSet<QString> setNamespacePrefix;
 
 2359        for ( 
const QString &part : std::as_const( parts ) )
 
 2361          const QStringList subparts = part.split( 
':' );
 
 2362          if ( subparts.size() == 2 && !setNamespacePrefix.contains( subparts[0] ) )
 
 2364            const auto iterNamespacePrefix = mNamespacePrefixToUriMap.constFind( subparts[0] );
 
 2365            if ( iterNamespacePrefix != mNamespacePrefixToUriMap.constEnd() )
 
 2367              setNamespacePrefix.insert( subparts[0] );
 
 2368              QDomAttr attr = mDoc.createAttribute( QStringLiteral( 
"xmlns:" ) +  subparts[0] );
 
 2369              attr.setValue( *iterNamespacePrefix );
 
 2370              propElem.setAttributeNode( attr );
 
 2376      propElem.appendChild( mDoc.createTextNode( xpath ) );
 
 2381  QString columnRef( node->
name() );
 
 2382  if ( !mNamespacePrefix.isEmpty() && !mNamespaceURI.isEmpty() )
 
 2383    columnRef =  mNamespacePrefix + QStringLiteral( 
":" ) + columnRef;
 
 2384  propElem.appendChild( mDoc.createTextNode( columnRef ) );
 
 2392  if ( node->
list()->
list().size() == 1 )
 
 2396    QDomElement eqElem = mDoc.createElement( mFilterPrefix + 
":PropertyIsEqualTo" );
 
 2397    eqElem.appendChild( leftNode );
 
 2398    eqElem.appendChild( firstListNode );
 
 2401      QDomElement notElem = mDoc.createElement( mFilterPrefix + 
":Not" );
 
 2402      notElem.appendChild( eqElem );
 
 2408  QDomElement orElem = mDoc.createElement( mFilterPrefix + 
":Or" );
 
 2411  const auto constList = node->
list()->
list();
 
 2415    if ( !mErrorMessage.isEmpty() )
 
 2416      return QDomElement();
 
 2418    QDomElement eqElem = mDoc.createElement( mFilterPrefix + 
":PropertyIsEqualTo" );
 
 2419    eqElem.appendChild( leftNode.cloneNode() );
 
 2420    eqElem.appendChild( listNode );
 
 2422    orElem.appendChild( eqElem );
 
 2427    QDomElement notElem = mDoc.createElement( mFilterPrefix + 
":Not" );
 
 2428    notElem.appendChild( orElem );
 
 2437  { QLatin1String( 
"disjoint" ),   QLatin1String( 
"Disjoint" ) },
 
 2438  { QLatin1String( 
"intersects" ), QLatin1String( 
"Intersects" )},
 
 2439  { QLatin1String( 
"touches" ),    QLatin1String( 
"Touches" ) },
 
 2440  { QLatin1String( 
"crosses" ),    QLatin1String( 
"Crosses" ) },
 
 2441  { QLatin1String( 
"contains" ),   QLatin1String( 
"Contains" ) },
 
 2442  { QLatin1String( 
"overlaps" ),   QLatin1String( 
"Overlaps" ) },
 
 2443  { QLatin1String( 
"within" ),     QLatin1String( 
"Within" ) }
 
 2446static 
bool isBinarySpatialOperator( const QString &fnName )
 
 2448  return BINARY_SPATIAL_OPS_MAP()->contains( fnName );
 
 
 2451static QString tagNameForSpatialOperator( 
const QString &fnName )
 
 2453  return BINARY_SPATIAL_OPS_MAP()->value( fnName );
 
 2463  return fd->
name() == QLatin1String( 
"$geometry" ) || ( fd->
name() == QLatin1String( 
"var" ) && fn->
referencedVariables().contains( QLatin1String( 
"geometry" ) ) );
 
 2475    if ( fnDef->
name() == QLatin1String( 
"geom_from_wkt" ) )
 
 2477      const QList<QgsExpressionNode *> &args = fnNode->
args()->
list();
 
 2493  if ( fd->
name() == QLatin1String( 
"intersects_bbox" ) )
 
 2495    QList<QgsExpressionNode *> argNodes = node->
args()->
list();
 
 2496    Q_ASSERT( argNodes.count() == 2 ); 
 
 2498    const QgsGeometry geom = geometryFromConstExpr( argNodes[1] );
 
 2499    if ( !geom.
isNull() && isGeometryColumn( argNodes[0] ) )
 
 2509      QDomElement funcElem = mDoc.createElement( mFilterPrefix + 
":BBOX" );
 
 2511      if ( !mGeometryName.isEmpty() )
 
 2514        QDomElement geomProperty = mDoc.createElement( mFilterPrefix + 
":" + mPropertyName );
 
 2515        QString columnRef( mGeometryName );
 
 2516        if ( !mNamespacePrefix.isEmpty() && !mNamespaceURI.isEmpty() )
 
 2517          columnRef =  mNamespacePrefix + QStringLiteral( 
":" ) + columnRef;
 
 2518        geomProperty.appendChild( mDoc.createTextNode( columnRef ) );
 
 2520        funcElem.appendChild( geomProperty );
 
 2522      funcElem.appendChild( elemBox );
 
 2527      mErrorMessage = QObject::tr( 
"<BBOX> is currently supported only in form: bbox(@geometry, geomFromWKT('…'))" );
 
 2528      return QDomElement();
 
 2532  if ( isBinarySpatialOperator( fd->
name() ) )
 
 2534    QList<QgsExpressionNode *> argNodes = node->
args()->
list();
 
 2535    Q_ASSERT( argNodes.count() == 2 ); 
 
 2538    if ( isGeometryColumn( argNodes[0] ) )
 
 2539      otherNode = argNodes[1];
 
 2540    else if ( isGeometryColumn( argNodes[1] ) )
 
 2541      otherNode = argNodes[0];
 
 2544      mErrorMessage = QObject::tr( 
"Unable to translate spatial operator: at least one must refer to geometry." );
 
 2545      return QDomElement();
 
 2548    QDomElement otherGeomElem;
 
 2553      mErrorMessage = QObject::tr( 
"spatial operator: the other operator must be a geometry constructor function" );
 
 2554      return QDomElement();
 
 2559    if ( otherFnDef->
name() == QLatin1String( 
"geom_from_wkt" ) )
 
 2564        mErrorMessage = QObject::tr( 
"geom_from_wkt: argument must be string literal" );
 
 2565        return QDomElement();
 
 2570                      QStringLiteral( 
"qgis_id_geom_%1" ).arg( mGeomId ) );
 
 2571      if ( otherGeomElem.isNull() )
 
 2573        mErrorMessage = QObject::tr( 
"geom_from_wkt: unable to generate GML from wkt geometry" );
 
 2574        return QDomElement();
 
 2578    else if ( otherFnDef->
name() == QLatin1String( 
"geom_from_gml" ) )
 
 2583        mErrorMessage = QObject::tr( 
"geom_from_gml: argument must be string literal" );
 
 2584        return QDomElement();
 
 2587      QDomDocument geomDoc;
 
 2590      const QString xml = QStringLiteral( 
"<tmp xmlns:gml=\"%1\">%2</tmp>" ).arg( 
GML_NAMESPACE, gml );
 
 2591      if ( !geomDoc.setContent( xml, 
true ) )
 
 2593        mErrorMessage = QObject::tr( 
"geom_from_gml: unable to parse XML" );
 
 2594        return QDomElement();
 
 2597      const QDomNode geomNode = mDoc.importNode( geomDoc.documentElement().firstChildElement(), 
true );
 
 2598      otherGeomElem = geomNode.toElement();
 
 2604                      QStringLiteral( 
"qgis_id_geom_%1" ).arg( mGeomId ) );
 
 2605      if ( otherGeomElem.
isNull() )
 
 2607        mErrorMessage = QObject::tr( 
"geom from static value: unable to generate GML from static variable" );
 
 2608        return QDomElement();
 
 2614      mErrorMessage = QObject::tr( 
"spatial operator: unknown geometry constructor function" );
 
 2615      return QDomElement();
 
 2620    QDomElement funcElem = mDoc.createElement( mFilterPrefix + 
":" + tagNameForSpatialOperator( fd->
name() ) );
 
 2621    QDomElement geomProperty = mDoc.createElement( mFilterPrefix + 
":" + mPropertyName );
 
 2622    QString columnRef( mGeometryName );
 
 2623    if ( !mNamespacePrefix.isEmpty() && !mNamespaceURI.isEmpty() )
 
 2624      columnRef =  mNamespacePrefix + QStringLiteral( 
":" ) + columnRef;
 
 2625    geomProperty.appendChild( mDoc.createTextNode( columnRef ) );
 
 2626    funcElem.appendChild( geomProperty );
 
 2627    funcElem.appendChild( otherGeomElem );
 
 2631  if ( fd->
isStatic( node, expression, context ) )
 
 2633    const QVariant result = fd->
run( node->
args(), context, expression, node );
 
 2635    return expressionLiteralToOgcFilter( &literal, expression, context );
 
 2640    mErrorMessage = QObject::tr( 
"Special columns/constants are not supported." );
 
 2641    return QDomElement();
 
 2645  QDomElement funcElem = mDoc.createElement( mFilterPrefix + 
":Function" );
 
 2646  funcElem.setAttribute( QStringLiteral( 
"name" ), fd->
name() );
 
 2647  const auto constList = node->
args()->
list();
 
 2651    if ( !mErrorMessage.isEmpty() )
 
 2652      return QDomElement();
 
 2654    funcElem.appendChild( childElem );
 
 2665    const QList<QgsOgcUtils::LayerProperties> &layerProperties,
 
 2666    bool honourAxisOrientation,
 
 2667    bool invertAxisOrientation,
 
 2668    const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename,
 
 2669    const QMap<QString, QString> &fieldNameToXPathMap,
 
 2670    const QMap<QString, QString> &namespacePrefixToUriMap )
 
 2673  , mGMLVersion( gmlVersion )
 
 2674  , mFilterVersion( filterVersion )
 
 2675  , mLayerProperties( layerProperties )
 
 2676  , mHonourAxisOrientation( honourAxisOrientation )
 
 2677  , mInvertAxisOrientation( invertAxisOrientation )
 
 2678  , mFilterPrefix( ( filterVersion == 
QgsOgcUtils::FILTER_FES_2_0 ) ? 
"fes" : 
"ogc" )
 
 2679  , mPropertyName( ( filterVersion == 
QgsOgcUtils::FILTER_FES_2_0 ) ? 
"ValueReference" : 
"PropertyName" )
 
 2681  , mMapUnprefixedTypenameToPrefixedTypename( mapUnprefixedTypenameToPrefixedTypename )
 
 2682  , mFieldNameToXPathMap( fieldNameToXPathMap )
 
 2683  , mNamespacePrefixToUriMap( namespacePrefixToUriMap )
 
 
 2709      mErrorMessage = QObject::tr( 
"Node type not supported: %1" ).arg( node->
nodeType() );
 
 2710      return QDomElement();
 
 
 2719  if ( !mErrorMessage.isEmpty() )
 
 2720    return QDomElement();
 
 2723  switch ( node->
op() )
 
 2726      uoElem = mDoc.createElement( mFilterPrefix + 
":Literal" );
 
 2731        uoElem.appendChild( mDoc.createTextNode( 
"-" + operandElem.text() ) );
 
 2732        mDoc.removeChild( operandElem );
 
 2736        mErrorMessage = QObject::tr( 
"This use of unary operator not implemented yet" );
 
 2737        return QDomElement();
 
 2741      uoElem = mDoc.createElement( mFilterPrefix + 
":Not" );
 
 2742      uoElem.appendChild( operandElem );
 
 2747      return QDomElement();
 
 2757  if ( !mErrorMessage.isEmpty() )
 
 2758    return QDomElement();
 
 2771        QDomElement elem = mDoc.createElement( mFilterPrefix + 
":PropertyIsNull" );
 
 2772        elem.appendChild( leftElem );
 
 2776          QDomElement notElem = mDoc.createElement( mFilterPrefix + 
":Not" );
 
 2777          notElem.appendChild( elem );
 
 2791  if ( !mErrorMessage.isEmpty() )
 
 2792    return QDomElement();
 
 2797    opText = QStringLiteral( 
"Or" );
 
 2799    opText = QStringLiteral( 
"And" );
 
 2801    opText = QStringLiteral( 
"PropertyIsEqualTo" );
 
 2803    opText = QStringLiteral( 
"PropertyIsNotEqualTo" );
 
 2805    opText = QStringLiteral( 
"PropertyIsLessThanOrEqualTo" );
 
 2807    opText = QStringLiteral( 
"PropertyIsGreaterThanOrEqualTo" );
 
 2809    opText = QStringLiteral( 
"PropertyIsLessThan" );
 
 2811    opText = QStringLiteral( 
"PropertyIsGreaterThan" );
 
 2813    opText = QStringLiteral( 
"PropertyIsLike" );
 
 2815    opText = QStringLiteral( 
"PropertyIsLike" );
 
 2817  if ( opText.isEmpty() )
 
 2821    return QDomElement();
 
 2824  QDomElement boElem = mDoc.createElement( mFilterPrefix + 
":" + opText );
 
 2829      boElem.setAttribute( QStringLiteral( 
"matchCase" ), QStringLiteral( 
"false" ) );
 
 2832    boElem.setAttribute( QStringLiteral( 
"wildCard" ), QStringLiteral( 
"%" ) );
 
 2833    boElem.setAttribute( QStringLiteral( 
"singleChar" ), QStringLiteral( 
"_" ) );
 
 2835      boElem.setAttribute( QStringLiteral( 
"escape" ), QStringLiteral( 
"\\" ) );
 
 2837      boElem.setAttribute( QStringLiteral( 
"escapeChar" ), QStringLiteral( 
"\\" ) );
 
 2840  boElem.appendChild( leftElem );
 
 2841  boElem.appendChild( rightElem );
 
 2849  switch ( node->
value().userType() )
 
 2851    case QMetaType::Type::Int:
 
 2852      value = QString::number( node->
value().toInt() );
 
 2854    case QMetaType::Type::LongLong:
 
 2855      value = QString::number( node->
value().toLongLong() );
 
 2857    case QMetaType::Type::Double:
 
 2860    case QMetaType::Type::QString:
 
 2861      value = node->
value().toString();
 
 2865      mErrorMessage = QObject::tr( 
"Literal type not supported: %1" ).arg( 
static_cast<QMetaType::Type
>( node->
value().userType() ) );
 
 2866      return QDomElement();
 
 2869  QDomElement litElem = mDoc.createElement( mFilterPrefix + 
":Literal" );
 
 2870  litElem.appendChild( mDoc.createTextNode( value ) );
 
 2877  QDomElement propElem = mDoc.createElement( mFilterPrefix + 
":" + mPropertyName );
 
 2878  if ( node->
tableName().isEmpty() || mLayerProperties.size() == 1 )
 
 2880    if ( !mFieldNameToXPathMap.isEmpty() )
 
 2882      const auto iterFieldName = mFieldNameToXPathMap.constFind( node->
name() );
 
 2883      if ( iterFieldName != mFieldNameToXPathMap.constEnd() )
 
 2885        const QString xpath( *iterFieldName );
 
 2887        if ( !mNamespacePrefixToUriMap.isEmpty() )
 
 2889          const QStringList parts = xpath.split( 
'/' );
 
 2890          QSet<QString> setNamespacePrefix;
 
 2891          for ( 
const QString &part : std::as_const( parts ) )
 
 2893            const QStringList subparts = part.split( 
':' );
 
 2894            if ( subparts.size() == 2 && !setNamespacePrefix.contains( subparts[0] ) )
 
 2896              const auto iterNamespacePrefix = mNamespacePrefixToUriMap.constFind( subparts[0] );
 
 2897              if ( iterNamespacePrefix != mNamespacePrefixToUriMap.constEnd() )
 
 2899                setNamespacePrefix.insert( subparts[0] );
 
 2900                QDomAttr attr = mDoc.createAttribute( QStringLiteral( 
"xmlns:" ) +  subparts[0] );
 
 2901                attr.setValue( *iterNamespacePrefix );
 
 2902                propElem.setAttributeNode( attr );
 
 2908        propElem.appendChild( mDoc.createTextNode( xpath ) );
 
 2913    if ( mLayerProperties.size() == 1 && !mLayerProperties[0].mNamespacePrefix.isEmpty() && !mLayerProperties[0].mNamespaceURI.isEmpty() )
 
 2914      propElem.appendChild( mDoc.createTextNode(
 
 2915                              mLayerProperties[0].mNamespacePrefix + QStringLiteral( 
":" ) + node->
name() ) );
 
 2917      propElem.appendChild( mDoc.createTextNode( node->
name() ) );
 
 2921    QString tableName( mMapTableAliasToNames[node->
tableName()] );
 
 2922    if ( mMapUnprefixedTypenameToPrefixedTypename.contains( tableName ) )
 
 2923      tableName = mMapUnprefixedTypenameToPrefixedTypename[tableName];
 
 2924    propElem.appendChild( mDoc.createTextNode( tableName + 
"/" + node->
name() ) );
 
 2931  if ( node->
list()->
list().size() == 1 )
 
 2935    QDomElement eqElem = mDoc.createElement( mFilterPrefix + 
":PropertyIsEqualTo" );
 
 2936    eqElem.appendChild( leftNode );
 
 2937    eqElem.appendChild( firstListNode );
 
 2940      QDomElement notElem = mDoc.createElement( mFilterPrefix + 
":Not" );
 
 2941      notElem.appendChild( eqElem );
 
 2947  QDomElement orElem = mDoc.createElement( mFilterPrefix + 
":Or" );
 
 2950  const auto constList = node->
list()->
list();
 
 2954    if ( !mErrorMessage.isEmpty() )
 
 2955      return QDomElement();
 
 2957    QDomElement eqElem = mDoc.createElement( mFilterPrefix + 
":PropertyIsEqualTo" );
 
 2958    eqElem.appendChild( leftNode.cloneNode() );
 
 2959    eqElem.appendChild( listNode );
 
 2961    orElem.appendChild( eqElem );
 
 2966    QDomElement notElem = mDoc.createElement( mFilterPrefix + 
":Not" );
 
 2967    notElem.appendChild( orElem );
 
 2976  QDomElement elem = mDoc.createElement( mFilterPrefix + 
":PropertyIsBetween" );
 
 2978  QDomElement lowerBoundary = mDoc.createElement( mFilterPrefix + 
":LowerBoundary" );
 
 2980  elem.appendChild( lowerBoundary );
 
 2981  QDomElement upperBoundary = mDoc.createElement( mFilterPrefix + 
":UpperBoundary" );
 
 2983  elem.appendChild( upperBoundary );
 
 2987    QDomElement notElem = mDoc.createElement( mFilterPrefix + 
":Not" );
 
 2988    notElem.appendChild( elem );
 
 2995static QString mapBinarySpatialToOgc( 
const QString &name )
 
 2997  QString nameCompare( name );
 
 2998  if ( name.size() > 3 && QStringView {name} .mid( 0, 3 ).toString().compare( QLatin1String( 
"ST_" ), Qt::CaseInsensitive ) == 0 )
 
 2999    nameCompare = name.mid( 3 );
 
 3000  QStringList spatialOps;
 
 3001  spatialOps << QStringLiteral( 
"BBOX" ) << QStringLiteral( 
"Intersects" ) << QStringLiteral( 
"Contains" ) << QStringLiteral( 
"Crosses" ) << QStringLiteral( 
"Equals" )
 
 3002             << QStringLiteral( 
"Disjoint" ) << QStringLiteral( 
"Overlaps" ) << QStringLiteral( 
"Touches" ) << QStringLiteral( 
"Within" );
 
 3003  const auto constSpatialOps = spatialOps;
 
 3004  for ( QString op : constSpatialOps )
 
 3006    if ( nameCompare.compare( op, Qt::CaseInsensitive ) == 0 )
 
 3012static QString mapTernarySpatialToOgc( 
const QString &name )
 
 3014  QString nameCompare( name );
 
 3015  if ( name.size() > 3 && QStringView {name} .mid( 0, 3 ).compare( QLatin1String( 
"ST_" ), Qt::CaseInsensitive ) == 0 )
 
 3016    nameCompare = name.mid( 3 );
 
 3017  if ( nameCompare.compare( QLatin1String( 
"DWithin" ), Qt::CaseInsensitive ) == 0 )
 
 3018    return QStringLiteral( 
"DWithin" );
 
 3019  if ( nameCompare.compare( QLatin1String( 
"Beyond" ), Qt::CaseInsensitive ) == 0 )
 
 3020    return QStringLiteral( 
"Beyond" );
 
 3024QString QgsOgcUtilsSQLStatementToFilter::getGeometryColumnSRSName( 
const QgsSQLStatement::Node *node )
 
 3032    const auto constMLayerProperties = mLayerProperties;
 
 3035      if ( prop.mName.compare( mMapTableAliasToNames[col->
tableName()], Qt::CaseInsensitive ) == 0 &&
 
 3036           prop.mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
 
 3038        return prop.mSRSName;
 
 3042  if ( !mLayerProperties.empty() &&
 
 3043       mLayerProperties.at( 0 ).mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
 
 3045    return  mLayerProperties.at( 0 ).mSRSName;
 
 3051    QList<QgsSQLStatement::Node *> args,
 
 3052    bool lastArgIsSRSName,
 
 3054    bool &axisInversion )
 
 3057  axisInversion = mInvertAxisOrientation;
 
 3059  if ( lastArgIsSRSName )
 
 3064      mErrorMessage = QObject::tr( 
"%1: Last argument must be string or integer literal" ).arg( mainNode->
name() );
 
 3068    if ( lit->
value().userType() == QMetaType::Type::Int )
 
 3072        srsName = 
"EPSG:" + QString::number( lit->
value().toInt() );
 
 3076        srsName = 
"urn:ogc:def:crs:EPSG::" + QString::number( lit->
value().toInt() );
 
 3082      if ( 
srsName.startsWith( QLatin1String( 
"EPSG:" ), Qt::CaseInsensitive ) )
 
 3094      axisInversion = !axisInversion;
 
 3104  if ( node->
name().compare( QLatin1String( 
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 )
 
 3106    QList<QgsSQLStatement::Node *> args = node->
args()->
list();
 
 3107    if ( args.size() != 1 && args.size() != 2 )
 
 3109      mErrorMessage = QObject::tr( 
"Function %1 should have 1 or 2 arguments" ).arg( node->
name() );
 
 3110      return QDomElement();
 
 3116      mErrorMessage = QObject::tr( 
"%1: First argument must be string literal" ).arg( node->
name() );
 
 3117      return QDomElement();
 
 3122    if ( ! processSRSName( node, args, args.size() == 2, 
srsName, axisInversion ) )
 
 3124      return QDomElement();
 
 3130                                 QStringLiteral( 
"qgis_id_geom_%1" ).arg( mGeomId ) );
 
 3132    if ( geomElem.isNull() )
 
 3134      mErrorMessage = QObject::tr( 
"%1: invalid WKT" ).arg( node->
name() );
 
 3135      return QDomElement();
 
 3142  if ( node->
name().compare( QLatin1String( 
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 )
 
 3144    QList<QgsSQLStatement::Node *> args = node->
args()->
list();
 
 3145    if ( args.size() != 4 && args.size() != 5 )
 
 3147      mErrorMessage = QObject::tr( 
"Function %1 should have 4 or 5 arguments" ).arg( node->
name() );
 
 3148      return QDomElement();
 
 3153    for ( 
int i = 0; i < 4; i++ )
 
 3158        mErrorMessage = QObject::tr( 
"%1: Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
 
 3159        return QDomElement();
 
 3163      if ( lit->
value().userType() == QMetaType::Type::Int )
 
 3164        val = lit->
value().toInt();
 
 3165      else if ( lit->
value().userType() == QMetaType::Type::LongLong )
 
 3166        val = lit->
value().toLongLong();
 
 3167      else if ( lit->
value().userType() == QMetaType::Type::Double )
 
 3168        val = lit->
value().toDouble();
 
 3171        mErrorMessage = QObject::tr( 
"%1 Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
 
 3172        return QDomElement();
 
 3186    if ( ! processSRSName( node, args, args.size() == 5, 
srsName, axisInversion ) )
 
 3188      return QDomElement();
 
 3199  if ( node->
name().compare( QLatin1String( 
"ST_GeomFromGML" ), Qt::CaseInsensitive ) == 0 )
 
 3201    QList<QgsSQLStatement::Node *> args = node->
args()->
list();
 
 3202    if ( args.size() != 1 )
 
 3204      mErrorMessage = QObject::tr( 
"Function %1 should have 1 argument" ).arg( node->
name() );
 
 3205      return QDomElement();
 
 3211      mErrorMessage = QObject::tr( 
"%1: Argument must be string literal" ).arg( node->
name() );
 
 3212      return QDomElement();
 
 3215    QDomDocument geomDoc;
 
 3218    const QString xml = QStringLiteral( 
"<tmp xmlns:gml=\"%1\">%2</tmp>" ).arg( 
GML_NAMESPACE, gml );
 
 3219    if ( !geomDoc.setContent( xml, 
true ) )
 
 3221      mErrorMessage = QObject::tr( 
"ST_GeomFromGML: unable to parse XML" );
 
 3222      return QDomElement();
 
 3225    const QDomNode geomNode = mDoc.importNode( geomDoc.documentElement().firstChildElement(), 
true );
 
 3227    return geomNode.toElement();
 
 3231  QString ogcName( mapBinarySpatialToOgc( node->
name() ) );
 
 3232  if ( !ogcName.isEmpty() )
 
 3234    QList<QgsSQLStatement::Node *> args = node->
args()->
list();
 
 3235    if ( args.size() != 2 )
 
 3237      mErrorMessage = QObject::tr( 
"Function %1 should have 2 arguments" ).arg( node->
name() );
 
 3238      return QDomElement();
 
 3241    for ( 
int i = 0; i < 2; i ++ )
 
 3244           ( 
static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String( 
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
 
 3245             static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String( 
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
 
 3247        mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
 
 3254    QDomElement funcElem = mDoc.createElement( mFilterPrefix + 
":" + ogcName );
 
 3255    const auto constArgs = args;
 
 3259      if ( !mErrorMessage.isEmpty() )
 
 3261        mCurrentSRSName.clear();
 
 3262        return QDomElement();
 
 3265      funcElem.appendChild( childElem );
 
 3268    mCurrentSRSName.clear();
 
 3272  ogcName = mapTernarySpatialToOgc( node->
name() );
 
 3273  if ( !ogcName.isEmpty() )
 
 3275    QList<QgsSQLStatement::Node *> args = node->
args()->
list();
 
 3276    if ( args.size() != 3 )
 
 3278      mErrorMessage = QObject::tr( 
"Function %1 should have 3 arguments" ).arg( node->
name() );
 
 3279      return QDomElement();
 
 3282    for ( 
int i = 0; i < 2; i ++ )
 
 3285           ( 
static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String( 
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
 
 3286             static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String( 
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
 
 3288        mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
 
 3293    QDomElement funcElem = mDoc.createElement( mFilterPrefix + 
":" + node->
name().mid( 3 ) );
 
 3294    for ( 
int i = 0; i < 2; i++ )
 
 3296      const QDomElement childElem = 
toOgcFilter( args[i] );
 
 3297      if ( !mErrorMessage.isEmpty() )
 
 3299        mCurrentSRSName.clear();
 
 3300        return QDomElement();
 
 3303      funcElem.appendChild( childElem );
 
 3305    mCurrentSRSName.clear();
 
 3310      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() );
 
 3311      return QDomElement();
 
 3316      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() );
 
 3317      return QDomElement();
 
 3320    QString unit( QStringLiteral( 
"m" ) );
 
 3321    switch ( lit->
value().userType() )
 
 3323      case QMetaType::Type::Int:
 
 3324        distance = QString::number( lit->
value().toInt() );
 
 3326      case QMetaType::Type::LongLong:
 
 3327        distance = QString::number( lit->
value().toLongLong() );
 
 3329      case QMetaType::Type::Double:
 
 3332      case QMetaType::Type::QString:
 
 3334        distance = lit->
value().toString();
 
 3335        for ( 
int i = 0; i < distance.size(); i++ )
 
 3337          if ( !( ( distance[i] >= 
'0' && distance[i] <= 
'9' ) || distance[i] == 
'-' || distance[i] == 
'.' || distance[i] == 
'e' || distance[i] == 
'E' ) )
 
 3339            unit = distance.mid( i ).trimmed();
 
 3340            distance = distance.mid( 0, i );
 
 3348        mErrorMessage = QObject::tr( 
"Literal type not supported: %1" ).arg( 
static_cast<QMetaType::Type
>( lit->
value().userType() ) );
 
 3349        return QDomElement();
 
 3352    QDomElement distanceElem = mDoc.createElement( mFilterPrefix + 
":Distance" );
 
 3354      distanceElem.setAttribute( QStringLiteral( 
"uom" ), unit );
 
 3356      distanceElem.setAttribute( QStringLiteral( 
"unit" ), unit );
 
 3357    distanceElem.appendChild( mDoc.createTextNode( distance ) );
 
 3358    funcElem.appendChild( distanceElem );
 
 3363  QDomElement funcElem = mDoc.createElement( mFilterPrefix + 
":Function" );
 
 3364  funcElem.setAttribute( QStringLiteral( 
"name" ), node->
name() );
 
 3365  const auto constList = node->
args()->
list();
 
 3369    if ( !mErrorMessage.isEmpty() )
 
 3370      return QDomElement();
 
 3372    funcElem.appendChild( childElem );
 
 3378    const QString &leftTable )
 
 3386  QList<QDomElement> listElem;
 
 3388  for ( 
const QString &columnName : constUsingColumns )
 
 3390    QDomElement eqElem = mDoc.createElement( mFilterPrefix + 
":PropertyIsEqualTo" );
 
 3391    QDomElement propElem1 = mDoc.createElement( mFilterPrefix + 
":" + mPropertyName );
 
 3392    propElem1.appendChild( mDoc.createTextNode( leftTable + 
"/" + columnName ) );
 
 3393    eqElem.appendChild( propElem1 );
 
 3394    QDomElement propElem2 = mDoc.createElement( mFilterPrefix + 
":" + mPropertyName );
 
 3395    propElem2.appendChild( mDoc.createTextNode( node->
tableDef()->
name() + 
"/" + columnName ) );
 
 3396    eqElem.appendChild( propElem2 );
 
 3397    listElem.append( eqElem );
 
 3400  if ( listElem.size() == 1 )
 
 3404  else if ( listElem.size() > 1 )
 
 3406    QDomElement andElem = mDoc.createElement( mFilterPrefix + 
":And" );
 
 3407    const auto constListElem = listElem;
 
 3408    for ( 
const QDomElement &elem : constListElem )
 
 3410      andElem.appendChild( elem );
 
 3415  return QDomElement();
 
 3420  if ( node->
alias().isEmpty() )
 
 3422    mMapTableAliasToNames[ node->
name()] = node->
name();
 
 3426    mMapTableAliasToNames[ node->
alias()] = node->
name();
 
 3432  QList<QDomElement> listElem;
 
 3435       ( node->
tables().size() != 1 || !node->
joins().empty() ) )
 
 3437    mErrorMessage = QObject::tr( 
"Joins are only supported with WFS 2.0" );
 
 3438    return QDomElement();
 
 3442  const auto constTables = node->
tables();
 
 3447  const auto constJoins = node->
joins();
 
 3450    visit( join->tableDef() );
 
 3454  const QList< QgsSQLStatement::NodeTableDef *> nodeTables = node->
tables();
 
 3455  QString leftTable = nodeTables.at( nodeTables.length() - 1 )->name();
 
 3458    const QDomElement joinElem = 
toOgcFilter( join, leftTable );
 
 3459    if ( !mErrorMessage.isEmpty() )
 
 3460      return QDomElement();
 
 3461    listElem.append( joinElem );
 
 3462    leftTable = join->tableDef()->name();
 
 3466  if ( node->
where() )
 
 3469    if ( !mErrorMessage.isEmpty() )
 
 3470      return QDomElement();
 
 3471    listElem.append( whereElem );
 
 3475  if ( listElem.size() == 1 )
 
 3479  else if ( listElem.size() > 1 )
 
 3481    QDomElement andElem = mDoc.createElement( mFilterPrefix + 
":And" );
 
 3482    const auto constListElem = listElem;
 
 3483    for ( 
const QDomElement &elem : constListElem )
 
 3485      andElem.appendChild( elem );
 
 3490  return QDomElement();
 
 3496  mPropertyName = QStringLiteral( 
"PropertyName" );
 
 3497  mPrefix = QStringLiteral( 
"ogc" );
 
 3501    mPropertyName = QStringLiteral( 
"ValueReference" );
 
 3502    mPrefix = QStringLiteral( 
"fes" );
 
 
 3508  if ( element.isNull() )
 
 3512  if ( isBinaryOperator( element.tagName() ) )
 
 3518  if ( isSpatialOperator( element.tagName() ) )
 
 3524  if ( element.tagName() == QLatin1String( 
"Not" ) )
 
 3528  else if ( element.tagName() == QLatin1String( 
"PropertyIsNull" ) )
 
 3532  else if ( element.tagName() == QLatin1String( 
"Literal" ) )
 
 3536  else if ( element.tagName() == QLatin1String( 
"Function" ) )
 
 3540  else if ( element.tagName() == mPropertyName )
 
 3544  else if ( element.tagName() == QLatin1String( 
"PropertyIsBetween" ) )
 
 3549  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() );
 
 
 3555  if ( element.isNull() )
 
 3558  int op = binaryOperatorFromTagName( element.tagName() );
 
 3561    mErrorMessage = QObject::tr( 
"'%1' binary operator not supported." ).arg( element.tagName() );
 
 3565  if ( op == 
QgsExpressionNodeBinaryOperator::boLike && element.hasAttribute( QStringLiteral( 
"matchCase" ) ) && element.attribute( QStringLiteral( 
"matchCase" ) ) == QLatin1String( 
"false" ) )
 
 3570  QDomElement operandElem = element.firstChildElement();
 
 3575    mErrorMessage = QObject::tr( 
"invalid left operand for '%1' binary operator" ).arg( element.tagName() );
 
 3579  const std::unique_ptr<QgsExpressionNode> leftOp( expr->clone() );
 
 3580  for ( operandElem = operandElem.nextSiblingElement(); !operandElem.isNull(); operandElem = operandElem.nextSiblingElement() )
 
 3585      mErrorMessage = QObject::tr( 
"invalid right operand for '%1' binary operator" ).arg( element.tagName() );
 
 3592      if ( element.hasAttribute( QStringLiteral( 
"wildCard" ) ) )
 
 3594        wildCard = element.attribute( QStringLiteral( 
"wildCard" ) );
 
 3597      if ( element.hasAttribute( QStringLiteral( 
"singleChar" ) ) )
 
 3599        singleChar = element.attribute( QStringLiteral( 
"singleChar" ) );
 
 3601      QString escape = QStringLiteral( 
"\\" );
 
 3602      if ( element.hasAttribute( QStringLiteral( 
"escape" ) ) )
 
 3604        escape = element.attribute( QStringLiteral( 
"escape" ) );
 
 3606      if ( element.hasAttribute( QStringLiteral( 
"escapeChar" ) ) )
 
 3608        escape = element.attribute( QStringLiteral( 
"escapeChar" ) );
 
 3612      if ( !wildCard.isEmpty() && wildCard != QLatin1String( 
"%" ) )
 
 3614        oprValue.replace( 
'%', QLatin1String( 
"\\%" ) );
 
 3615        if ( oprValue.startsWith( wildCard ) )
 
 3617          oprValue.replace( 0, 1, QStringLiteral( 
"%" ) );
 
 3620        QRegularExpressionMatch match = rx.match( oprValue );
 
 3622        while ( match.hasMatch() )
 
 3624          pos = match.capturedStart();
 
 3625          oprValue.replace( pos + 1, 1, QStringLiteral( 
"%" ) );
 
 3627          match = rx.match( oprValue, pos );
 
 3629        oprValue.replace( escape + wildCard, wildCard );
 
 3631      if ( !singleChar.isEmpty() && singleChar != QLatin1String( 
"_" ) )
 
 3633        oprValue.replace( 
'_', QLatin1String( 
"\\_" ) );
 
 3634        if ( oprValue.startsWith( singleChar ) )
 
 3636          oprValue.replace( 0, 1, QStringLiteral( 
"_" ) );
 
 3639        QRegularExpressionMatch match = rx.match( oprValue );
 
 3641        while ( match.hasMatch() )
 
 3643          pos = match.capturedStart();
 
 3644          oprValue.replace( pos + 1, 1, QStringLiteral( 
"_" ) );
 
 3646          match = rx.match( oprValue, pos );
 
 3648        oprValue.replace( escape + singleChar, singleChar );
 
 3650      if ( !escape.isEmpty() && escape != QLatin1String( 
"\\" ) )
 
 3652        oprValue.replace( escape + escape, escape );
 
 3660  if ( expr == leftOp )
 
 3662    mErrorMessage = QObject::tr( 
"only one operand for '%1' binary operator" ).arg( element.tagName() );
 
 
 3675  auto gml2Args = std::make_unique<QgsExpressionNode::NodeList>();
 
 3676  QDomElement childElem = element.firstChildElement();
 
 3678  while ( !childElem.isNull() && gml2Str.isEmpty() )
 
 3680    if ( childElem.tagName() != mPropertyName )
 
 3682      QTextStream gml2Stream( &gml2Str );
 
 3683      childElem.save( gml2Stream, 0 );
 
 3685    childElem = childElem.nextSiblingElement();
 
 3687  if ( !gml2Str.isEmpty() )
 
 3693    mErrorMessage = QObject::tr( 
"No OGC Geometry found" );
 
 3697  auto opArgs = std::make_unique<QgsExpressionNode::NodeList>();
 
 
 3706  if ( element.isNull() || element.tagName() != mPropertyName )
 
 3708    mErrorMessage = QObject::tr( 
"%1:PropertyName expected, got %2" ).arg( mPrefix, element.tagName() );
 
 
 3717  if ( element.isNull() || element.tagName() != QLatin1String( 
"Literal" ) )
 
 3719    mErrorMessage = QObject::tr( 
"%1:Literal expected, got %2" ).arg( mPrefix, element.tagName() );
 
 3723  std::unique_ptr<QgsExpressionNode> root;
 
 3724  if ( !element.hasChildNodes() )
 
 3727    return root.release();
 
 3731  QDomNode childNode = element.firstChild();
 
 3732  while ( !childNode.isNull() )
 
 3734    std::unique_ptr<QgsExpressionNode> operand;
 
 3736    if ( childNode.nodeType() == QDomNode::ElementNode )
 
 3739      const QDomElement operandElem = childNode.toElement();
 
 3743        mErrorMessage = QObject::tr( 
"'%1' is an invalid or not supported content for %2:Literal" ).arg( operandElem.tagName(), mPrefix );
 
 3750      QVariant value = childNode.nodeValue();
 
 3752      bool converted = 
false;
 
 3757        QDomElement propertyNameElement = element.previousSiblingElement( mPropertyName );
 
 3758        if ( propertyNameElement.isNull() || propertyNameElement.tagName() != mPropertyName )
 
 3760          propertyNameElement = element.nextSiblingElement( mPropertyName );
 
 3762        if ( !propertyNameElement.isNull() || propertyNameElement.tagName() == mPropertyName )
 
 3764          const int fieldIndex = mLayer->
fields().
indexOf( propertyNameElement.firstChild().nodeValue() );
 
 3765          if ( fieldIndex != -1 )
 
 3767            const QgsField field = mLayer->
fields().
field( propertyNameElement.firstChild().nodeValue() );
 
 3778        const double d = value.toDouble( &ok );
 
 3791      root = std::move( operand );
 
 3798    childNode = childNode.nextSibling();
 
 3802    return root.release();
 
 
 3809  if ( element.tagName() != QLatin1String( 
"Not" ) )
 
 3812  const QDomElement operandElem = element.firstChildElement();
 
 3816    mErrorMessage = QObject::tr( 
"invalid operand for '%1' unary operator" ).arg( element.tagName() );
 
 
 3826  if ( element.tagName() != QLatin1String( 
"PropertyIsNull" ) )
 
 3831  const QDomElement operandElem = element.firstChildElement();
 
 
 3842  if ( element.isNull() || element.tagName() != QLatin1String( 
"Function" ) )
 
 3844    mErrorMessage = QObject::tr( 
"%1:Function expected, got %2" ).arg( mPrefix, element.tagName() );
 
 3852    if ( element.attribute( QStringLiteral( 
"name" ) ) != funcDef->
name() )
 
 3855    auto args = std::make_unique<QgsExpressionNode::NodeList>();
 
 3857    QDomElement operandElem = element.firstChildElement();
 
 3858    while ( !operandElem.isNull() )
 
 3865      args->append( op.release() );
 
 3867      operandElem = operandElem.nextSiblingElement();
 
 
 3879  std::unique_ptr<QgsExpressionNode> operand;
 
 3880  std::unique_ptr<QgsExpressionNode> lowerBound;
 
 3881  std::unique_ptr<QgsExpressionNode> upperBound;
 
 3883  QDomElement operandElem = element.firstChildElement();
 
 3884  while ( !operandElem.isNull() )
 
 3886    if ( operandElem.tagName() == QLatin1String( 
"LowerBoundary" ) )
 
 3888      const QDomElement lowerBoundElem = operandElem.firstChildElement();
 
 3891    else if ( operandElem.tagName() == QLatin1String( 
"UpperBoundary" ) )
 
 3893      const QDomElement upperBoundElem = operandElem.firstChildElement();
 
 3902    if ( operand && lowerBound && upperBound )
 
 3905    operandElem = operandElem.nextSiblingElement();
 
 3908  if ( !operand || !lowerBound || !upperBound )
 
 3910    mErrorMessage = QObject::tr( 
"missing some required sub-elements in %1:PropertyIsBetween" ).arg( mPrefix );
 
 
 3921  return mErrorMessage;
 
 
 3926  const thread_local QRegularExpression re_url( QRegularExpression::anchoredPattern( QStringLiteral( 
"http://www\\.opengis\\.net/gml/srs/epsg\\.xml#(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
 
 3927  if ( 
const QRegularExpressionMatch match = re_url.match( crsName ); match.hasMatch() )
 
 3929    authority = QStringLiteral( 
"EPSG" );
 
 3930    code = match.captured( 1 );
 
 3934  const thread_local QRegularExpression re_ogc_urn( QRegularExpression::anchoredPattern( QStringLiteral( 
"urn:ogc:def:crs:([^:]+).+(?<=:)([^:]+)" ) ), QRegularExpression::CaseInsensitiveOption );
 
 3935  if ( 
const QRegularExpressionMatch match = re_ogc_urn.match( crsName ); match.hasMatch() )
 
 3937    authority = match.captured( 1 );
 
 3938    code = match.captured( 2 );
 
 3942  const thread_local QRegularExpression re_x_ogc_urn( QRegularExpression::anchoredPattern( QStringLiteral( 
"urn:x-ogc:def:crs:([^:]+).+(?<=:)([^:]+)" ) ), QRegularExpression::CaseInsensitiveOption );
 
 3943  if ( 
const QRegularExpressionMatch match = re_x_ogc_urn.match( crsName ); match.hasMatch() )
 
 3945    authority = match.captured( 1 );
 
 3946    code = match.captured( 2 );
 
 3950  const thread_local QRegularExpression re_http_uri( QRegularExpression::anchoredPattern( QStringLiteral( 
"http://www\\.opengis\\.net/def/crs/([^/]+).+/([^/]+)" ) ), QRegularExpression::CaseInsensitiveOption );
 
 3951  if ( 
const QRegularExpressionMatch match = re_http_uri.match( crsName ); match.hasMatch() )
 
 3953    authority = match.captured( 1 );
 
 3954    code = match.captured( 2 );
 
 3958  const thread_local QRegularExpression re_auth_code( QRegularExpression::anchoredPattern( QStringLiteral( 
"([^:]+):(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
 
 3959  if ( 
const QRegularExpressionMatch match = re_auth_code.match( crsName ); match.hasMatch() )
 
 3961    authority = match.captured( 1 );
 
 3962    code = match.captured( 2 );
 
 
 3969QgsGeometry QgsOgcUtils::geometryFromGMLUsingGdal( 
const QDomElement &geometryElement )
 
 3972  QTextStream gmlStream( &gml );
 
 3973  geometryElement.save( gmlStream, 0 );
 
 3978QgsGeometry QgsOgcUtils::geometryFromGMLMultiCurve( 
const QDomElement &geometryElement )
 
 3980  return geometryFromGMLUsingGdal( geometryElement );
 
GeometryOperationResult
Success or failure of a geometry operation.
 
@ Success
Operation succeeded.
 
WkbType
The WKB type describes the number of dimensions a geometry has.
 
@ LineString25D
LineString25D.
 
@ MultiPointZ
MultiPointZ.
 
@ MultiPolygon25D
MultiPolygon25D.
 
@ MultiLineString25D
MultiLineString25D.
 
@ MultiPolygon
MultiPolygon.
 
@ MultiLineString
MultiLineString.
 
@ MultiPoint25D
MultiPoint25D.
 
@ MultiLineStringZ
MultiLineStringZ.
 
@ MultiPolygonZ
MultiPolygonZ.
 
@ LineStringZ
LineStringZ.
 
virtual void swapXy()=0
Swaps the x and y coordinates from the geometry.
 
Qgis::WkbType readHeader() const
readHeader
 
Represents a coordinate reference system (CRS).
 
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
 
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
 
bool createFromUserInput(const QString &definition)
Set up this CRS from various text formats.
 
bool hasAxisInverted() const
Returns whether the axis order is inverted for the CRS compared to the order east/north (longitude/la...
 
Custom exception class for Coordinate Reference System related exceptions.
 
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
 
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
 
An abstract base class for defining QgsExpression functions.
 
int params() const
The number of parameters this function takes.
 
virtual bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
Will be called during prepare to determine if the function is static.
 
QString name() const
The name of the function.
 
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 binary expression operator, which operates on two values.
 
QgsExpressionNode * opLeft() const
Returns the node to the left of the operator.
 
QgsExpressionNode * opRight() const
Returns the node to the right of the operator.
 
QgsExpressionNodeBinaryOperator::BinaryOperator op() const
Returns the binary operator.
 
QString text() const
Returns a the name of this operator without the operands.
 
BinaryOperator
list of binary operators
 
An expression node which takes its value from a feature's field.
 
QString name() const
The name of the column.
 
An expression node for expression functions.
 
int fnIndex() const
Returns the index of the node's function.
 
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
 
QSet< QString > referencedVariables() const override
Returns a set of all variables which are used in this expression.
 
An expression node for value IN or NOT IN clauses.
 
QgsExpressionNode * node() const
Returns the expression node.
 
QgsExpressionNode::NodeList * list() const
Returns the list of nodes to search for matching values within.
 
bool isNotIn() const
Returns true if this node is a "NOT IN" operator, or false if the node is a normal "IN" operator.
 
An expression node for literal values.
 
QVariant value() const
The value of the literal.
 
A unary node is either negative as in boolean (not) or as in numbers (minus).
 
QgsExpressionNodeUnaryOperator::UnaryOperator op() const
Returns the unary operator.
 
QString text() const
Returns a the name of this operator without the operands.
 
QgsExpressionNode * operand() const
Returns the node the operator will operate upon.
 
A list of expression nodes.
 
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
 
Abstract base class for all nodes that can appear in an expression.
 
bool hasCachedStaticValue() const
Returns true if the node can be replaced by a static cached value.
 
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
 
QVariant cachedStaticValue() const
Returns the node's static cached value.
 
Handles parsing and evaluation of expressions (formerly called "search strings").
 
static const QList< QgsExpressionFunction * > & Functions()
 
void setExpression(const QString &expression)
Set the expression string, will reset the whole internal structure.
 
static int functionIndex(const QString &name)
Returns index of the function in Functions array.
 
QString dump() const
Returns an expression string, constructed from the internal abstract syntax tree.
 
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
 
Encapsulate a field in an attribute table or data source.
 
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
 
Q_INVOKABLE int indexOf(const QString &fieldName) const
Gets the field index from the field name.
 
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
 
A geometry is the spatial representation of a feature.
 
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
 
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
 
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
 
static Q_INVOKABLE QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
 
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
 
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const
Export the geometry to WKB.
 
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
 
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
 
QgsCoordinateReferenceSystem crs
 
@ HTTP_EPSG_DOT_XML
E.g. http://www.opengis.net/gml/srs/epsg.xml#4326 (called "OGC HTTP URL" in GeoServer WFS configurati...
 
@ OGC_HTTP_URI
E.g. http://www.opengis.net/def/crs/EPSG/0/4326.
 
@ X_OGC_URN
E.g. urn:x-ogc:def:crs:EPSG::4326.
 
@ UNKNOWN
Unknown/unhandled flavor.
 
@ OGC_URN
E.g. urn:ogc:def:crs:EPSG::4326.
 
@ AUTH_CODE
E.g EPSG:4326.
 
static CRSFlavor parseCrsName(const QString &crsName, QString &authority, QString &code)
Parse a CRS name in one of the flavors of OGC services, and decompose it as authority and code.
 
Internal use by QgsOgcUtils.
 
QgsOgcUtilsExprToFilter(QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, QgsOgcUtils::FilterVersion filterVersion, const QString &namespacePrefix, const QString &namespaceURI, const QString &geometryName, const QString &srsName, bool honourAxisOrientation, bool invertAxisOrientation, const QMap< QString, QString > &fieldNameToXPathMap, const QMap< QString, QString > &namespacePrefixToUriMap)
Constructor.
 
bool GMLNamespaceUsed() const
Returns whether the gml: namespace is used.
 
QDomElement expressionNodeToOgcFilter(const QgsExpressionNode *node, QgsExpression *expression, const QgsExpressionContext *context)
Convert an expression to a OGC filter.
 
QString errorMessage() const
Returns the error message.
 
Internal use by QgsOgcUtils.
 
QgsExpressionNodeFunction * nodeSpatialOperatorFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with spatial operators.
 
QgsExpressionNodeUnaryOperator * nodeNotFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with Not operator.
 
QgsExpressionNodeColumnRef * nodeColumnRefFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with column references.
 
QgsExpressionNode * nodeIsBetweenFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with boundaries operator.
 
QgsOgcUtilsExpressionFromFilter(QgsOgcUtils::FilterVersion version=QgsOgcUtils::FILTER_OGC_1_0, const QgsVectorLayer *layer=nullptr)
Constructor for QgsOgcUtilsExpressionFromFilter.
 
QgsExpressionNodeBinaryOperator * nodeBinaryOperatorFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with binary operators.
 
QgsExpressionNodeFunction * nodeFunctionFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with functions.
 
QgsExpressionNode * nodeFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document element.
 
QgsExpressionNodeBinaryOperator * nodePropertyIsNullFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with IsNull operator.
 
QString errorMessage() const
Returns the underlying error message, or an empty string in case of no error.
 
QgsExpressionNode * nodeLiteralFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with literal tag.
 
Internal use by QgsOgcUtils.
 
QgsOgcUtilsSQLStatementToFilter(QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, QgsOgcUtils::FilterVersion filterVersion, const QList< QgsOgcUtils::LayerProperties > &layerProperties, bool honourAxisOrientation, bool invertAxisOrientation, const QMap< QString, QString > &mapUnprefixedTypenameToPrefixedTypename, const QMap< QString, QString > &fieldNameToXPathMap, const QMap< QString, QString > &namespacePrefixToUriMap)
Constructor.
 
QDomElement toOgcFilter(const QgsSQLStatement::Node *node)
Convert a SQL statement to a OGC filter.
 
bool GMLNamespaceUsed() const
Returns whether the gml: namespace is used.
 
QString errorMessage() const
Returns the error message.
 
Provides various utility functions for conversion between OGC (Open Geospatial Consortium) standards ...
 
static QDomElement elseFilterExpression(QDomDocument &doc)
Creates an ElseFilter from doc.
 
static QgsRectangle rectangleFromGMLBox(const QDomNode &boxNode)
Read rectangle from GML2 Box.
 
static QDomElement expressionToOgcExpression(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr, bool requiresFilterElement=false)
Creates an OGC expression XML element from the exp expression with default values for the geometry na...
 
static QColor colorFromOgcFill(const QDomElement &fillElement)
Parse XML with OGC fill into QColor.
 
static QDomElement expressionToOgcFilter(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates OGC filter XML element.
 
FilterVersion
OGC filter version.
 
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, const QMap< QString, QString > &fieldNameToXPathMap=QMap< QString, QString >(), const QMap< QString, QString > &namespacePrefixToUriMap=QMap< QString, QString >())
Creates OGC filter XML element from the WHERE and JOIN clauses of a SQL statement.
 
static QDomElement rectangleToGMLEnvelope(const QgsRectangle *env, QDomDocument &doc, int precision=17)
Exports the rectangle to GML3 Envelope.
 
static QgsRectangle rectangleFromGMLEnvelope(const QDomNode &envelopeNode)
Read rectangle from GML3 Envelope.
 
static QDomElement geometryToGML(const QgsGeometry &geometry, QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, const QString &srsName, bool invertAxisOrientation, const QString &gmlIdBase, int precision=17)
Exports the geometry to GML.
 
static QgsGeometry geometryFromGML(const QString &xmlString, const QgsOgcUtils::Context &context=QgsOgcUtils::Context())
Static method that creates geometry from GML.
 
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
 
static QDomElement rectangleToGMLBox(const QgsRectangle *box, QDomDocument &doc, int precision=17)
Exports the rectangle to GML2 Box.
 
static QgsGeometry ogrGeometryToQgsGeometry(OGRGeometryH geom)
Converts an OGR geometry representation to a QgsGeometry object.
 
Point geometry type, with support for z-dimension and m-values.
 
A rectangle specified with double values.
 
void setYMinimum(double y)
Set the minimum y value.
 
void setXMinimum(double x)
Set the minimum x value.
 
void setYMaximum(double y)
Set the maximum y value.
 
void setXMaximum(double x)
Set the maximum x value.
 
void normalize()
Normalize the rectangle so it has non-negative width/height.
 
An 'X BETWEEN y and z' operator.
 
QgsSQLStatement::Node * node() const
Variable at the left of BETWEEN.
 
QgsSQLStatement::Node * minVal() const
Minimum bound.
 
bool isNotBetween() const
Whether this is a NOT BETWEEN operator.
 
QgsSQLStatement::Node * maxVal() const
Maximum bound.
 
Binary logical/arithmetical operator (AND, OR, =, +, ...).
 
QgsSQLStatement::Node * opLeft() const
Left operand.
 
QgsSQLStatement::BinaryOperator op() const
Operator.
 
QgsSQLStatement::Node * opRight() const
Right operand.
 
QString name() const
The name of the column.
 
QString tableName() const
The name of the table. May be empty.
 
Function with a name and arguments node.
 
QgsSQLStatement::NodeList * args() const
Returns arguments.
 
QString name() const
Returns function name.
 
An 'x IN (y, z)' operator.
 
bool isNotIn() const
Whether this is a NOT IN operator.
 
QgsSQLStatement::Node * node() const
Variable at the left of IN.
 
QgsSQLStatement::NodeList * list() const
Values list.
 
QgsSQLStatement::NodeTableDef * tableDef() const
Table definition.
 
QgsSQLStatement::Node * onExpr() const
On expression. Will be nullptr if usingColumns() is not empty.
 
QList< QString > usingColumns() const
Columns referenced by USING.
 
QList< QgsSQLStatement::Node * > list()
Returns list.
 
Literal value (integer, integer64, double, string).
 
QVariant value() const
The value of the literal.
 
QList< QgsSQLStatement::NodeJoin * > joins() const
Returns the list of joins.
 
QgsSQLStatement::Node * where() const
Returns the where clause.
 
QList< QgsSQLStatement::NodeTableDef * > tables() const
Returns the list of tables.
 
QString name() const
Table name.
 
QString alias() const
Table alias.
 
Unary logical/arithmetical operator ( NOT, - ).
 
QgsSQLStatement::UnaryOperator op() const
Operator.
 
QgsSQLStatement::Node * operand() const
Operand.
 
Abstract node class for SQL statement nodes.
 
virtual QgsSQLStatement::NodeType nodeType() const =0
Abstract virtual that returns the type of this node.
 
BinaryOperator
list of binary operators
 
static const char * BINARY_OPERATOR_TEXT[]
 
const QgsSQLStatement::Node * rootNode() const
Returns the root node of the statement.
 
static const char * UNARY_OPERATOR_TEXT[]
 
static QString qRegExpEscape(const QString &string)
Returns an escaped string matching the behavior of QRegExp::escape.
 
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
 
Represents a vector layer which manages a vector based dataset.
 
Custom exception class for Wkb related exceptions.
 
std::unique_ptr< std::remove_pointer< OGRGeometryH >::type, OGRGeometryDeleter > ogr_geometry_unique_ptr
Scoped OGR geometry.
 
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
 
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
 
QMap< QString, QString > QgsStringMap
 
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
 
QVector< QgsPolyline > QgsMultiPolyline
Multi polyline represented as a vector of polylines.
 
QgsPointSequence QgsPolyline
Polyline as represented as a vector of points.
 
#define QgsDebugMsgLevel(str, level)
 
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)
 
QMap< QString, int > IntMap
 
const QString & geometryName
 
const QgsCoordinateReferenceSystem & crs
 
The Context struct stores the current layer and coordinate transform context.
 
const QgsMapLayer * layer
 
QgsCoordinateTransformContext transformContext