From: Olivier Courtin Date: Tue, 20 Oct 2009 12:54:01 +0000 (+0000) Subject: Add initial version of GeomFromGML function, and units tests cases. X-Git-Tag: 1.5.0b1~353 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5178422626056133943c52a6284ab21b726d0225;p=postgis Add initial version of GeomFromGML function, and units tests cases. git-svn-id: http://svn.osgeo.org/postgis/trunk@4667 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/postgis/Makefile.in b/postgis/Makefile.in index 667640ec0..715705731 100644 --- a/postgis/Makefile.in +++ b/postgis/Makefile.in @@ -42,6 +42,7 @@ PG_OBJS=lwgeom_pg.o \ lwgeom_svg.o \ lwgeom_gml.o \ lwgeom_kml.o \ + lwgeom_in_gml.o \ lwgeom_geojson.o \ lwgeom_triggers.o \ lwgeom_dump.o \ diff --git a/postgis/lwgeom_in_gml.c b/postgis/lwgeom_in_gml.c new file mode 100644 index 000000000..6f9e8ca00 --- /dev/null +++ b/postgis/lwgeom_in_gml.c @@ -0,0 +1,1110 @@ +/********************************************************************** + * PostGIS - Spatial Types for PostgreSQL + * http://postgis.refractions.net + * Copyright 2009 Oslandia + * + * This is free software; you can redistribute and/or modify it under + * the terms of hte GNU General Public Licence. See the COPYING file. + * + **********************************************************************/ + +/** +* @file GML input routines. +* Ability to parse GML geometry fragment and to return an LWGEOM +* or an error message. +* +* Implement ISO SQL/MM ST_GMLToSQL method +* Cf: ISO 13249-3 -> 5.1.50 (p 134) +* +* GML versions supported: +* - GML 2.1.2 +* - GML 3.1.1 Simple Features profile (1.0.0) +* Cf: +* +* Current known limitations: +* - Support only GML SF profile geometries (i.e no PostGIS curves support) +* - Don't care about GML namespace +* - Don't handle Xlink or PointRef construction +* - Don't reproject if mixed srsName in multi/aggregate geoms +* +* Written by Olivier Courtin - Oslandia +* +**********************************************************************/ + + +#include "postgres.h" +#include "lwgeom_pg.h" +#include "liblwgeom.h" + +#if HAVE_LIBXML2 +#include +#include + +#include "lwgeom_export.h" /* getSRSbySRID */ + + +Datum geom_from_gml(PG_FUNCTION_ARGS); +static LWGEOM* parse_gml(xmlNodePtr xnode, bool *hasz); + + +/** + * Ability to parse GML geometry fragment and to return an LWGEOM + * or an error message. + * + * ISO SQL/MM define two error messages: +* Cf: ISO 13249-3 -> 5.1.50 (p 134) + * - invalid GML representation + * - unknown spatial reference system + */ +PG_FUNCTION_INFO_V1(geom_from_gml); +Datum geom_from_gml(PG_FUNCTION_ARGS) +{ + PG_LWGEOM *geom, *geom2d; + xmlDocPtr xmldoc; + text *xml_input; + LWGEOM *lwgeom; + int xml_size; + uchar *srl; + char *xml; + size_t size=0; + bool hasz=true; + xmlNodePtr xmlroot=NULL; + + + /* Get the GML stream */ + if (PG_ARGISNULL(0)) PG_RETURN_NULL(); + xml_input = PG_GETARG_TEXT_P(0); + + xml_size = VARSIZE(xml_input) - VARHDRSZ; /* actual letters */ + xml = palloc(xml_size + 1); /* +1 for null */ + memcpy(xml, VARDATA(xml_input), xml_size); + xml[xml_size] = 0; /* null term */ + + /* Begin to Parse XML doc */ + xmlInitParser(); + xmldoc = xmlParseMemory(xml, xml_size); + if (!xmldoc || (xmlroot = xmlDocGetRootElement(xmldoc)) == NULL) { + xmlFreeDoc(xmldoc); + xmlCleanupParser(); + lwerror("invalid GML representation"); + } + + lwgeom = parse_gml(xmlroot, &hasz); + geom = pglwgeom_serialize(lwgeom); + lwgeom_release(lwgeom); + + xmlFreeDoc(xmldoc); + xmlCleanupParser(); + + /* GML geometry could be either 2 or 3D and can be nested mixed. + * Missing Z dimension is even tolerated inside some GML coords + * + * So we deal with 3D in all structure allocation, and flag hasz + * to false if we met once a missing Z dimension + * In this case, we force recursive 2D. + */ + if (!hasz) { + srl = lwalloc(VARSIZE(geom)); + lwgeom_force2d_recursive(SERIALIZED_FORM(geom), srl, &size); + geom2d = PG_LWGEOM_construct(srl, pglwgeom_getSRID(geom), + lwgeom_hasBBOX(geom->type)); + lwfree(geom); + geom = geom2d; + } + + PG_RETURN_POINTER(geom); +} + + +/** + * Parse a string supposed to be a double + */ +static double parse_gml_double(char *d, bool space_before, bool space_after) +{ + char *p; + int st; + enum states { + INIT = 0, + NEED_DIG = 1, + DIG = 2, + NEED_DIG_DEC = 3, + DIG_DEC = 4, + EXP = 5, + NEED_DIG_EXP = 6, + DIG_EXP = 7, + END = 8 + }; + + /* + * Double pattern + * [-|\+]?[0-9]+(\.[0-9]+)?([Ee](\+|-)?[0-9]+) + * + * We could also meet spaces before or after + * this pattern upon parameters + */ + + if (space_before) while (isspace(*d)) d++; + for (st = INIT, p = d ; *p ; p++) { + + if (isdigit(*p)) { + if (st == INIT || st == NEED_DIG) st = DIG; + else if (st == NEED_DIG_DEC) st = DIG_DEC; + else if (st == NEED_DIG_EXP || st == EXP) st = DIG_EXP; + else if (st == DIG || st == DIG_DEC || st == DIG_EXP); + else lwerror("invalid GML representation"); + } else if (*p == '.') { + if (st == DIG) st = NEED_DIG_DEC; + else lwerror("invalid GML representation"); + } else if (*p == '-' || *p == '+') { + if (st == INIT) st = NEED_DIG; + else if (st == EXP) st = NEED_DIG_EXP; + else lwerror("invalid GML representation"); + } else if (*p == 'e' || *p == 'E') { + if (st == DIG || st == DIG_DEC) st = EXP; + else lwerror("invalid GML representation"); + } else if (isspace(*p)) { + if (!space_after) lwerror("invalid GML representation"); + if (st == DIG || st == DIG_DEC || st == DIG_EXP)st = END; + else if (st == END); + else lwerror("invalid GML representation"); + } else lwerror("invalid GML representation"); + } + + if (st != DIG && st != DIG_DEC && st != DIG_EXP && st != END) + lwerror("invalid GML representation"); + + return atof(d); +} + + +/** + * Parse gml:coordinates + */ +static POINTARRAY* parse_gml_coordinates(xmlNodePtr xnode, bool *hasz) +{ + xmlChar *gml_coord, *gml_ts, *gml_cs, *gml_dec; + char *coord, *p, *q; + char cs, ts, dec; + DYNPTARRAY *dpa; + POINTARRAY *pa; + int gml_dims; + bool digit; + POINT4D pt; + uchar dims=0; + + /* We begin to retrieve coordinates string */ + gml_coord = xmlNodeGetContent(xnode); + p = coord = (char *) gml_coord; + + /* Default GML coordinates pattern: x1,y1 x2,y2 + * x1,y1,z1 x2,y2,z2 + * + * Cf GML 2.1.2 -> 4.3.1 (p18) + */ + + /* Retrieve separator between coordinates tuples */ + gml_ts = xmlGetProp(xnode, (xmlChar *) "ts"); + if (gml_ts == NULL) ts = ' '; + else { + if (xmlStrlen(gml_ts) > 1 || isdigit(gml_ts[0])) + lwerror("invalid GML representation"); + ts = gml_ts[0]; + xmlFree(gml_ts); + } + + /* Retrieve separator between each coordinate */ + gml_cs = xmlGetProp(xnode, (xmlChar *) "cs"); + if (gml_cs == NULL) cs = ','; + else { + if (xmlStrlen(gml_cs) > 1 || isdigit(gml_cs[0])) + lwerror("invalid GML representation"); + cs = gml_cs[0]; + xmlFree(gml_cs); + } + + /* Retrieve decimal separator */ + gml_dec = xmlGetProp(xnode, (xmlChar *) "decimal"); + if (gml_dec == NULL) dec = '.'; + else { + if (xmlStrlen(gml_dec) > 1 || isdigit(gml_dec[0])) + lwerror("invalid GML representation"); + dec = gml_dec[0]; + xmlFree(gml_dec); + } + + if (cs == ts || cs == dec || ts == dec) + lwerror("invalid GML representation"); + + /* Now we create PointArray from coordinates values */ + TYPE_SETZM(dims, 1, 0); + dpa = dynptarray_create(1, dims); + + while(isspace(*p)) p++; /* Eat extra whitespaces if any */ + for (q = p, gml_dims=0, digit = false ; *p ; p++) { + + if (isdigit(*p)) digit = true; /* One state parser */ + + /* Coordinate Separator */ + if (*p == cs) { + *p = '\0'; + gml_dims++; + + if (*(p+1) == '\0') lwerror("invalid GML representation"); + + if (gml_dims == 1) pt.x = parse_gml_double(q, 0, 1); + else if (gml_dims == 2) pt.y = parse_gml_double(q, 0, 1); + + q = p+1; + + /* Tuple Separator (or end string) */ + } else if (digit && (*p == ts || *(p+1) == '\0')) { + if (*p == ts) *p = '\0'; + gml_dims++; + + if (gml_dims < 2 || gml_dims > 3) + lwerror("invalid GML representation"); + + if (gml_dims == 3) pt.z = parse_gml_double(q, 0, 1); + else { + pt.y = atof(q); + *hasz = false; + } + + dynptarray_addPoint4d(dpa, &pt, 0); + digit = false; + + q = p+1; + gml_dims = 0; + + /* Need to put standard decimal separator to atof handle */ + } else if (*p == dec && dec != '.') *p = '.'; + } + + xmlFree(gml_coord); + pa = ptarray_clone(dpa->pa); + lwfree(dpa); + + return pa; +} + + +/** + * Parse gml:coord + */ +static POINTARRAY* parse_gml_coord(xmlNodePtr xnode, bool *hasz) +{ + xmlNodePtr coord, xyz; + DYNPTARRAY *dpa; + POINTARRAY *pa; + bool x,y,z; + xmlChar *c; + POINT4D p; + uchar dims=0; + + TYPE_SETZM(dims, 1, 0); + dpa = dynptarray_create(1, dims); + + for (coord = xnode ; coord != NULL ; coord = coord->next) { + + /* Looking for gml:coord element */ + if (coord->type != XML_ELEMENT_NODE) continue; + if (strcmp((char *) coord->name, "coord")) continue; + + x = y = z = false; + for (xyz = coord->children ; xyz != NULL ; xyz = xyz->next) { + + if (xyz->type != XML_ELEMENT_NODE) continue; + + if (!strcmp((char *) xyz->name, "X")) { + if (x) lwerror("invalid GML representation"); + c = xmlNodeGetContent(xyz); + p.x = parse_gml_double((char *) c, 1, 1); + x = true; + xmlFree(c); + } else if (!strcmp((char *) xyz->name, "Y")) { + if (y) lwerror("invalid GML representation"); + c = xmlNodeGetContent(xyz); + p.y = parse_gml_double((char *) c, 1, 1); + y = true; + xmlFree(c); + } else if (!strcmp((char *) xyz->name, "Z")) { + if (z) lwerror("invalid GML representation"); + c = xmlNodeGetContent(xyz); + p.z = parse_gml_double((char *) c, 1, 1); + z = true; + xmlFree(c); + } + } + + /* Check dimension consistancy */ + if (!x || !y) lwerror("invalid GML representation"); + if (!z) *hasz = false; + + dynptarray_addPoint4d(dpa, &p, 0); + x = y = z = false; + } + + pa = ptarray_clone(dpa->pa); + lwfree(dpa); + + return pa; +} + + +/** + * Parse gml:pos + */ +static POINTARRAY* parse_gml_pos(xmlNodePtr xnode, bool *hasz) +{ + xmlChar *dimension, *gmlpos; + xmlNodePtr posnode; + int dim, gml_dim; + DYNPTARRAY *dpa; + POINTARRAY *pa; + char *pos, *p; + bool digit; + POINT4D pt; + uchar dims=0; + + TYPE_SETZM(dims, 1, 0); + dpa = dynptarray_create(1, dims); + + for (posnode = xnode ; posnode != NULL ; posnode = posnode->next) { + + /* We only care about pos element */ + if (posnode->type != XML_ELEMENT_NODE) continue; + if (strcmp((char *) posnode->name, "pos")) continue; + + dimension = xmlGetProp(xnode, (xmlChar *) "dimension"); + if (dimension == NULL) dim = 2; /* We assume that we are in 2D */ + else { + dim = atoi((char *) dimension); + xmlFree(dimension); + if (dim < 2 || dim > 3) + lwerror("invalid GML representation"); + } + if (dim == 2) *hasz = false; + + /* We retrieve gml:pos string */ + gmlpos = xmlNodeGetContent(posnode); + pos = (char *) gmlpos; + while(isspace(*pos)) pos++; /* Eat extra whitespaces if any */ + + /* gml:pos pattern: x1 y1 + * x1 y1 z1 + */ + for (p=pos, gml_dim=0, digit=false ; *pos ; pos++) { + + if (isdigit(*pos)) digit = true; + + if (digit && (*pos == ' ' || *(pos+1) == '\0')) { + + if (*pos == ' ') *pos = '\0'; + gml_dim++; + if (gml_dim == 1) pt.x = parse_gml_double(p, 0, 1); + else if (gml_dim == 2) pt.y = parse_gml_double(p, 0, 1); + else if (gml_dim == 3) pt.z = parse_gml_double(p, 0, 1); + + p = pos+1; + digit = false; + } + } + xmlFree(gmlpos); + + /* Test again coherent dimensions on each coord */ + if (gml_dim == 2) *hasz = false; + if (gml_dim < 2 || gml_dim > 3 || gml_dim != dim) + lwerror("invalid GML representation"); + + dynptarray_addPoint4d(dpa, &pt, 0); + } + + pa = ptarray_clone(dpa->pa); + lwfree(dpa); + + return pa; +} + + +/** + * Parse gml:posList + */ +static POINTARRAY* parse_gml_poslist(xmlNodePtr xnode, bool *hasz) +{ + xmlChar *dimension, *gmlposlist; + char *poslist, *p; + int dim, gml_dim; + DYNPTARRAY *dpa; + POINTARRAY *pa; + POINT4D pt; + bool digit; + uchar dims=0; + + /* Retrieve gml:dimension attribute if any */ + dimension = xmlGetProp(xnode, (xmlChar *) "dimension"); + if (dimension == NULL) dim = 2; /* We assume that we are in common 2D */ + else { + dim = atoi((char *) dimension); + xmlFree(dimension); + if (dim < 2 || dim > 3) lwerror("invalid GML representation"); + } + if (dim == 2) *hasz = false; + + /* Retrieve gml:posList string */ + gmlposlist = xmlNodeGetContent(xnode); + poslist = (char *) gmlposlist; + + TYPE_SETZM(dims, 1, 0); + dpa = dynptarray_create(1, dims); + + /* gml:posList pattern: x1 y1 x2 y2 + * x1 y1 z1 x2 y2 z2 + */ + while(isspace(*poslist)) poslist++; /* Eat extra whitespaces if any */ + for (p=poslist, gml_dim=0, digit=false ; *poslist ; poslist++) { + + if (isdigit(*poslist)) digit = true; + + if (digit && (*poslist == ' ' || *(poslist+1) == '\0')) { + + if (*poslist == ' ') *poslist = '\0'; + + gml_dim++; + if (gml_dim == 1) pt.x = parse_gml_double(p, 0, 1); + else if (gml_dim == 2) pt.y = parse_gml_double(p, 0, 1); + else if (gml_dim == 3) pt.z = parse_gml_double(p, 0, 1); + + if (gml_dim == dim) { + dynptarray_addPoint4d(dpa, &pt, 0); + gml_dim = 0; + } else if (*(poslist+1) == '\0') + lwerror("invalid GML representation"); + + p = poslist+1; + digit = false; + } + } + + xmlFree(gmlposlist); + pa = ptarray_clone(dpa->pa); + lwfree(dpa); + + return pa; +} + + +/** + * Parse data coordinates + * + * There's four ways to encode coordinates: + * - gml:pos element + * - gml:posList element + * - gml:coord elements with X,Y(,Z) nested elements (deprecated in 3.0.0) + * - gml:coordinate element with tuples string inside (deprecated in 3.1.0) + * + * Cf: GML 2.1.2 -> 4.3.2 (p17) + * Cf: GML 3.1.1 -> 9.1.3.5 (p45) + * + * NOTA: we don't support pointRep references ! + */ +static POINTARRAY * parse_gml_data(xmlNodePtr xnode, bool *hasz) +{ + bool coordinates, coord, pos, poslist; + xmlNodePtr node; + + coordinates = coord = pos = poslist = false; + + for (node = xnode ; node != NULL ; node = node->next) { + + if (node->type != XML_ELEMENT_NODE) continue; + if (!strcmp((char *) node->name, "pos")) { + pos=true; + break; + } else if (!strcmp((char *) node->name, "posList")) { + poslist=true; + break; + } else if (!strcmp((char *) node->name, "coordinates")) { + coordinates=true; + break; + } else if (!strcmp((char *) node->name, "coord")) { + coord=true; + break; + } + } + + if (pos) return parse_gml_pos(node, hasz); + if (poslist) return parse_gml_poslist(node, hasz); + if (coordinates) return parse_gml_coordinates(node, hasz); + if (coord) return parse_gml_coord(node, hasz); + + lwerror("invalid GML representation"); + + return NULL; +} + + +/** + * Parse gml srsName attribute + */ +static int parse_gml_srs(xmlNodePtr xnode) +{ + xmlChar *srs; + char *p; + int srid=-1; + + srs = xmlGetProp(xnode, (xmlChar *) "srsName"); + if (!srs) return -1; /* Default srid if no srsName attribute */ + + /* Severals srsName formats are available... + * cf WFS 1.1.0 -> 9.2 (p36) + * cf ISO 19142 -> 7.9.2.4.4 (p34) + * cf RFC 5165 + */ + + /* SRS pattern like: EPSG:4326 + urn:EPSG:geographicCRS:4326 + urn:ogc:def:crs:EPSG:4326 + urn:ogc:def:crs:EPSG::4326 + urn:ogc:def:crs:EPSG:6.6:4326 + urn:x-ogc:def:crs:EPSG:6.6:4326 */ + + if ( !strncmp((char *) srs, "EPSG:", 5) + || !strncmp((char *) srs, "urn:ogc:def:crs:EPSG:", 21) + || !strncmp((char *) srs, "urn:x-ogc:def:crs:EPSG:", 23) + || !strncmp((char *) srs, "urn:EPSG:geographicCRS:", 23)) { + + /* retrieve the last ':' char */ + for (p = (char *) srs ; *p ; p++); + for (--p ; *p != ':' ; p--) + if (!isdigit(*p)) lwerror("unknown spatial reference system"); + + srid = atoi(++p); + + /* SRS pattern like: http://www.opengis.net/gml/srs/epsg.xml#4326 */ + } else if (!strncmp((char *) srs, "http://www.opengis.net/gml/srs/epsg.xml#", 40)) { + p = strchr((char *) srs, '#'); + srid = atoi(++p); + } + + /* Check into spatial_ref_sys that this SRID really exist */ + if (srid == -1 || getSRSbySRID(srid, true) == NULL) + lwerror("unknown spatial reference system"); + + xmlFree(srs); + return srid; +} + + +/** + * Parse GML point (2.1.2, 3.x.x) + */ +static LWGEOM* parse_gml_point(xmlNodePtr xnode, bool *hasz) +{ + int srid; + POINTARRAY *pa; + + srid = parse_gml_srs(xnode); + + pa = parse_gml_data(xnode->children, hasz); + if (pa->npoints != 1) + lwerror("invalid GML representation"); + + return (LWGEOM *) lwpoint_construct(srid, NULL, pa); +} + + +/** + * Parse GML lineString (2.1.2, 3.x.x) + */ +static LWGEOM* parse_gml_line(xmlNodePtr xnode, bool *hasz) +{ + int srid; + POINTARRAY *pa; + + srid = parse_gml_srs(xnode); + pa = parse_gml_data(xnode->children, hasz); + if (pa->npoints < 2) + lwerror("invalid GML representation"); + + return (LWGEOM *) lwline_construct(srid, NULL, pa); +} + + +/** + * Parse GML Curve (3.x.x) + */ +static LWGEOM* parse_gml_curve(xmlNodePtr xnode, bool *hasz) +{ + int srid, lss, last, i; + xmlChar *interpolation; + POINTARRAY **ppa; + POINTARRAY *pa; + xmlNodePtr xa; + bool found=false; + unsigned int npoints=0; + + srid = parse_gml_srs(xnode); + + /* Looking for gml:segments */ + for (xa = xnode->children ; xa != NULL ; xa = xa->next) { + + if (xa->type != XML_ELEMENT_NODE) continue; + if (!strcmp((char *) xa->name, "segments")) { + found = true; + break; + } + } + if (!found) lwerror("invalid GML representation"); + + ppa = (POINTARRAY**) lwalloc(sizeof(POINTARRAY*)); + + /* Processing each gml:LineStringSegment */ + for (xa = xa->children, lss=0; xa != NULL ; xa = xa->next) { + + if (xa->type != XML_ELEMENT_NODE) continue; + if (strcmp((char *) xa->name, "LineStringSegment")) continue; + + /* GML SF is resticted to linear interpolation */ + interpolation = xmlGetProp(xa, (xmlChar *) "interpolation"); + if (interpolation != NULL) { + if (strcmp((char *) interpolation, "linear")) + lwerror("invalid GML representation"); + xmlFree(interpolation); + } + + if (lss > 0) ppa = (POINTARRAY**) lwrealloc((LWLINE *) ppa, + sizeof(POINTARRAY*) * (lss + 1)); + + ppa[lss] = parse_gml_data(xa->children, hasz); + npoints += ppa[lss]->npoints; + if (ppa[lss]->npoints < 2) + lwerror("invalid GML representation"); + lss++; + } + if (lss == 0) lwerror("invalid GML representation"); + + /* Most common case, a single segment */ + if (lss == 1) return (LWGEOM *) lwline_construct(srid, NULL, ppa[0]); + + + /* + * "The curve segments are connected to one another, with the end point + * of each segment except the last being the start point of the next + * segment" from ISO 19107 -> 6.3.16.1 (p43) + * + * So we must aggregate all the segments into a single one and avoid + * to copy the redundants points + */ + pa = ptarray_construct(1, 0, npoints - (lss - 1)); + for (last = npoints = i = 0; i < lss ; i++) { + + if (i + 1 == lss) last = 1; + /* Check if segments are not disjoints */ + if (i > 0 && memcmp( getPoint_internal(pa, npoints), + getPoint_internal(ppa[i], 0), + *hasz?sizeof(POINT3D):sizeof(POINT2D))) + lwerror("invalid GML representation"); + + /* Aggregate stuff */ + memcpy( getPoint_internal(pa, npoints), + getPoint_internal(ppa[i], 0), + pointArray_ptsize(ppa[i]) * (ppa[i]->npoints + last)); + + npoints += ppa[i]->npoints - 1; + lwfree(ppa[i]); + } + lwfree(ppa); + + return (LWGEOM *) lwline_construct(srid, NULL, pa); +} + + +/** + * Parse GML Polygon (2.1.2, 3.x.x) + */ +static LWGEOM* parse_gml_polygon(xmlNodePtr xnode, bool *hasz) +{ + int srid, ring; + xmlNodePtr xa, xb; + POINTARRAY **ppa = NULL; + + for (xa = xnode->children ; xa != NULL ; xa = xa->next) { + + /* Polygon/outerBoundaryIs -> GML 2.1.2 */ + /* Polygon/exterior -> GML 3.x.x */ + if (xa->type != XML_ELEMENT_NODE) continue; + if (strcmp((char *) xa->name, "outerBoundaryIs") && + strcmp((char *) xa->name, "exterior")) continue; + + for (xb = xa->children ; xb != NULL ; xb = xb->next) { + + if (xb->type != XML_ELEMENT_NODE) continue; + if (strcmp((char *) xb->name, "LinearRing")) continue; + + ppa = (POINTARRAY**) lwalloc(sizeof(POINTARRAY*)); + ppa[0] = parse_gml_data(xb->children, hasz); + + /* FIXME: And what about the 3D ? */ + if (ppa[0]->npoints < 4 || !ptarray_isclosed2d(ppa[0])) + lwerror("invalid GML representation"); + } + } + + for (ring=1, xa = xnode->children ; xa != NULL ; xa = xa->next) { + + /* Polygon/innerBoundaryIs -> GML 2.1.2 */ + /* Polygon/interior -> GML 3.x.x */ + if (xa->type != XML_ELEMENT_NODE) continue; + if (strcmp((char *) xa->name, "innerBoundaryIs") && + strcmp((char *) xa->name, "interior")) continue; + + for (xb = xa->children ; xb != NULL ; xb = xb->next) { + + if (xb->type != XML_ELEMENT_NODE) continue; + if (strcmp((char *) xb->name, "LinearRing")) continue; + + ppa = (POINTARRAY**) lwrealloc((POINTARRAY *) ppa, + sizeof(POINTARRAY*) * (ring + 1)); + ppa[ring] = parse_gml_data(xb->children, hasz); + + /* FIXME: And what about the 3D ? */ + if (ppa[ring]->npoints < 4 || !ptarray_isclosed2d(ppa[ring])) + lwerror("invalid GML representation"); + ring++; + } + } + + /* Exterior Ring is mandatory */ + if (ppa == NULL || ppa[0] == NULL) lwerror("invalid GML representation"); + + srid = parse_gml_srs(xnode); + return (LWGEOM*) lwpoly_construct(srid, NULL, ring, ppa); +} + + +/** + * Parse GML Surface (3.x.x) + */ +static LWGEOM* parse_gml_surface(xmlNodePtr xnode, bool *hasz) +{ + xmlChar *interpolation; + xmlNodePtr xa, xb, xc; + int patch, ring, srid; + POINTARRAY **ppa; + bool found=false; + + /* Looking for gml:patches */ + for (xa = xnode->children ; xa != NULL ; xa = xa->next) { + + if (xa->type != XML_ELEMENT_NODE) continue; + if (!strcmp((char *) xa->name, "patches")) { + found = true; + break; + } + } + if (!found) lwerror("invalid GML representation"); + + /* Processing gml:PolygonPatch */ + for (patch=0, xa = xa->children ; xa != NULL ; xa = xa->next) { + + if (xa->type != XML_ELEMENT_NODE) continue; + if (strcmp((char *) xa->name, "PolygonPatch")) continue; + patch++; + + /* SQL/MM define ST_CurvePolygon as a single patch only, + cf ISO 13249-3 -> 4.2.9 (p27) */ + if (patch > 1) lwerror("invalid GML representation"); + + /* GML SF is resticted to planar interpolation */ + interpolation = xmlGetProp(xa, (xmlChar *) "interpolation"); + if (interpolation != NULL) { + if (strcmp((char *) interpolation, "planar")) + lwerror("invalid GML representation"); + xmlFree(interpolation); + } + + /* PolygonPatch/exterior */ + for (xb = xa->children ; xb != NULL ; xb = xb->next) { + if (strcmp((char *) xb->name, "exterior")) continue; + + /* PolygonPatch/exterior/LinearRing */ + for (xc = xb->children ; xc != NULL ; xc = xc->next) { + + if (xc->type != XML_ELEMENT_NODE) continue; + if (strcmp((char *) xc->name, "LinearRing")) continue; + + ppa = (POINTARRAY**) lwalloc(sizeof(POINTARRAY*)); + ppa[0] = parse_gml_data(xc->children, hasz); + + /* FIXME: And what about the 3D ? */ + if (ppa[0]->npoints < 4 || !ptarray_isclosed2d(ppa[0])) + lwerror("invalid GML representation"); + } + } + + /* PolygonPatch/interior */ + for (ring=1, xb = xa->children ; xb != NULL ; xb = xb->next) { + + if (xb->type != XML_ELEMENT_NODE) continue; + if (strcmp((char *) xb->name, "interior")) continue; + if (xb->children == NULL) break; /* FIXME Why this is needed ??? */ + + /* PolygonPatch/interior/LinearRing */ + for (xc = xb->children ; xc != NULL ; xc = xc->next) { + + if (xc->type != XML_ELEMENT_NODE) continue; + if (strcmp((char *) xc->name, "LinearRing")) continue; + + ppa = (POINTARRAY**) lwrealloc((POINTARRAY *) ppa, + sizeof(POINTARRAY*) * (ring + 1)); + ppa[ring] = parse_gml_data(xc->children, hasz); + + /* FIXME: And what about the 3D ? */ + if (ppa[ring]->npoints < 4 || !ptarray_isclosed2d(ppa[ring])) + lwerror("invalid GML representation"); + } + ring++; + } + } + + /* Exterior Ring is mandatory */ + if (ppa == NULL || ppa[0] == NULL) lwerror("invalid GML representation"); + + srid = parse_gml_srs(xnode); + return (LWGEOM*) lwpoly_construct(srid, NULL, ring, ppa); +} + + +/** + * Parse gml:MultiPoint (2.1.2, 3.x.x) + */ +static LWGEOM* parse_gml_mpoint(xmlNodePtr xnode, bool *hasz) +{ + int srid; + xmlNodePtr xa; + LWGEOM *geom = NULL; + + srid = parse_gml_srs(xnode); + + geom = (LWGEOM *)lwcollection_construct_empty(srid, 1, 0); + geom->type = lwgeom_makeType(1, 0, srid != -1, MULTIPOINTTYPE); + + for (xa = xnode->children ; xa != NULL ; xa = xa->next) { + + /* MultiPoint/pointMember */ + if (xa->type != XML_ELEMENT_NODE) continue; + if (strcmp((char *) xa->name, "pointMember")) continue; + if (xa->children != NULL) + geom = lwmpoint_add((LWMPOINT *)geom, -1, + parse_gml(xa->children, hasz)); + } + + return geom; +} + + +/** + * Parse gml:MultiLineString (2.1.2, 3.x.x) + */ +static LWGEOM* parse_gml_mline(xmlNodePtr xnode, bool *hasz) +{ + int srid; + xmlNodePtr xa; + LWGEOM *geom = NULL; + + srid = parse_gml_srs(xnode); + + geom = (LWGEOM *)lwcollection_construct_empty(srid, 1, 0); + geom->type = lwgeom_makeType(1, 0, srid != -1, MULTILINETYPE); + + for (xa = xnode->children ; xa != NULL ; xa = xa->next) { + + /* MultiLineString/lineMember */ + if (xa->type != XML_ELEMENT_NODE) continue; + if (strcmp((char *) xa->name, "lineStringMember")) continue; + if (xa->children != NULL) + geom = lwmline_add((LWMLINE *)geom, -1, + parse_gml(xa->children, hasz)); + } + + return geom; +} + + +/** + * Parse GML MultiCurve (3.x.x) + */ +static LWGEOM* parse_gml_mcurve(xmlNodePtr xnode, bool *hasz) +{ + int srid; + xmlNodePtr xa; + LWGEOM *geom = NULL; + + srid = parse_gml_srs(xnode); + + geom = (LWGEOM *)lwcollection_construct_empty(srid, 1, 0); + geom->type = lwgeom_makeType(1, 0, srid != -1, MULTILINETYPE); + + for (xa = xnode->children ; xa != NULL ; xa = xa->next) { + + /* MultiCurve/curveMember */ + if (xa->type != XML_ELEMENT_NODE) continue; + if (strcmp((char *) xa->name, "curveMember")) continue; + if (xa->children != NULL) + geom = lwmline_add((LWMLINE *)geom, -1, + parse_gml(xa->children, hasz)); + } + + return geom; +} + + +/** + * Parse GML MultiPolygon (2.1.2, 3.x.x) + */ +static LWGEOM* parse_gml_mpoly(xmlNodePtr xnode, bool *hasz) +{ + int srid; + xmlNodePtr xa; + LWGEOM *geom = NULL; + + srid = parse_gml_srs(xnode); + + geom = (LWGEOM *)lwcollection_construct_empty(srid, 1, 0); + geom->type = lwgeom_makeType(1, 0, srid != -1, MULTIPOLYGONTYPE); + + for (xa = xnode->children ; xa != NULL ; xa = xa->next) { + + /* MultiPolygon/polygonMember */ + if (xa->type != XML_ELEMENT_NODE) continue; + if (strcmp((char *) xa->name, "polygonMember")) continue; + if (xa->children != NULL) + geom = lwmpoly_add((LWMPOLY *)geom, -1, + parse_gml(xa->children, hasz)); + } + + return geom; +} + + +/** + * Parse GML MultiSurface (3.x.x) + */ +static LWGEOM* parse_gml_msurface(xmlNodePtr xnode, bool *hasz) +{ + int srid; + xmlNodePtr xa; + LWGEOM *geom = NULL; + + srid = parse_gml_srs(xnode); + + geom = (LWGEOM *)lwcollection_construct_empty(srid, 1, 0); + geom->type = lwgeom_makeType(1, 0, srid != -1, MULTIPOLYGONTYPE); + + for (xa = xnode->children ; xa != NULL ; xa = xa->next) { + + /* MultiSurface/surfaceMember */ + if (xa->type != XML_ELEMENT_NODE) continue; + if (strcmp((char *) xa->name, "surfaceMember")) continue; + if (xa->children != NULL) + geom = lwmpoly_add((LWMPOLY *)geom, -1, + parse_gml(xa->children, hasz)); + } + + return geom; +} + + +/** + * Parse GML MultiGeometry (2.1.2, 3.x.x) + */ +static LWGEOM* parse_gml_coll(xmlNodePtr xnode, bool *hasz) +{ + int srid; + xmlNodePtr xa; + LWGEOM *geom = NULL; + + srid = parse_gml_srs(xnode); + + geom = (LWGEOM *)lwcollection_construct_empty(srid, 1, 0); + geom->type = lwgeom_makeType(1, 0, srid != -1, COLLECTIONTYPE); + + for (xa = xnode->children ; xa != NULL ; xa = xa->next) { + + if (xa->type != XML_ELEMENT_NODE) continue; + + if ( !strcmp((char *) xa->name, "pointMember") + || !strcmp((char *) xa->name, "lineMember") + || !strcmp((char *) xa->name, "curveMember") + || !strcmp((char *) xa->name, "polygonMember") + || !strcmp((char *) xa->name, "surfaceMember") + || !strcmp((char *) xa->name, "geometryMember")) { + + if (xa->children == NULL) break; + geom = lwcollection_add((LWCOLLECTION *)geom, -1, + parse_gml(xa->children, hasz)); + + } else if ( !strcmp((char *) xa->name, "MultiPoint") + || !strcmp((char *) xa->name, "MultiLineString") + || !strcmp((char *) xa->name, "MultiCurve") + || !strcmp((char *) xa->name, "MultiPolygon") + || !strcmp((char *) xa->name, "MultiSurface") + || !strcmp((char *) xa->name, "MultiGeometry")) { + + if (xa->children == NULL) break; + geom = lwcollection_add((LWCOLLECTION *)geom, -1, + parse_gml(xa, hasz)); + } + } + + return geom; +} + + +/** + * Parse GML + */ +static LWGEOM* parse_gml(xmlNodePtr xnode, bool *hasz) +{ + xmlNodePtr xa = xnode; + + while (xa != NULL && xa->type != XML_ELEMENT_NODE) xa = xa->next; + + if (!strcmp((char *) xa->name, "Point")) + return parse_gml_point(xa, hasz); + + if (!strcmp((char *) xa->name, "LineString")) + return parse_gml_line(xa, hasz); + + if (!strcmp((char *) xa->name, "Curve")) + return parse_gml_curve(xa, hasz); + + if (!strcmp((char *) xa->name, "Polygon")) + return parse_gml_polygon(xa, hasz); + + if (!strcmp((char *) xa->name, "Surface")) + return parse_gml_surface(xa, hasz); + + if (!strcmp((char *) xa->name, "MultiPoint")) + return parse_gml_mpoint(xa, hasz); + + if (!strcmp((char *) xa->name, "MultiLineString")) + return parse_gml_mline(xa, hasz); + + if (!strcmp((char *) xa->name, "MultiCurve")) + return parse_gml_mcurve(xa, hasz); + + if (!strcmp((char *) xa->name, "MultiPolygon")) + return parse_gml_mpoly(xa, hasz); + + if (!strcmp((char *) xa->name, "MultiSurface")) + return parse_gml_msurface(xa, hasz); + + if (!strcmp((char *) xa->name, "MultiGeometry")) + return parse_gml_coll(xa, hasz); + + lwerror("invalid GML representation"); + return NULL; /* Never reach */ +} + +#endif /* if HAVE_LIBXML2 */ diff --git a/postgis/postgis.sql.in.c b/postgis/postgis.sql.in.c index 2070b47d3..811779189 100644 --- a/postgis/postgis.sql.in.c +++ b/postgis/postgis.sql.in.c @@ -4532,6 +4532,23 @@ CREATE OR REPLACE FUNCTION ST_Equals(geometry,geometry) AS 'MODULE_PATHNAME','geomequals' LANGUAGE 'C' IMMUTABLE STRICT; + +#if HAVE_LIBXML2 +----------------------------------------------------------------------- +-- GML INPUT +-- Availability: 1.5.0 +----------------------------------------------------------------------- +CREATE OR REPLACE FUNCTION ST_GeomFromGML(text) + RETURNS geometry + AS 'MODULE_PATHNAME','geom_from_gml' + LANGUAGE 'C' IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION ST_GMLToSQL(text) + RETURNS geometry + AS 'MODULE_PATHNAME','geom_from_gml' + LANGUAGE 'C' IMMUTABLE STRICT; + +#endif ----------------------------------------------------------------------- -- SVG OUTPUT ----------------------------------------------------------------------- diff --git a/regress/Makefile.in b/regress/Makefile.in index 70648d26f..1ac78a3b4 100644 --- a/regress/Makefile.in +++ b/regress/Makefile.in @@ -3,6 +3,7 @@ TMPDIR?=/tmp POSTGIS_PGSQL_VERSION=@POSTGIS_PGSQL_VERSION@ POSTGIS_GEOS_VERSION=@POSTGIS_GEOS_VERSION@ POSTGIS_PROJ_VERSION=@POSTGIS_PROJ_VERSION@ +HAVE_LIBXML2=@HAVE_LIBXML2@ # MingW hack: rather than use PGSQL_BINDIR directly, we change # to the directory and then use "pwd" to return the path. This @@ -81,6 +82,12 @@ ifeq ($(shell expr $(POSTGIS_GEOS_VERSION) ">=" 32),1) TESTS += hausdorff endif +# GeomFromGML need libxml2 +ifeq ($(shell expr $(HAVE_LIBXML2) "=" 1),1) + TESTS += in_gml +endif + + all: test diff --git a/regress/in_gml.sql b/regress/in_gml.sql new file mode 100644 index 000000000..40fece605 --- /dev/null +++ b/regress/in_gml.sql @@ -0,0 +1,783 @@ +-- +-- GeomFromGML regression test +-- Written by Olivier Courtin - Oslandia +-- + + +-- +-- spatial_ref_sys data +-- +INSERT INTO "spatial_ref_sys" ("srid","auth_name","auth_srid","srtext","proj4text") VALUES (4326,'EPSG',4326,'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs '); + + +-- Empty Geometry +SELECT 'empty_geom', ST_AsEWKT(ST_GeomFromGML(NULL)); + +-- +-- XML +-- + +-- Empty String +SELECT 'xml_1', ST_AsEWKT(ST_GeomFromGML('')); + +-- Not well formed XML +SELECT 'xml_2', ST_AsEWKT(ST_GeomFromGML('')); + +-- Not a GML Geometry +SELECT 'xml_3', ST_AsEWKT(ST_GeomFromGML('')); + + + +-- +-- Point +-- + +-- 1 Point +SELECT 'point_1', ST_AsEWKT(ST_GeomFromGML('1,2')); + +-- ERROR: 2 points +SELECT 'point_2', ST_AsEWKT(ST_GeomFromGML('1,2 3,4')); + +-- ERROR: empty point +SELECT 'point_3', ST_AsEWKT(ST_GeomFromGML('')); + +-- srsName handle +SELECT 'point_4', ST_AsEWKT(ST_GeomFromGML('1 2')); + + + +-- +-- LineString +-- + +-- 2 Points +SELECT 'linestring_1', ST_AsEWKT(ST_GeomFromGML('1,2 3,4')); + +-- ERROR 1 Point +SELECT 'linestring_2', ST_AsEWKT(ST_GeomFromGML('1,2')); + +-- srsName handle +SELECT 'linestring_3', ST_AsEWKT(ST_GeomFromGML('1,2 3,4')); + +-- ERROR: empty coordinates +SELECT 'linestring_4', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'linestring_5', ST_AsEWKT(ST_GeomFromGML('')); + +-- XML not elements handle +SELECT 'linestring_6', ST_AsEWKT(ST_GeomFromGML(' 1,2 3,4')); + + + + +-- +-- Curve +-- + +-- 2 Points +SELECT 'curve_1', ST_AsEWKT(ST_GeomFromGML('1 2 3 4')); + +-- ERROR 1 Point +SELECT 'curve_2', ST_AsEWKT(ST_GeomFromGML('1 2')); + +-- srsName handle +SELECT 'curve_3', ST_AsEWKT(ST_GeomFromGML('1 2 3 4')); + +-- ERROR: empty coordinates +SELECT 'curve_4', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'curve_5', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'curve_6', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'curve_7', ST_AsEWKT(ST_GeomFromGML('')); + +-- linear interpolation +SELECT 'curve_8', ST_AsEWKT(ST_GeomFromGML('1 2 3 4')); + +-- ERROR: wrong interpolation +SELECT 'curve_9', ST_AsEWKT(ST_GeomFromGML('1 2 3 4')); + +-- XML not elements handle +SELECT 'curve_10', ST_AsEWKT(ST_GeomFromGML(' 1 2 3 4')); + +-- 2 Segments +SELECT 'curve_11', ST_AsEWKT(ST_GeomFromGML('1 2 3 43 4 5 6')); +SELECT 'curve_12', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5 64 5 6 7 8 9')); + +-- ERROR 2 Segments disjoint +SELECT 'curve_13', ST_AsEWKT(ST_GeomFromGML('1 2 3 45 6 7 8')); + +-- ERROR 2 3D Segments disjoint in Z +SELECT 'curve_14', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5 64 5 0 7 8 9')); + +-- 2 segments, mixed dimension +SELECT 'curve_15', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5 64 5 7 8')); +SELECT 'curve_16', ST_AsEWKT(ST_GeomFromGML('1 2 3 43 4 5 6 7 8')); + + + + +-- +-- Polygon +-- + +-- GML 2 - 1 ring +SELECT 'polygon_1', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,2')); + +-- srsName handle +SELECT 'polygon_2', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,2')); + +-- ERROR: In exterior ring: Last point is not the same as the first one +SELECT 'polygon_3', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,3')); + +-- TODO ERROR: In exterior 3D ring: Last point is not the same as the first one in Z + +-- ERROR: Only 3 points in exterior ring +SELECT 'polygon_4', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 1,2')); + +-- ERROR: Empty exterior ring coordinates +SELECT 'polygon_5', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'polygon_6', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'polygon_7', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'polygon_8', ST_AsEWKT(ST_GeomFromGML('')); + +-- GML 2 - 2 rings +SELECT 'polygon_9', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,27,8 9,10 11,12 7,8')); + +-- XML not elements handle +SELECT 'polygon_10', ST_AsEWKT(ST_GeomFromGML(' 1,2 3,4 5,6 1,2 7,8 9,10 11,12 7,8')); + +-- Empty interior ring coordinates (even if defined) +SELECT 'polygon_11', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,2')); + +-- ERROR: Only 3 points in interior ring +SELECT 'polygon_12', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,27,8 9,10 7,8')); + +-- ERROR: In interior ring: Last point is not the same as the first one +SELECT 'polygon_13', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,27,8 9,10 11,12 7,9')); + +-- TODO ERROR: In interior 3D ring: Last point is not the same as the first one in Z + +-- GML 2 - 3 rings +SELECT 'polygon_14', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,27,8 9,10 11,12 7,813,14 15,16 17,18 13,14')); + +-- GML 3 +SELECT 'polygon_15', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,27,8 9,10 11,12 7,8')); + +-- Mixed dimension in rings +SELECT 'polygon_16', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5 6 7 8 9 1 2 310 11 12 13 14 15 10 11')); +SELECT 'polygon_17', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5 6 1 27 8 9 10 11 12 13 14 15 7 8 9')); + + + + +-- +-- Surface +-- + +-- 1 ring +SELECT 'surface_1', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,2')); + +-- srsName handle +SELECT 'surface_2', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,2')); + +-- ERROR: In exterior ring: Last point is not the same as the first one +SELECT 'surface_3', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,0')); + +-- TODO -- ERROR: In exterior 3D ring: Last point is not the same as the first one in Z + +-- ERROR: Only 3 points in exterior ring +SELECT 'surface_4', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 1,2')); + +-- ERROR: Empty exterior ring coordinates +SELECT 'surface_5', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'surface_6', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'surface_7', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'surface_8', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'surface_9', ST_AsEWKT(ST_GeomFromGML('')); + +-- 2 rings +SELECT 'surface_10', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,27,8 9,10 11,12 7,8')); + +-- XML not elements handle +SELECT 'surface_11', ST_AsEWKT(ST_GeomFromGML(' 1,2 3,4 5,6 1,2 7,8 9,10 11,12 7,8')); + +-- Empty interior ring coordinates (even if defined) +SELECT 'surface_12', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,2')); + +-- ERROR: Only 3 points in interior ring +SELECT 'surface_13', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,27,8 9,10 7,8')); + +-- ERROR: In interior ring: Last point is not the same as the first one +SELECT 'surface_14', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,27,8 9,10 11,12 7,0')); + +-- TODO -- ERROR: In interior 3D ring: Last point is not the same as the first one in Z + +-- 3 rings +SELECT 'surface_15', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,27,8 9,10 11,12 7,813,14 15,16 17,18 13,14')); + +-- Mixed dimension in rings +SELECT 'surface_16', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5 6 7 8 9 1 2 310 11 12 13 14 15 10 11')); +SELECT 'surface_17', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5 6 1 27 8 9 10 11 12 13 14 15 7 8 9')); + +-- ERROR: two patches +SELECT 'surface_18', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,27,8 9,10 11,12 7,8')); + +-- planar interpolation +SELECT 'surface_19', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,2')); + +-- ERROR: interpolation not planar +SELECT 'surface_20', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,2')); + + + + +-- +-- MultiPoint +-- + +-- 1 point +SELECT 'mpoint_1', ST_AsEWKT(ST_GeomFromGML('1,2')); + +-- 2 points +SELECT 'mpoint_2', ST_AsEWKT(ST_GeomFromGML('1,23,4')); + +-- srsName handle +SELECT 'mpoint_3', ST_AsEWKT(ST_GeomFromGML('1,2')); + +-- Empty MultiPoints +SELECT 'mpoint_4', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'mpoint_5', ST_AsEWKT(ST_GeomFromGML('')); + +-- XML not elements handle +SELECT 'mpoint_6', ST_AsEWKT(ST_GeomFromGML(' 1,2 3,4')); + +-- TODO Mixed srsName + + + + +-- +-- MultiLineString +-- + +-- 1 line +SELECT 'mline_1', ST_AsEWKT(ST_GeomFromGML('1,2 3,4')); + +-- 2 lines +SELECT 'mline_2', ST_AsEWKT(ST_GeomFromGML('1,2 3,45,6 7,8')); + +-- srsName handle +SELECT 'mline_3', ST_AsEWKT(ST_GeomFromGML('1,2 3,4')); + +-- Empty MultiLineString +SELECT 'mline_4', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'mline_5', ST_AsEWKT(ST_GeomFromGML('')); + +-- XML not elements handle +SELECT 'mline_6', ST_AsEWKT(ST_GeomFromGML(' 1,2 3,4 5,6 7,8')); + +-- Mixed dimension +SELECT 'mline_7', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5 67 8 9 10')); +SELECT 'mline_8', ST_AsEWKT(ST_GeomFromGML('1 2 3 45 6 7 8 9 10')); + +-- TODO Mixed srsName + + + + +-- +-- MultiCurve +-- + +-- 1 curve +SELECT 'mcurve_1', ST_AsEWKT(ST_GeomFromGML('1 2 3 4')); + +-- 2 curves +SELECT 'mcurve_2', ST_AsEWKT(ST_GeomFromGML('1 2 3 45 6 7 8')); + +-- srsName handle +SELECT 'mcurve_3', ST_AsEWKT(ST_GeomFromGML('1 2 3 4')); + +-- Empty Curve +SELECT 'mcurve_4', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'mcurve_5', ST_AsEWKT(ST_GeomFromGML('')); + +-- XML not elements handle +SELECT 'mcurve_6', ST_AsEWKT(ST_GeomFromGML(' 1 2 3 4 5 6 7 8')); + +-- Mixed dimension +SELECT 'mcurve_7', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5 67 8 9 10')); +SELECT 'mcurve_8', ST_AsEWKT(ST_GeomFromGML('1 2 3 45 6 7 8 9 10')); + +-- TODO Mixed srsName + + + +-- +-- MultiPolygon +-- + +-- 1 polygon +SELECT 'mpoly_1', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,2')); + +-- 2 polygons +SELECT 'mpoly_2', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,27,8 9,10 11,12 7,8')); + +-- srsName handle +SELECT 'mpoly_3', ST_AsEWKT(ST_GeomFromGML('1,2 3,4 5,6 1,2')); + +-- Empty MultiPolygon +SELECT 'mpoly_4', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'mpoly_5', ST_AsEWKT(ST_GeomFromGML('')); + + +-- XML not elements handle +SELECT 'mpoly_6', ST_AsEWKT(ST_GeomFromGML(' 1,2 3,4 5,6 1,2 7,8 9,10 11,12 7,8')); + +-- Mixed dimension +SELECT 'mpoly_7', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5 6 7 8 9 1 2 310 11 12 13 14 15 10 11')); +SELECT 'mpoly_8', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5 6 1 27 8 9 10 11 12 13 14 15 7 8 9')); + +-- TODO Mixed srsName + + + + +-- +-- MultiSurface +-- + +-- 1 surface +SELECT 'msurface_1', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5 6 1 2')); + +-- 2 surfaces +SELECT 'msurface_2', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5 6 1 27 8 9 10 11 12 7 8')); + +-- srsName handle +SELECT 'msurface_3', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5 6 1 2')); + +-- Empty MultiSurface +SELECT 'msurface_4', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'msurface_5', ST_AsEWKT(ST_GeomFromGML('')); + +-- XML not elements handle +SELECT 'msurface_6', ST_AsEWKT(ST_GeomFromGML(' 1 2 3 4 5 6 1 2 7 8 9 10 11 12 7 8')); + +-- Mixed dimension +SELECT 'msurface_7', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5 6 7 8 9 1 2 310 11 12 13 14 15 10 11')); +SELECT 'msurface_8', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5 6 1 27 8 9 10 11 12 13 14 15 7 8 9')); + +-- TODO Mixed srsName + + + +-- +-- GeometryCollection +-- + +-- 1 simple geom +SELECT 'collection_1', ST_AsEWKT(ST_GeomFromGML('1,2')); + +-- 2 simples geom +SELECT 'collection_2', ST_AsEWKT(ST_GeomFromGML('1 23 4 5 6')); + +-- 1 multi geom +SELECT 'collection_3', ST_AsEWKT(ST_GeomFromGML('1 23 4')); + +-- 2 multi geom +SELECT 'collection_4', ST_AsEWKT(ST_GeomFromGML('1 23 45 6 7 89 10 11 12')); + +-- 2 multi geom and 2 simples +SELECT 'collection_5', ST_AsEWKT(ST_GeomFromGML('1 23 45 67 8 9 1011 12 13 1415 16 17 18 19 20 15 16')); + +-- Empty collection +SELECT 'collection_6', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'collection_7', ST_AsEWKT(ST_GeomFromGML('')); + +-- Collection of collection +SELECT 'collection_8', ST_AsEWKT(ST_GeomFromGML('1,23,4')); + +-- Collection of collection of collection +SELECT 'collection_9', ST_AsEWKT(ST_GeomFromGML('1,23,4')); + +-- srsName handle +SELECT 'collection_10', ST_AsEWKT(ST_GeomFromGML('1,2')); + +-- XML not elements handle +SELECT 'collection_11', ST_AsEWKT(ST_GeomFromGML(' 1,2 3,4')); + +-- Mixed dimension +SELECT 'collection_12', ST_AsEWKT(ST_GeomFromGML('1 2 34 5')); +SELECT 'collection_13', ST_AsEWKT(ST_GeomFromGML('1 23 4 5')); + +-- TODO Mixed srsName + + + + + +-- +-- srsName +-- + +-- Supported srsName patterns +SELECT 'srs_1', ST_AsEWKT(ST_GeomFromGML('1 2')); +SELECT 'srs_2', ST_AsEWKT(ST_GeomFromGML('1 2')); +SELECT 'srs_3', ST_AsEWKT(ST_GeomFromGML('1 2')); +SELECT 'srs_4', ST_AsEWKT(ST_GeomFromGML('1 2')); +SELECT 'srs_5', ST_AsEWKT(ST_GeomFromGML('1 2')); +SELECT 'srs_6', ST_AsEWKT(ST_GeomFromGML('1 2')); +SELECT 'srs_7', ST_AsEWKT(ST_GeomFromGML('1 2')); +SELECT 'srs_8', ST_AsEWKT(ST_GeomFromGML('1 2')); + +-- ERROR not a valid pattern +SELECT 'srs_9', ST_AsEWKT(ST_GeomFromGML('1 2')); + +-- ERROR: not a defined SRID +SELECT 'srs_10', ST_AsEWKT(ST_GeomFromGML('1 2')); + +-- ERROR: SRID is not an int +SELECT 'srs_11', ST_AsEWKT(ST_GeomFromGML('1 2')); + +-- ERROR: SRID is not only int +SELECT 'srs_12', ST_AsEWKT(ST_GeomFromGML('1 2')); +SELECT 'srs_13', ST_AsEWKT(ST_GeomFromGML('1 2')); + +-- ERROR: srsName empty +SELECT 'srs_14', ST_AsEWKT(ST_GeomFromGML('1 2')); +SELECT 'srs_15', ST_AsEWKT(ST_GeomFromGML('1 2')); + +-- ERROR: srsName is defined as -1 +SELECT 'srs_16', ST_AsEWKT(ST_GeomFromGML('1 2')); + + + +-- +-- TODO GML Namespace +-- + +-- +-- TODO xlink/Reference +-- + + +-- +-- Coordinates (simple) +-- + +-- X,Y +SELECT 'coordinates_1', ST_AsEWKT(ST_GeomFromGML('1,2')); + +-- ERROR: single X +SELECT 'coordinates_2', ST_AsEWKT(ST_GeomFromGML('1')); + +-- X,Y,Z +SELECT 'coordinates_3', ST_AsEWKT(ST_GeomFromGML('1,2,3')); + +-- ERROR: 4 dimension +SELECT 'coordinates_4', ST_AsEWKT(ST_GeomFromGML('1,2,3,4')); + +-- ERROR: Only commas +SELECT 'coordinates_5', ST_AsEWKT(ST_GeomFromGML(',')); +SELECT 'coordinates_6', ST_AsEWKT(ST_GeomFromGML(' , ')); + +-- ERROR: empty or spaces +SELECT 'coordinates_7', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'coordinates_8', ST_AsEWKT(ST_GeomFromGML(' ')); + +-- ERROR: End on comma +SELECT 'coordinates_9', ST_AsEWKT(ST_GeomFromGML('1,2,3,')); +SELECT 'coordinates_10', ST_AsEWKT(ST_GeomFromGML('1,2,')); + +-- ERROR: Begin on comma +SELECT 'coordinates_11', ST_AsEWKT(ST_GeomFromGML(',1 2,3')); + +-- Whitespaces before and after +SELECT 'coordinates_12', ST_AsEWKT(ST_GeomFromGML(' 1,2 3,4 ')); +SELECT 'coordinates_13', ST_AsEWKT(ST_GeomFromGML(' + 1,2 3,4 + ')); + +-- Mixed dimension +SELECT 'coordinates_14', ST_AsEWKT(ST_GeomFromGML('1,2,3 4,5')); + +-- ERROR: Spaces insides +SELECT 'coordinates_15', ST_AsEWKT(ST_GeomFromGML('1, 2 3, 4')); +SELECT 'coordinates_16', ST_AsEWKT(ST_GeomFromGML('1,2 3,4')); + +-- ERROR: Junk +SELECT 'coordinates_17', ST_AsEWKT(ST_GeomFromGML('!@#$%^*()"')); + + + + +-- +-- Coordinates (cs,ts,decimal) +-- + +-- Specify default CS separator +SELECT 'coordinates_cs_1', ST_AsEWKT(ST_GeomFromGML('1,2')); + +-- ERROR: wrong CS separator +SELECT 'coordinates_cs_2', ST_AsEWKT(ST_GeomFromGML('1,2')); + +-- Specify a CS separator +SELECT 'coordinates_cs_3', ST_AsEWKT(ST_GeomFromGML('1;2')); + +-- ERROR: CS separator is a number +SELECT 'coordinates_cs_4', ST_AsEWKT(ST_GeomFromGML('102')); + +-- ERROR: CS separator is multichar +SELECT 'coordinates_cs_5', ST_AsEWKT(ST_GeomFromGML('1||2')); + +-- Specify default TS separator +SELECT 'coordinates_cs_6', ST_AsEWKT(ST_GeomFromGML('1,2 3,4')); + +-- ERROR: wrong TS separator +SELECT 'coordinates_cs_7', ST_AsEWKT(ST_GeomFromGML('1,2;3,4')); + +-- Specify a TS separator +SELECT 'coordinates_cs_8', ST_AsEWKT(ST_GeomFromGML('1,2;3,4')); + +-- ERROR: TS separator is a number +SELECT 'coordinates_cs_9', ST_AsEWKT(ST_GeomFromGML('1,203,4')); + +-- ERROR: TS separator is multichar +SELECT 'coordinates_cs_10', ST_AsEWKT(ST_GeomFromGML('1,2||3,4')); + +-- Specify default Decimal separator +SELECT 'coordinates_cs_11', ST_AsEWKT(ST_GeomFromGML('1.1,2.2 3.3,4.4')); + +-- ERROR: wrong Decimal separator +SELECT 'coordinates_cs_12', ST_AsEWKT(ST_GeomFromGML('1;1,2;2 3;3,4;4')); + +-- ERROR: Decimal separator is a number +SELECT 'coordinates_cs_13', ST_AsEWKT(ST_GeomFromGML('101,202 303,404')); + +-- ERROR: Decimal separator is multichar +SELECT 'coordinates_cs_14', ST_AsEWKT(ST_GeomFromGML('1||1,2||2 3||3,4||4')); + +-- CS and TS and Decimal together +SELECT 'coordinates_cs_15', ST_AsEWKT(ST_GeomFromGML('1,1.2,2;3,3.4,4')); + +-- ERROR: CS and Decimal are the same +SELECT 'coordinates_cs_16', ST_AsEWKT(ST_GeomFromGML('1 2 3 4')); +SELECT 'coordinates_cs_17', ST_AsEWKT(ST_GeomFromGML('1.1.2.2;3.3.4,4')); +SELECT 'coordinates_cs_18', ST_AsEWKT(ST_GeomFromGML('1;1.2;2;3;3.4,4')); + + +-- XML Entity substitution +SELECT 'coordinates_cs_19', ST_AsEWKT(ST_GeomFromGML('1 2,3 4')); + + + + +-- +-- pos +-- + +-- X,Y +SELECT 'pos_1', ST_AsEWKT(ST_GeomFromGML('1 2')); + +-- ERROR: single X +SELECT 'pos_2', ST_AsEWKT(ST_GeomFromGML('1')); + +-- ERROR: X,Y,Z but without explicit dimension +SELECT 'pos_3', ST_AsEWKT(ST_GeomFromGML('1 2 3')); + +-- ERROR: 4 dimension +SELECT 'pos_4', ST_AsEWKT(ST_GeomFromGML('1 2 3 4')); + +-- ERROR: empty or spaces +SELECT 'pos_5', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'pos_6', ST_AsEWKT(ST_GeomFromGML(' ')); +SELECT 'pos_7', ST_AsEWKT(ST_GeomFromGML(' ')); + +-- Whitespaces before and after +SELECT 'pos_8', ST_AsEWKT(ST_GeomFromGML(' 1 2 ')); +SELECT 'pos_9', ST_AsEWKT(ST_GeomFromGML(' 1 2 ')); +SELECT 'pos_10', ST_AsEWKT(ST_GeomFromGML(' + 1 2 + ')); +-- ERROR: Several Spaces insides +SELECT 'pos_11', ST_AsEWKT(ST_GeomFromGML('1 2')); + +-- ERROR: Junk +SELECT 'pos_12', ST_AsEWKT(ST_GeomFromGML('@!#$#%')); + +-- ERROR: 1 dimension +SELECT 'pos_13', ST_AsEWKT(ST_GeomFromGML('1')); + +-- 2 Dimensions explicit +SELECT 'pos_14', ST_AsEWKT(ST_GeomFromGML('1 2')); + +-- ERROR: 2 Dimensions explicit but 3 dims +SELECT 'pos_15', ST_AsEWKT(ST_GeomFromGML('1 2 3')); + +-- 3 Dimensions explicit +SELECT 'pos_16', ST_AsEWKT(ST_GeomFromGML('1 2 3')); + +-- ERROR: 4 dimensions +SELECT 'pos_17', ST_AsEWKT(ST_GeomFromGML('1 2 3 4')); + + +-- +-- posList +-- +-- 2 coords +SELECT 'poslist_1', ST_AsEWKT(ST_GeomFromGML('1 2 3 4')); + +-- spaces before and after +SELECT 'poslist_2', ST_AsEWKT(ST_GeomFromGML(' 1 2 3 4 ')); +SELECT 'poslist_3', ST_AsEWKT(ST_GeomFromGML(' 1 2 3 4 ')); +SELECT 'poslist_4', ST_AsEWKT(ST_GeomFromGML(' + 1 2 3 4 + ')); + +-- explicit 2 dimension +SELECT 'poslist_5', ST_AsEWKT(ST_GeomFromGML('1 2 3 4')); +-- ERROR: wrong dimension +SELECT 'poslist_6', ST_AsEWKT(ST_GeomFromGML(' 1 2 3 4 5 ')); +SELECT 'poslist_7', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5')); + +-- 2 coord 3D +SELECT 'poslist_8', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5 6')); + +-- ERROR: 1 dimension +SELECT 'poslist_9', ST_AsEWKT(ST_GeomFromGML('1')); +SELECT 'poslist_10', ST_AsEWKT(ST_GeomFromGML('1')); + +-- ERROR: 4 dimensions +SELECT 'poslist_11', ST_AsEWKT(ST_GeomFromGML('1 2 3 4 5 6 7 8')); + +-- ERROR: 3D but no explicit dimension +SELECT 'poslist_12', ST_AsEWKT(ST_GeomFromGML('1 2 3')); + +-- ERROR: empty or spaces +SELECT 'poslist_13', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'poslist_14', ST_AsEWKT(ST_GeomFromGML(' ')); +SELECT 'poslist_15', ST_AsEWKT(ST_GeomFromGML(' ')); + +-- ERROR: spaces insides posList +SELECT 'poslist_16', ST_AsEWKT(ST_GeomFromGML('1 2 3 4')); +SELECT 'poslist_17', ST_AsEWKT(ST_GeomFromGML(' 1 2 3 4 ')); + +-- ERROR: Junk +SELECT 'poslist_18', ST_AsEWKT(ST_GeomFromGML('!@#$%^*()"')); + + + + + +-- +-- coord +-- + +-- X,Y +SELECT 'coord_1', ST_AsEWKT(ST_GeomFromGML('12')); + +-- X,Y,Z +SELECT 'coord_2', ST_AsEWKT(ST_GeomFromGML('123')); + +-- ERROR no X or Y +SELECT 'coord_3', ST_AsEWKT(ST_GeomFromGML('12')); +SELECT 'coord_4', ST_AsEWKT(ST_GeomFromGML('12')); +SELECT 'coord_5', ST_AsEWKT(ST_GeomFromGML('1')); + +-- ERROR empty coord even if defined +SELECT 'coord_6', ST_AsEWKT(ST_GeomFromGML('')); +SELECT 'coord_7', ST_AsEWKT(ST_GeomFromGML('')); + +-- ERROR space in coord +SELECT 'coord_8', ST_AsEWKT(ST_GeomFromGML('1 ')); +SELECT 'coord_9', ST_AsEWKT(ST_GeomFromGML('1 ')); + +-- Spaces before and after coord +SELECT 'coord_10', ST_AsEWKT(ST_GeomFromGML('1 2 ')); +SELECT 'coord_11', ST_AsEWKT(ST_GeomFromGML('1 2 ')); +SELECT 'coord_12', ST_AsEWKT(ST_GeomFromGML('1 + 2 + ')); + +-- Several coords +SELECT 'coord_13', ST_AsEWKT(ST_GeomFromGML('1234')); + +-- Several coords mixed dimension +SELECT 'coord_14', ST_AsEWKT(ST_GeomFromGML('12345')); +SELECT 'coord_15', ST_AsEWKT(ST_GeomFromGML('12345')); + +-- XML not elements handle +SELECT 'coord_16', ST_AsEWKT(ST_GeomFromGML(' 1 2 3 4')); + + +-- +-- Double +-- + +-- Several digits +SELECT 'double_1', ST_AsEWKT(ST_GeomFromGML('1 1234567890')); + +-- Sign +/- +SELECT 'double_2', ST_AsEWKT(ST_GeomFromGML('1 -1')); +SELECT 'double_3', ST_AsEWKT(ST_GeomFromGML('1 +1')); + +-- ERROR: double sign +SELECT 'double_4', ST_AsEWKT(ST_GeomFromGML('1 --1')); + +-- ERROR: sign inside digit +SELECT 'double_5', ST_AsEWKT(ST_GeomFromGML('1 1-1')); + +-- Decimal part +SELECT 'double_6', ST_AsEWKT(ST_GeomFromGML('1 1.2')); +SELECT 'double_7', ST_AsEWKT(ST_GeomFromGML('1 1.23')); + +-- ERROR: no digit after dot +SELECT 'double_8', ST_AsEWKT(ST_GeomFromGML('1 1.')); + +-- ERROR: several dots +SELECT 'double_9', ST_AsEWKT(ST_GeomFromGML('1 1.2.3')); + +-- ERROR: no digit before dot +SELECT 'double_10', ST_AsEWKT(ST_GeomFromGML('1 .1')); +SELECT 'double_11', ST_AsEWKT(ST_GeomFromGML('1 -.1')); + +-- ERROR: not a digit +SELECT 'double_12', ST_AsEWKT(ST_GeomFromGML('1 a')); +SELECT 'double_13', ST_AsEWKT(ST_GeomFromGML('1 1a')); +SELECT 'double_14', ST_AsEWKT(ST_GeomFromGML('1 1a2')); + +-- Exp +SELECT 'double_15', ST_AsEWKT(ST_GeomFromGML('1 1e2')); +SELECT 'double_16', ST_AsEWKT(ST_GeomFromGML('1 1E+2')); +SELECT 'double_17', ST_AsEWKT(ST_GeomFromGML('1 1e-2')); +SELECT 'double_18', ST_AsEWKT(ST_GeomFromGML('1 1E-2')); + +-- Exp with decimal parts +SELECT 'double_19', ST_AsEWKT(ST_GeomFromGML('1 1.23E2')); +SELECT 'double_20', ST_AsEWKT(ST_GeomFromGML('1 1.23e2')); +SELECT 'double_21', ST_AsEWKT(ST_GeomFromGML('1 -1.23E2')); + +-- ERROR: no exp digit +SELECT 'double_22', ST_AsEWKT(ST_GeomFromGML('1 1E')); +SELECT 'double_23', ST_AsEWKT(ST_GeomFromGML('1 1e')); + +-- ERROR: dot inside exp digits +SELECT 'double_24', ST_AsEWKT(ST_GeomFromGML('1 1e2.3')); +SELECT 'double_25', ST_AsEWKT(ST_GeomFromGML('1 1E2.3')); + +-- ERROR: spaces inside +SELECT 'double_26', ST_AsEWKT(ST_GeomFromGML('1 - 1.23')); +SELECT 'double_27', ST_AsEWKT(ST_GeomFromGML('1 -1 .23')); +SELECT 'double_28', ST_AsEWKT(ST_GeomFromGML('1 -1. 23')); +SELECT 'double_29', ST_AsEWKT(ST_GeomFromGML('1 -1.23 E2')); +SELECT 'double_30', ST_AsEWKT(ST_GeomFromGML('1 -1.23E 2')); + +-- ERROR: Junk +SELECT 'double_31', ST_AsEWKT(ST_GeomFromGML('1 $0%@#$^%#')); + + + + + +-- +-- Delete inserted spatial data +-- +DELETE FROM spatial_ref_sys WHERE srid = 4326; diff --git a/regress/in_gml_expected b/regress/in_gml_expected new file mode 100644 index 000000000..f3b0f0fc9 --- /dev/null +++ b/regress/in_gml_expected @@ -0,0 +1,252 @@ +empty_geom| +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +point_1|POINT(1 2) +ERROR: invalid GML representation +ERROR: invalid GML representation +point_4|SRID=4326;POINT(1 2) +linestring_1|LINESTRING(1 2,3 4) +ERROR: invalid GML representation +linestring_3|SRID=4326;LINESTRING(1 2,3 4) +ERROR: invalid GML representation +ERROR: invalid GML representation +linestring_6|LINESTRING(1 2,3 4) +curve_1|LINESTRING(1 2,3 4) +ERROR: invalid GML representation +curve_3|SRID=4326;LINESTRING(1 2,3 4) +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +curve_8|LINESTRING(1 2,3 4) +ERROR: invalid GML representation +curve_10|LINESTRING(1 2,3 4) +curve_11|LINESTRING(1 2,3 4,5 6) +curve_12|LINESTRING(1 2 3,4 5 6,7 8 9) +ERROR: invalid GML representation +ERROR: invalid GML representation +curve_15|LINESTRING(1 2,4 5,7 8) +curve_16|LINESTRING(1 2,3 4,6 7) +polygon_1|POLYGON((1 2,3 4,5 6,1 2)) +polygon_2|SRID=4326;POLYGON((1 2,3 4,5 6,1 2)) +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +polygon_9|POLYGON((1 2,3 4,5 6,1 2),(7 8,9 10,11 12,7 8)) +polygon_10|POLYGON((1 2,3 4,5 6,1 2),(7 8,9 10,11 12,7 8)) +polygon_11|POLYGON((1 2,3 4,5 6,1 2)) +ERROR: invalid GML representation +ERROR: invalid GML representation +polygon_14|POLYGON((1 2,3 4,5 6,1 2),(7 8,9 10,11 12,7 8),(13 14,15 16,17 18,13 14)) +polygon_15|POLYGON((1 2,3 4,5 6,1 2),(7 8,9 10,11 12,7 8)) +polygon_16|POLYGON((1 2,4 5,7 8,1 2),(10 11,12 13,14 15,10 11)) +polygon_17|POLYGON((1 2,3 4,5 6,1 2),(7 8,10 11,13 14,7 8)) +surface_1|POLYGON((1 2,3 4,5 6,1 2)) +surface_2|SRID=4326;POLYGON((1 2,3 4,5 6,1 2)) +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +surface_10|POLYGON((1 2,3 4,5 6,1 2),(7 8,9 10,11 12,7 8)) +surface_11|POLYGON((1 2,3 4,5 6,1 2),(7 8,9 10,11 12,7 8)) +surface_12|POLYGON((1 2,3 4,5 6,1 2)) +ERROR: invalid GML representation +ERROR: invalid GML representation +surface_15|POLYGON((1 2,3 4,5 6,1 2),(7 8,9 10,11 12,7 8),(13 14,15 16,17 18,13 14)) +surface_16|POLYGON((1 2,4 5,7 8,1 2),(10 11,12 13,14 15,10 11)) +surface_17|POLYGON((1 2,3 4,5 6,1 2),(7 8,10 11,13 14,7 8)) +ERROR: invalid GML representation +surface_19|POLYGON((1 2,3 4,5 6,1 2)) +ERROR: invalid GML representation +mpoint_1|MULTIPOINT(1 2) +mpoint_2|MULTIPOINT(1 2,3 4) +mpoint_3|SRID=4326;MULTIPOINT(1 2) +mpoint_4|MULTIPOINT EMPTY +mpoint_5|MULTIPOINT EMPTY +mpoint_6|MULTIPOINT(1 2,3 4) +mline_1|MULTILINESTRING((1 2,3 4)) +mline_2|MULTILINESTRING((1 2,3 4),(5 6,7 8)) +mline_3|SRID=4326;MULTILINESTRING((1 2,3 4)) +mline_4|MULTILINESTRING EMPTY +mline_5|MULTILINESTRING EMPTY +mline_6|MULTILINESTRING((1 2,3 4),(5 6,7 8)) +mline_7|MULTILINESTRING((1 2,4 5),(7 8,9 10)) +mline_8|MULTILINESTRING((1 2,3 4),(5 6,8 9)) +mcurve_1|MULTILINESTRING((1 2,3 4)) +mcurve_2|MULTILINESTRING((1 2,3 4),(5 6,7 8)) +mcurve_3|SRID=4326;MULTILINESTRING((1 2,3 4)) +mcurve_4|MULTILINESTRING EMPTY +mcurve_5|MULTILINESTRING EMPTY +mcurve_6|MULTILINESTRING((1 2,3 4),(5 6,7 8)) +mcurve_7|MULTILINESTRING((1 2,4 5),(7 8,9 10)) +mcurve_8|MULTILINESTRING((1 2,3 4),(5 6,8 9)) +mpoly_1|MULTIPOLYGON(((1 2,3 4,5 6,1 2))) +mpoly_2|MULTIPOLYGON(((1 2,3 4,5 6,1 2)),((7 8,9 10,11 12,7 8))) +mpoly_3|SRID=4326;MULTIPOLYGON(((1 2,3 4,5 6,1 2))) +mpoly_4|MULTIPOLYGON EMPTY +mpoly_5|MULTIPOLYGON EMPTY +mpoly_6|MULTIPOLYGON(((1 2,3 4,5 6,1 2)),((7 8,9 10,11 12,7 8))) +mpoly_7|MULTIPOLYGON(((1 2,4 5,7 8,1 2)),((10 11,12 13,14 15,10 11))) +mpoly_8|MULTIPOLYGON(((1 2,3 4,5 6,1 2)),((7 8,10 11,13 14,7 8))) +msurface_1|MULTIPOLYGON(((1 2,3 4,5 6,1 2))) +msurface_2|MULTIPOLYGON(((1 2,3 4,5 6,1 2)),((7 8,9 10,11 12,7 8))) +msurface_3|SRID=4326;MULTIPOLYGON(((1 2,3 4,5 6,1 2))) +msurface_4|MULTIPOLYGON EMPTY +msurface_5|MULTIPOLYGON EMPTY +msurface_6|MULTIPOLYGON(((1 2,3 4,5 6,1 2)),((7 8,9 10,11 12,7 8))) +msurface_7|MULTIPOLYGON(((1 2,4 5,7 8,1 2)),((10 11,12 13,14 15,10 11))) +msurface_8|MULTIPOLYGON(((1 2,3 4,5 6,1 2)),((7 8,10 11,13 14,7 8))) +collection_1|GEOMETRYCOLLECTION(POINT(1 2)) +collection_2|GEOMETRYCOLLECTION(POINT(1 2),LINESTRING(3 4,5 6)) +collection_3|GEOMETRYCOLLECTION(MULTIPOINT(1 2,3 4)) +collection_4|GEOMETRYCOLLECTION(MULTIPOINT(1 2,3 4),MULTILINESTRING((5 6,7 8),(9 10,11 12))) +collection_5|GEOMETRYCOLLECTION(MULTIPOINT(1 2,3 4),POINT(5 6),MULTILINESTRING((7 8,9 10),(11 12,13 14)),POLYGON((15 16,17 18,19 20,15 16))) +collection_6|GEOMETRYCOLLECTION EMPTY +collection_7|GEOMETRYCOLLECTION EMPTY +collection_8|GEOMETRYCOLLECTION(POINT(1 2),GEOMETRYCOLLECTION(POINT(3 4))) +collection_9|GEOMETRYCOLLECTION(POINT(1 2),GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(3 4)))) +collection_10|SRID=4326;GEOMETRYCOLLECTION(POINT(1 2)) +collection_11|GEOMETRYCOLLECTION(POINT(1 2),GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(3 4)))) +collection_12|GEOMETRYCOLLECTION(POINT(1 2),GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(4 5)))) +collection_13|GEOMETRYCOLLECTION(POINT(1 2),GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(3 4)))) +srs_1|SRID=4326;POINT(1 2) +srs_2|SRID=4326;POINT(1 2) +srs_3|SRID=4326;POINT(1 2) +srs_4|SRID=4326;POINT(1 2) +srs_5|SRID=4326;POINT(1 2) +srs_6|SRID=4326;POINT(1 2) +srs_7|SRID=4326;POINT(1 2) +srs_8|SRID=4326;POINT(1 2) +ERROR: unknown spatial reference system +ERROR: unknown spatial reference system +ERROR: unknown spatial reference system +ERROR: unknown spatial reference system +ERROR: unknown spatial reference system +ERROR: unknown spatial reference system +ERROR: unknown spatial reference system +ERROR: unknown spatial reference system +coordinates_1|POINT(1 2) +ERROR: invalid GML representation +coordinates_3|POINT(1 2 3) +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +coordinates_12|LINESTRING(1 2,3 4) +coordinates_13|LINESTRING(1 2,3 4) +coordinates_14|LINESTRING(1 2,4 5) +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +coordinates_cs_1|POINT(1 2) +ERROR: invalid GML representation +coordinates_cs_3|POINT(1 2) +ERROR: invalid GML representation +ERROR: invalid GML representation +coordinates_cs_6|LINESTRING(1 2,3 4) +ERROR: invalid GML representation +coordinates_cs_8|LINESTRING(1 2,3 4) +ERROR: invalid GML representation +ERROR: invalid GML representation +coordinates_cs_11|LINESTRING(1.1 2.2,3.3 4.4) +coordinates_cs_12|LINESTRING(1.1 2.2,3.3 4.4) +ERROR: invalid GML representation +ERROR: invalid GML representation +coordinates_cs_15|LINESTRING(1.1 2.2,3.3 4.4) +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +coordinates_cs_19|LINESTRING(1 2,3 4) +pos_1|POINT(1 2) +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +pos_8|POINT(1 2) +pos_9|POINT(1 2) +pos_10|POINT(1 2) +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +pos_14|POINT(1 2) +ERROR: invalid GML representation +pos_16|POINT(1 2 3) +ERROR: invalid GML representation +poslist_1|LINESTRING(1 2,3 4) +poslist_2|LINESTRING(1 2,3 4) +poslist_3|LINESTRING(1 2,3 4) +poslist_4|LINESTRING(1 2,3 4) +poslist_5|LINESTRING(1 2,3 4) +ERROR: invalid GML representation +ERROR: invalid GML representation +poslist_8|LINESTRING(1 2 3,4 5 6) +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +coord_1|POINT(1 2) +coord_2|POINT(1 2 3) +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +coord_10|POINT(1 2) +coord_11|POINT(1 2) +coord_12|POINT(1 2) +coord_13|LINESTRING(1 2,3 4) +coord_14|LINESTRING(1 2,4 5) +coord_15|LINESTRING(1 2,3 4) +coord_16|LINESTRING(1 2,3 4) +double_1|POINT(1 1234567890) +double_2|POINT(1 -1) +double_3|POINT(1 1) +ERROR: invalid GML representation +ERROR: invalid GML representation +double_6|POINT(1 1.2) +double_7|POINT(1 1.23) +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +double_15|POINT(1 100) +double_16|POINT(1 100) +double_17|POINT(1 0.01) +double_18|POINT(1 0.01) +double_19|POINT(1 123) +double_20|POINT(1 123) +double_21|POINT(1 -123) +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation +ERROR: invalid GML representation