]> granicus.if.org Git - postgis/commitdiff
Initial version of ST_GeomFromKML function and related units tests
authorOlivier Courtin <olivier.courtin@camptocamp.com>
Sun, 8 Nov 2009 19:05:50 +0000 (19:05 +0000)
committerOlivier Courtin <olivier.courtin@camptocamp.com>
Sun, 8 Nov 2009 19:05:50 +0000 (19:05 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@4769 b70326c6-7e19-0410-871a-916f4a2858ee

postgis/Makefile.in
postgis/lwgeom_in_kml.c [new file with mode: 0644]
postgis/postgis.sql.in.c
regress/Makefile.in
regress/in_kml.sql [new file with mode: 0644]
regress/in_kml_expected [new file with mode: 0644]

index fcd04435041c1bfad320f36736a8ced930b85789..f587d3ad043616592db51989e403244fd919b0e0 100644 (file)
@@ -42,8 +42,9 @@ PG_OBJS=lwgeom_pg.o \
        lwgeom_svg.o \
        lwgeom_gml.o \
        lwgeom_kml.o \
-       lwgeom_in_gml.o \
        lwgeom_geojson.o \
+       lwgeom_in_gml.o \
+       lwgeom_in_kml.o \
        lwgeom_triggers.o \
        lwgeom_dump.o \
        lwgeom_functions_lrs.o \
diff --git a/postgis/lwgeom_in_kml.c b/postgis/lwgeom_in_kml.c
new file mode 100644 (file)
index 0000000..70fc95a
--- /dev/null
@@ -0,0 +1,470 @@
+/**********************************************************************
+ * $Id:$
+ *
+ * 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 the GNU General Public Licence. See the COPYING file.
+ *
+ **********************************************************************/
+
+/**
+* @file KML input routines.
+* Ability to parse KML geometry fragment and to return an LWGEOM
+* or an error message.
+*
+* KML version supported: 2.2.0
+* Cf: <http://www.opengeospatial.org/standards/kml>
+*
+* Known limitations related to 3D:
+*  - Not support kml:Model geometries
+*  - Don't handle kml:extrude attribute
+*
+* Written by Olivier Courtin - Oslandia
+*
+**********************************************************************/
+
+
+#include "postgres.h"
+#include "lwgeom_pg.h"
+#include "liblwgeom.h"
+
+
+#if HAVE_LIBXML2
+#include <libxml/tree.h> 
+#include <libxml/parser.h> 
+
+
+/* 
+TODO:
+       - OGC:LonLat84_5773 explicit support (rather than EPSG:4326)
+       - Don't return a GEOMETRYCOLLECTION if a MULTI one is enough
+       - altitudeModeGroup relativeToGround Z Altitude
+         computation upon Geoid
+*/
+
+
+Datum geom_from_kml(PG_FUNCTION_ARGS);
+static LWGEOM* parse_kml(xmlNodePtr xnode, bool *hasz);
+
+#define KML_NS         ((char *) "http://www.opengis.net/kml/2.2")
+
+
+/**
+ * Ability to parse KML geometry fragment and to return an LWGEOM
+ * or an error message.
+ */
+PG_FUNCTION_INFO_V1(geom_from_kml);
+Datum geom_from_kml(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 KML 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 KML representation");
+       }
+
+       lwgeom = parse_kml(xmlroot, &hasz);
+       lwgeom->bbox = lwgeom_compute_box2d(lwgeom);
+       geom = pglwgeom_serialize(lwgeom);
+       lwgeom_release(lwgeom);
+
+       xmlFreeDoc(xmldoc);
+       xmlCleanupParser();
+
+       /* KML geometries could be either 2 or 3D
+        *
+        * So we deal with 3D in all structures 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);
+}
+                       
+
+/**
+ * Return false if current element namespace is not a KML one
+ * Return true otherwise.
+ */
+static bool is_kml_namespace(xmlNodePtr xnode, bool is_strict)
+{
+       xmlNsPtr *ns, *p;
+         
+       ns = xmlGetNsList(xnode->doc, xnode);
+       /*
+        * If no namespace is available we could return true anyway
+        * (because we work only on KML fragment, we don't want to 
+        *  'oblige' to add namespace on the geometry root node)
+        */
+       if (ns == NULL) return !is_strict;
+
+       for (p=ns ; *p ; p++) {
+               if ((*p)->href == NULL) continue;
+               if (!strcmp((char *) (*p)->href, KML_NS)) {
+                       if (    (*p)->prefix == NULL ||
+                               !xmlStrcmp(xnode->ns->prefix, (*p)->prefix)) {
+
+                               xmlFree(ns);
+                               return true;
+                       }
+               }
+       }
+
+       xmlFree(ns);
+       return false;
+}
+
+
+/**
+ * Retrieve a KML propertie from a node or NULL otherwise
+ * Respect namespaces if presents in the node element
+ */
+static xmlChar *kmlGetProp(xmlNodePtr xnode, xmlChar *prop)
+{
+       xmlChar *value;
+
+       if (!is_kml_namespace(xnode, true))
+               return xmlGetProp(xnode, prop);
+
+       value = xmlGetNsProp(xnode, prop, (xmlChar *) KML_NS);
+
+       /* In last case try without explicit namespace */
+       if (value == NULL) value = xmlGetNoNsProp(xnode, prop);
+
+       return value;
+}
+
+
+/**
+ * Parse a string supposed to be a double
+ */
+static double parse_kml_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 and/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 KML representation"); 
+               } else if (*p == '.') {
+                       if      (st == DIG)                             st = NEED_DIG_DEC;
+                       else    lwerror("invalid KML representation"); 
+               } else if (*p == '-' || *p == '+') {
+                       if      (st == INIT)                            st = NEED_DIG;
+                       else if (st == EXP)                             st = NEED_DIG_EXP;
+                       else    lwerror("invalid KML representation"); 
+               } else if (*p == 'e' || *p == 'E') {
+                       if      (st == DIG || st == DIG_DEC)            st = EXP;
+                       else    lwerror("invalid KML representation"); 
+               } else if (isspace(*p)) {
+                       if (!space_after) lwerror("invalid KML representation");  
+                       if (st == DIG || st == DIG_DEC || st == DIG_EXP)st = END;
+                       else if (st == NEED_DIG_DEC)                    st = END;
+                       else if (st == END);
+                       else    lwerror("invalid KML representation");
+               } else  lwerror("invalid KML representation");
+       }              
+
+       if (st != DIG && st != NEED_DIG_DEC && st != DIG_DEC && st != DIG_EXP && st != END)
+               lwerror("invalid KML representation");
+
+       return atof(d);
+}
+
+
+/**
+ * Parse kml:coordinates
+ */
+static POINTARRAY* parse_kml_coordinates(xmlNodePtr xnode, bool *hasz)
+{
+        xmlChar *kml_coord;
+        bool digit, found;
+        DYNPTARRAY *dpa;
+        POINTARRAY *pa;
+        int kml_dims;
+        char *p, *q;
+        POINT4D pt;
+        uchar dims=0;
+
+       if (xnode == NULL) lwerror("invalid KML representation");
+       
+       for (found = false ; xnode != NULL ; xnode = xnode->next) {
+               if (xnode->type != XML_ELEMENT_NODE) continue;
+               if (!is_kml_namespace(xnode, false)) continue;
+               if (strcmp((char *) xnode->name, "coordinates")) continue;
+
+               found = true;
+               break;
+       }
+       if (!found) lwerror("invalid KML representation");
+
+        /* We begin to retrieve coordinates string */
+        kml_coord = xmlNodeGetContent(xnode);
+        p = (char *) kml_coord;
+
+        /* KML coordinates pattern:     x1,y1 x2,y2 
+         *                              x1,y1,z1 x2,y2,z2
+        */
+
+        /* Now we create PointArray from coordinates values */
+        TYPE_SETZM(dims, 1, 0);
+        dpa = dynptarray_create(1, dims);
+
+        for (q = p, kml_dims=0, digit = false ; *p ; p++) {
+
+                if (isdigit(*p)) digit = true;  /* One state parser */
+
+                /* Coordinate Separator */
+                if (*p == ',') {
+                        *p = '\0';
+                        kml_dims++;
+
+                        if (*(p+1) == '\0') lwerror("invalid KML representation");
+
+                        if      (kml_dims == 1) pt.x = parse_kml_double(q, true, true);
+                        else if (kml_dims == 2) pt.y = parse_kml_double(q, true, true);
+                        q = p+1;
+
+                /* Tuple Separator (or end string) */
+                } else if (digit && (isspace(*p) || *(p+1) == '\0')) {
+                        if (isspace(*p)) *p = '\0';
+                        kml_dims++;
+
+                        if (kml_dims < 2 || kml_dims > 3)
+                                lwerror("invalid KML representation");
+
+                        if (kml_dims == 3)
+                                pt.z = parse_kml_double(q, true, true);
+                        else {
+                                pt.y = parse_kml_double(q, true, true);
+                                *hasz = false;
+                        }
+
+                        dynptarray_addPoint4d(dpa, &pt, 0);
+                        digit = false;
+                        q = p+1;
+                        kml_dims = 0;
+
+                }
+        }
+
+        xmlFree(kml_coord);
+        pa = ptarray_clone(dpa->pa);
+        lwfree(dpa);
+
+        return pa;
+}
+
+
+/**
+ * Parse KML point
+ */
+static LWGEOM* parse_kml_point(xmlNodePtr xnode, bool *hasz)
+{
+       POINTARRAY *pa;
+
+       if (xnode->children == NULL) lwerror("invalid KML representation");
+       pa = parse_kml_coordinates(xnode->children, hasz);
+       if (pa->npoints != 1) lwerror("invalid KML representation");
+
+       return (LWGEOM *) lwpoint_construct(4326, NULL, pa);
+}
+
+
+/**
+ * Parse KML lineString 
+ */
+static LWGEOM* parse_kml_line(xmlNodePtr xnode, bool *hasz)
+{
+       POINTARRAY *pa;
+
+       if (xnode->children == NULL) lwerror("invalid KML representation");
+       pa = parse_kml_coordinates(xnode->children, hasz);
+       if (pa->npoints < 2) lwerror("invalid KML representation");
+
+       return (LWGEOM *) lwline_construct(4326, NULL, pa);
+}
+
+
+/**
+ * Parse KML Polygon
+ */
+static LWGEOM* parse_kml_polygon(xmlNodePtr xnode, bool *hasz)
+{
+       int ring;
+       xmlNodePtr xa, xb;
+       POINTARRAY **ppa = NULL;
+
+       for (xa = xnode->children ; xa != NULL ; xa = xa->next) {
+
+               /* Polygon/outerBoundaryIs */
+               if (xa->type != XML_ELEMENT_NODE) continue;
+               if (!is_kml_namespace(xa, false)) continue;
+               if (strcmp((char *) xa->name, "outerBoundaryIs")) continue;
+              
+               for (xb = xa->children ; xb != NULL ; xb = xb->next) {
+
+                       if (xb->type != XML_ELEMENT_NODE) continue;
+                       if (!is_kml_namespace(xb, false)) continue;
+                       if (strcmp((char *) xb->name, "LinearRing")) continue;
+
+                       ppa = (POINTARRAY**) lwalloc(sizeof(POINTARRAY*));
+                       ppa[0] = parse_kml_coordinates(xb->children, hasz);
+
+                       if (ppa[0]->npoints < 4
+                               || (!*hasz && !ptarray_isclosed2d(ppa[0]))
+                               ||  (*hasz && !ptarray_isclosed3d(ppa[0])))
+                               lwerror("invalid KML representation");
+               }
+       }
+
+       for (ring=1, xa = xnode->children ; xa != NULL ; xa = xa->next) {
+
+               /* Polygon/innerBoundaryIs */
+               if (xa->type != XML_ELEMENT_NODE) continue;
+               if (!is_kml_namespace(xa, false)) continue;
+               if (strcmp((char *) xa->name, "innerBoundaryIs")) continue;
+               
+               for (xb = xa->children ; xb != NULL ; xb = xb->next) {
+
+                       if (xb->type != XML_ELEMENT_NODE) continue;
+                       if (!is_kml_namespace(xb, false)) continue;
+                       if (strcmp((char *) xb->name, "LinearRing")) continue;
+
+                       ppa = (POINTARRAY**) lwrealloc((POINTARRAY *) ppa,
+                               sizeof(POINTARRAY*) * (ring + 1));
+                       ppa[ring] = parse_kml_coordinates(xb->children, hasz);
+
+                       if (ppa[ring]->npoints < 4
+                               || (!*hasz && !ptarray_isclosed2d(ppa[ring]))
+                               ||  (*hasz && !ptarray_isclosed3d(ppa[ring])))
+                               lwerror("invalid KML representation");
+
+                       ring++;
+               }
+       }
+                       
+       /* Exterior Ring is mandatory */
+       if (ppa == NULL || ppa[0] == NULL) lwerror("invalid KML representation");
+
+       return (LWGEOM *) lwpoly_construct(4326, NULL, ring, ppa);
+}
+
+
+/**
+ * Parse KML MultiGeometry
+ */
+static LWGEOM* parse_kml_multi(xmlNodePtr xnode, bool *hasz) 
+{
+       LWGEOM *geom;
+       xmlNodePtr xa;
+
+       geom = (LWGEOM *)lwcollection_construct_empty(4326, 1, 0);
+
+       for (xa = xnode->children ; xa != NULL ; xa = xa->next) {
+
+               if (xa->type != XML_ELEMENT_NODE) continue;
+               if (!is_kml_namespace(xa, false)) continue;
+
+               if (       !strcmp((char *) xa->name, "Point")
+                       || !strcmp((char *) xa->name, "LineString")
+                       || !strcmp((char *) xa->name, "Polygon")
+                       || !strcmp((char *) xa->name, "MultiGeometry")) {
+
+                       if (xa->children == NULL) break;
+                       geom = lwcollection_add((LWCOLLECTION *)geom, -1,
+                                parse_kml(xa, hasz));
+               }
+       }
+
+       return geom;
+}
+
+
+/**
+ * Parse KML 
+ */
+static LWGEOM* parse_kml(xmlNodePtr xnode, bool *hasz) 
+{
+       xmlNodePtr xa = xnode;
+
+       while (xa != NULL && (xa->type != XML_ELEMENT_NODE
+                       || !is_kml_namespace(xa, false))) xa = xa->next;
+
+       if (xa == NULL) lwerror("invalid KML representation");
+
+       if (!strcmp((char *) xa->name, "Point"))
+               return parse_kml_point(xa, hasz);
+
+       if (!strcmp((char *) xa->name, "LineString"))
+               return parse_kml_line(xa, hasz);
+
+       if (!strcmp((char *) xa->name, "Polygon"))
+               return parse_kml_polygon(xa, hasz);
+
+       if (!strcmp((char *) xa->name, "MultiGeometry"))
+               return parse_kml_multi(xa, hasz);
+       
+       lwerror("invalid KML representation");
+       return NULL; /* Never reach */
+}
+
+#endif /* if HAVE_LIBXML2 */
index 4af44663c3dc202da0b1b3fa7caea8ad8cdf97c1..16108a083052d665920bab6499eb3b1f6943a27c 100644 (file)
@@ -4233,7 +4233,7 @@ CREATE OR REPLACE FUNCTION ST_Equals(geometry,geometry)
 
 #if HAVE_LIBXML2
 -----------------------------------------------------------------------
--- GML INPUT
+-- GML & KML INPUT
 -- Availability: 1.5.0
 -----------------------------------------------------------------------
 CREATE OR REPLACE FUNCTION ST_GeomFromGML(text)
@@ -4246,6 +4246,11 @@ CREATE OR REPLACE FUNCTION ST_GMLToSQL(text)
        AS 'MODULE_PATHNAME','geom_from_gml'
        LANGUAGE 'C' IMMUTABLE STRICT;
 
+CREATE OR REPLACE FUNCTION ST_GeomFromKML(text)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME','geom_from_kml'
+       LANGUAGE 'C' IMMUTABLE STRICT;
+
 #endif
 -----------------------------------------------------------------------
 -- SVG OUTPUT
index 1ac78a3b4514b334b3cf79fbe3d3aa1c0a6ff341..6f20291fec5446354cec743a4cc9782a8874b6bc 100644 (file)
@@ -82,9 +82,10 @@ ifeq ($(shell expr $(POSTGIS_GEOS_VERSION) ">=" 32),1)
        TESTS += hausdorff
 endif
 
-# GeomFromGML need libxml2
+# Some import functions need libxml2
 ifeq ($(shell expr $(HAVE_LIBXML2) "=" 1),1)
        TESTS += in_gml
+       TESTS += in_kml
 endif
 
 
diff --git a/regress/in_kml.sql b/regress/in_kml.sql
new file mode 100644 (file)
index 0000000..6c3803c
--- /dev/null
@@ -0,0 +1,363 @@
+--
+-- GeomFromKML regression test
+-- Written by Olivier Courtin - Oslandia
+--
+
+
+--
+-- spatial_ref_sys datas
+--
+
+-- EPSG 4326 : WGS 84
+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_GeomFromKML(NULL));
+
+--
+-- XML
+--
+
+-- ERROR: Empty String
+SELECT 'xml_1', ST_AsEWKT(ST_GeomFromKML(''));
+
+-- ERROR: Not well formed XML
+SELECT 'xml_2', ST_AsEWKT(ST_GeomFromKML('<foo>'));
+
+-- ERROR: Not a KML Geometry
+SELECT 'xml_3', ST_AsEWKT(ST_GeomFromKML('<foo/>'));
+
+
+
+--
+-- Point
+--
+
+-- 1 Point
+SELECT 'point_1', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,2</kml:coordinates></kml:Point>'));
+
+-- ERROR: 2 points
+SELECT 'point_2', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,2 3,4</kml:coordinates></kml:Point>'));
+
+-- ERROR: empty point
+SELECT 'point_3', ST_AsEWKT(ST_GeomFromKML('<kml:Point></kml:Point>'));
+
+
+
+--
+-- LineString
+--
+
+-- 2 Points
+SELECT 'linestring_1', ST_AsEWKT(ST_GeomFromKML('<kml:LineString><kml:coordinates>1,2 3,4</kml:coordinates></kml:LineString>'));
+
+-- ERROR 1 Point
+SELECT 'linestring_2', ST_AsEWKT(ST_GeomFromKML('<kml:LineString><kml:coordinates>1,2</kml:coordinates></kml:LineString>'));
+
+-- ERROR: empty coordinates 
+SELECT 'linestring_3', ST_AsEWKT(ST_GeomFromKML('<kml:LineString><kml:coordinates></kml:coordinates></kml:LineString>'));
+SELECT 'linestring_4', ST_AsEWKT(ST_GeomFromKML('<kml:LineString></kml:LineString>'));
+
+-- XML not elements handle
+SELECT 'linestring_5', ST_AsEWKT(ST_GeomFromKML(' <!-- --> <kml:LineString> <!-- --> <kml:coordinates>1,2 3,4</kml:coordinates></kml:LineString>'));
+
+
+
+
+--
+-- Polygon
+--
+
+-- 1 ring
+SELECT 'polygon_1', ST_AsEWKT(ST_GeomFromKML('<kml:Polygon><kml:outerBoundaryIs><kml:LinearRing><kml:coordinates>1,2 3,4 5,6 1,2</kml:coordinates></kml:LinearRing></kml:outerBoundaryIs></kml:Polygon>'));
+
+-- ERROR: In exterior ring: Last point is not the same as the first one 
+SELECT 'polygon_2', ST_AsEWKT(ST_GeomFromKML('<kml:Polygon><kml:outerBoundaryIs><kml:LinearRing><kml:coordinates>1,2 3,4 5,6 1,3</kml:coordinates></kml:LinearRing></kml:outerBoundaryIs></kml:Polygon>'));
+
+-- ERROR: In exterior 3D ring: Last point is not the same as the first one in Z
+SELECT 'polygon_3', ST_AsEWKT(ST_GeomFromKML('<kml:Polygon><kml:outerBoundaryIs><kml:LinearRing><kml:coordinates>1,2,3 4,5,6 7,8,9 1,2,0</kml:coordinates></kml:LinearRing></kml:outerBoundaryIs></kml:Polygon>'));
+
+-- ERROR: Only 3 points in exterior ring
+SELECT 'polygon_4', ST_AsEWKT(ST_GeomFromKML('<kml:Polygon><kml:outerBoundaryIs><kml:LinearRing><kml:coordinates>1,2 3,4 1,2</kml:coordinates></kml:LinearRing></kml:outerBoundaryIs></kml:Polygon>'));
+
+-- ERROR: Empty exterior ring coordinates 
+SELECT 'polygon_5', ST_AsEWKT(ST_GeomFromKML('<kml:Polygon><kml:outerBoundaryIs><kml:LinearRing><kml:coordinates></kml:coordinates></kml:LinearRing></kml:outerBoundaryIs></kml:Polygon>'));
+SELECT 'polygon_6', ST_AsEWKT(ST_GeomFromKML('<kml:Polygon><kml:outerBoundaryIs><kml:LinearRing></kml:LinearRing></kml:outerBoundaryIs></kml:Polygon>'));
+SELECT 'polygon_7', ST_AsEWKT(ST_GeomFromKML('<kml:Polygon><kml:outerBoundaryIs></kml:outerBoundaryIs></kml:Polygon>'));
+SELECT 'polygon_8', ST_AsEWKT(ST_GeomFromKML('<kml:Polygon></kml:Polygon>'));
+
+-- 2 rings
+SELECT 'polygon_9', ST_AsEWKT(ST_GeomFromKML('<kml:Polygon><kml:outerBoundaryIs><kml:LinearRing><kml:coordinates>1,2 3,4 5,6 1,2</kml:coordinates></kml:LinearRing></kml:outerBoundaryIs><kml:innerBoundaryIs><kml:LinearRing><kml:coordinates>7,8 9,10 11,12 7,8</kml:coordinates></kml:LinearRing></kml:innerBoundaryIs></kml:Polygon>'));
+
+-- XML not elements handle
+SELECT 'polygon_10', ST_AsEWKT(ST_GeomFromKML(' <!-- --> <kml:Polygon> <!-- --> <kml:outerBoundaryIs> <!-- --> <kml:LinearRing> <!-- --> <kml:coordinates>1,2 3,4 5,6 1,2</kml:coordinates></kml:LinearRing></kml:outerBoundaryIs> <!-- --> <kml:innerBoundaryIs> <!-- --> <kml:LinearRing><kml:coordinates>7,8 9,10 11,12 7,8</kml:coordinates></kml:LinearRing></kml:innerBoundaryIs></kml:Polygon>'));
+
+-- Empty interior ring coordinates  (even if defined)
+SELECT 'polygon_11', ST_AsEWKT(ST_GeomFromKML('<kml:Polygon><kml:outerBoundaryIs><kml:LinearRing><kml:coordinates>1,2 3,4 5,6 1,2</kml:coordinates></kml:LinearRing></kml:outerBoundaryIs><kml:innerBoundaryIs></kml:innerBoundaryIs></kml:Polygon>'));
+
+-- ERROR: Only 3 points in interior ring
+SELECT 'polygon_12', ST_AsEWKT(ST_GeomFromKML('<kml:Polygon><kml:outerBoundaryIs><kml:LinearRing><kml:coordinates>1,2 3,4 5,6 1,2</kml:coordinates></kml:LinearRing></kml:outerBoundaryIs><kml:innerBoundaryIs><kml:LinearRing><kml:coordinates>7,8 9,10 7,8</kml:coordinates></kml:LinearRing></kml:innerBoundaryIs></kml:Polygon>'));
+
+-- ERROR: In interior ring: Last point is not the same as the first one 
+SELECT 'polygon_13', ST_AsEWKT(ST_GeomFromKML('<kml:Polygon><kml:outerBoundaryIs><kml:LinearRing><kml:coordinates>1,2 3,4 5,6 1,2</kml:coordinates></kml:LinearRing></kml:outerBoundaryIs><kml:innerBoundaryIs><kml:LinearRing><kml:coordinates>7,8 9,10 11,12 7,9</kml:coordinates></kml:LinearRing></kml:innerBoundaryIs></kml:Polygon>'));
+
+-- ERROR: In interior 3D ring: Last point is not the same as the first one in Z
+SELECT 'polygon_14', ST_AsEWKT(ST_GeomFromKML('<kml:Polygon><kml:outerBoundaryIs><kml:LinearRing><kml:coordinates>1,2,3 4,5,6 7,8,9 1,2,3</kml:coordinates></kml:LinearRing></kml:outerBoundaryIs><kml:innerBoundaryIs><kml:LinearRing><kml:coordinates>10,11,12 13,14,15 16,17,18 10,11,0</kml:coordinates></kml:LinearRing></kml:innerBoundaryIs></kml:Polygon>'));
+
+-- 3 rings
+SELECT 'polygon_15', ST_AsEWKT(ST_GeomFromKML('<kml:Polygon><kml:outerBoundaryIs><kml:LinearRing><kml:coordinates>1,2 3,4 5,6 1,2</kml:coordinates></kml:LinearRing></kml:outerBoundaryIs><kml:innerBoundaryIs><kml:LinearRing><kml:coordinates>7,8 9,10 11,12 7,8</kml:coordinates></kml:LinearRing></kml:innerBoundaryIs><kml:innerBoundaryIs><kml:LinearRing><kml:coordinates>13,14 15,16 17,18 13,14</kml:coordinates></kml:LinearRing></kml:innerBoundaryIs></kml:Polygon>'));
+
+
+
+
+--
+-- MultiGeometry
+--
+
+-- 1 point 
+--SELECT 'multi_1', ST_AsEWKT(ST_GeomFromKML('<kml:MultiGeometry><kml:Point><kml:coordinates>1,2</kml:coordinates></kml:Point></kml:MultiGeometry>'));
+
+-- 2 points
+--SELECT 'multi_2', ST_AsEWKT(ST_GeomFromKML('<kml:MultiGeometry><kml:Point><kml:coordinates>1,2</kml:coordinates></kml:Point><kml:Point><kml:coordinates>1,2</kml:coordinates></kml:Point></kml:MultiGeometry>'));
+
+-- 1 line 
+--SELECT 'multi_3', ST_AsEWKT(ST_GeomFromKML('<kml:MultiGeometry><kml:LineString><kml:coordinates>1,2 3,4</kml:coordinates></kml:LineString></kml:MultiGeometry>'));
+
+-- 2 lines
+--SELECT 'multi_4', ST_AsEWKT(ST_GeomFromKML('<kml:MultiGeometry><kml:LineString><kml:coordinates>1,2 3,4</kml:coordinates></kml:LineString><kml:LineString><kml:coordinates>5,6 7,8</kml:coordinates></kml:LineString></kml:MultiGeometry>'));
+
+-- 1 polygon 
+--SELECT 'multi_5', ST_AsEWKT(ST_GeomFromKML('<kml:MultiGeometry><kml:Polygon><kml:outerBoundaryIs><kml:LinearRing><kml:coordinates>1,2 3,4 5,6 1,2</kml:coordinates></kml:LinearRing></kml:outerBoundaryIs></kml:Polygon></kml:MultiGeometry>'));
+
+-- 2 polygons
+--SELECT 'multi_6', ST_AsEWKT(ST_GeomFromKML('<kml:MultiGeometry><kml:Polygon><kml:outerBoundaryIs><kml:LinearRing><kml:coordinates>1,2 3,4 5,6 1,2</kml:coordinates></kml:LinearRing></kml:outerBoundaryIs></kml:Polygon><kml:Polygon><kml:outerBoundaryIs><kml:LinearRing><kml:coordinates>7,8 9,10 11,12 7,8</kml:coordinates></kml:LinearRing></kml:outerBoundaryIs></kml:Polygon></kml:MultiGeometry>'));
+
+-- Point, LineString and Polygon
+SELECT 'multi_7', ST_AsEWKT(ST_GeomFromKML('<kml:MultiGeometry><kml:Point><kml:coordinates>1,2</kml:coordinates></kml:Point><kml:LineString><kml:coordinates>3,4 5,6</kml:coordinates></kml:LineString><kml:Polygon><kml:outerBoundaryIs><kml:LinearRing><kml:coordinates>7,8 9,10 11,12 7,8</kml:coordinates></kml:LinearRing></kml:outerBoundaryIs></kml:Polygon></kml:MultiGeometry>'));
+
+-- Empty collection
+SELECT 'multi_8', ST_AsEWKT(ST_GeomFromKML('<kml:MultiGeometry></kml:MultiGeometry>'));
+
+-- Collection of collection
+SELECT 'multi_9', ST_AsEWKT(ST_GeomFromKML('<kml:MultiGeometry><kml:Point><kml:coordinates>1,2</kml:coordinates></kml:Point><kml:MultiGeometry><kml:LineString><kml:coordinates>3,4 5,6</kml:coordinates></kml:LineString><kml:Polygon><kml:outerBoundaryIs><kml:LinearRing><kml:coordinates>7,8 9,10 11,12 7,8</kml:coordinates></kml:LinearRing></kml:outerBoundaryIs></kml:Polygon></kml:MultiGeometry></kml:MultiGeometry>'));
+
+-- XML not elements handle
+SELECT 'multi_10', ST_AsEWKT(ST_GeomFromKML(' <!-- --> <kml:MultiGeometry> <!-- --> <kml:Point> <!-- --> <kml:coordinates>1,2</kml:coordinates></kml:Point> <!-- --> <kml:LineString><kml:coordinates>3,4 5,6</kml:coordinates></kml:LineString> <!-- --> <kml:Polygon><kml:outerBoundaryIs><kml:LinearRing><kml:coordinates>7,8 9,10 11,12 7,8</kml:coordinates></kml:LinearRing></kml:outerBoundaryIs></kml:Polygon></kml:MultiGeometry>'));
+
+
+
+
+--
+-- KML Namespace
+-- 
+
+-- KML namespace
+SELECT 'ns_1', ST_AsEWKT(ST_GeomFromKML('<kml:Point xmlns:kml="http://www.opengis.net/kml/2.2"><kml:coordinates>1,2</kml:coordinates></kml:Point>'));
+
+-- KML namespace without explicit prefix 
+SELECT 'ns_2', ST_AsEWKT(ST_GeomFromKML('<kml:Point xmlns="http://www.opengis.net/kml/2.2"><kml:coordinates>1,2</kml:coordinates></kml:Point>'));
+
+-- ERROR wrong namespace
+SELECT 'ns_3', ST_AsEWKT(ST_GeomFromKML('<kml:Point xmlns:gml="http://foo.net"><kml:coordinates>1,2</kml:coordinates></kml:Point>'));
+
+-- Several namespaces
+SELECT 'ns_4', ST_AsEWKT(ST_GeomFromKML('<kml:Point xmlns:foo="http://bar.net" xmlns:kml="http://www.opengis.net/kml/2.2"><kml:coordinates>1,2</kml:coordinates></kml:Point>'));
+
+-- Ignore other namespace element
+SELECT 'ns_5', ST_AsEWKT(ST_GeomFromKML('<kml:Point xmlns:foo="http://foo.net" xmlns:kml="http://www.opengis.net/kml/2.2"><kml:coordinates>1,2</kml:coordinates><foo:coordinates>3,4</foo:coordinates></kml:Point>'));
+
+-- Attribute without explicit namespace
+-- TODO SELECT 'ns_6', ST_AsEWKT(ST_GeomFromKML('<kml:Point altitudeMode="relative" xmlns:gml="http://www.opengis.net/gml"><kml:coordinates>1,2</kml:coordinates></kml:Point>'));
+
+-- Attribute with explicit KML namespace
+-- TODO SELECT 'ns_8', ST_AsEWKT(ST_GeomFromKML('<kml:Point kml:srsName="EPSG:4326" xmlns:gml="http://www.opengis.net/gml"><kml:coordinates>1,2</kml:coordinates></kml:Point>'));
+
+-- Attribute with explicit prefix but unqualified namespace
+-- TODO SELECT 'ns_10', ST_AsEWKT(ST_GeomFromKML('<kml:Point foo:srsName="EPSG:4326" xmlns:gml="http://www.opengis.net/gml"><kml:coordinates>1,2</kml:coordinates></kml:Point>'));
+
+-- Ignore other namespace attribute
+-- TODO SELECT 'ns_11', ST_AsEWKT(ST_GeomFromKML('<kml:Point foo:srsName="EPSG:4326" xmlns:foo="http://foo.net" xmlns:gml="http://www.opengis.net/gml"><kml:coordinates>1,2</kml:coordinates><foo:coordinates>3,4</foo:coordinates></kml:Point>'));
+
+
+
+
+--
+-- Coordinates
+--
+
+-- X,Y
+SELECT 'coordinates_1', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,2</kml:coordinates></kml:Point>'));
+
+-- ERROR: single X
+SELECT 'coordinates_2', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1</kml:coordinates></kml:Point>'));
+
+-- X,Y,Z
+SELECT 'coordinates_3', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,2,3</kml:coordinates></kml:Point>'));
+
+-- ERROR: 4 dimension
+SELECT 'coordinates_4', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,2,3,4</kml:coordinates></kml:Point>'));
+
+-- ERROR: Only commas
+SELECT 'coordinates_5', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>,</kml:coordinates></kml:Point>'));
+SELECT 'coordinates_6', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates> , </kml:coordinates></kml:Point>'));
+
+-- ERROR: empty or spaces
+SELECT 'coordinates_7', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates></kml:coordinates></kml:Point>'));
+SELECT 'coordinates_8', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>  </kml:coordinates></kml:Point>'));
+
+-- ERROR: End on comma
+SELECT 'coordinates_9', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,2,3,</kml:coordinates></kml:Point>'));
+SELECT 'coordinates_10', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,2,</kml:coordinates></kml:Point>'));
+
+-- ERROR: Begin on comma
+SELECT 'coordinates_11', ST_AsEWKT(ST_GeomFromKML('<kml:LineString><kml:coordinates>,1 2,3</kml:coordinates></kml:LineString>'));
+
+-- Whitespaces before and after 
+SELECT 'coordinates_12', ST_AsEWKT(ST_GeomFromKML('<kml:LineString><kml:coordinates> 1,2 3,4 </kml:coordinates></kml:LineString>'));
+SELECT 'coordinates_13', ST_AsEWKT(ST_GeomFromKML('<kml:LineString><kml:coordinates> 
+                                                               1,2 3,4  
+                                                  </kml:coordinates></kml:LineString>'));
+
+-- ERROR: Spaces insides 
+SELECT 'coordinates_14', ST_AsEWKT(ST_GeomFromKML('<kml:LineString><kml:coordinates>1, 2 3, 4</kml:coordinates></kml:LineString>'));
+
+-- Several spaces as tuples separator
+SELECT 'coordinates_15', ST_AsEWKT(ST_GeomFromKML('<kml:LineString><kml:coordinates>1,2   3,4</kml:coordinates></kml:LineString>'));
+SELECT 'coordinates_16', ST_AsEWKT(ST_GeomFromKML('<kml:LineString><kml:coordinates>
+                                                                       1,2
+                                                                       3,4
+                                                  </kml:coordinates></kml:LineString>'));
+
+-- ERROR: Junk
+SELECT 'coordinates_17', ST_AsEWKT(ST_GeomFromKML('<kml:LineString><kml:coordinates>!@#$%^*()"</kml:coordinates></kml:LineString>'));
+
+
+
+
+
+
+
+
+--
+-- Bijective PostGIS KML test
+--
+
+-- Point
+SELECT 'kml_1', ST_AsEWKT(ST_GeomFromKML(ST_AsKML(ST_AsEWKT('SRID=4326;POINT(1 2)'))));
+
+-- Point - 3D
+SELECT 'kml_2', ST_AsEWKT(ST_GeomFromKML(ST_AsKML(ST_AsEWKT('SRID=4326;POINT(1 2 3)'))));
+
+-- Linestring  
+SELECT 'kml_3', ST_AsEWKT(ST_GeomFromKML(ST_AsKML(ST_AsEWKT('SRID=4326;LINESTRING(1 2,3 4)'))));
+
+-- Linestring - 3D
+SELECT 'kml_4', ST_AsEWKT(ST_GeomFromKML(ST_AsKML(ST_AsEWKT('SRID=4326;LINESTRING(1 2 3,4 5 6)'))));
+
+-- Polygon KML
+SELECT 'kml_5', ST_AsEWKT(ST_GeomFromKML(ST_AsKML(ST_AsEWKT('SRID=4326;POLYGON((1 2,3 4,5 6,1 2))'))));
+
+-- Polygon KML - 3D
+SELECT 'kml_6', ST_AsEWKT(ST_GeomFromKML(ST_AsKML(ST_AsEWKT('SRID=4326;POLYGON((1 2 3,4 5 6,7 8 9,1 2 3))'))));
+
+-- Multipoint
+--SELECT 'kml_7', ST_AsEWKT(ST_GeomFromKML(ST_AsKML(ST_AsEWKT('SRID=4326;MULTIPOINT(1 2)'))));
+
+-- Multipoint - 3D
+--SELECT 'kml_8', ST_AsEWKT(ST_GeomFromKML(ST_AsKML(ST_AsEWKT('SRID=4326;MULTIPOINT(1 2 3)'))));
+
+-- Multilinestring
+--SELECT 'kml_9', ST_AsEWKT(ST_GeomFromKML(ST_AsKML(ST_AsEWKT('SRID=4326;MULTILINESTRING((1 2,3 4))'))));
+
+-- Multilinestring - 3D
+--SELECT 'kml_10', ST_AsEWKT(ST_GeomFromKML(ST_AsKML(ST_AsEWKT('SRID=4326;MULTILINESTRING((1 2 3,4 5 6))'))));
+
+-- Multipolygon 
+--SELECT 'kml_11', ST_AsEWKT(ST_GeomFromKML(ST_AsKML(ST_AsEWKT('SRID=4326;MULTIPOLYGON(((1 2,3 4,5 6,1 2)))'))));
+
+-- Multipolygon - 3D
+--SELECT 'kml_12', ST_AsEWKT(ST_GeomFromKML(ST_AsKML(ST_AsEWKT('SRID=4326;MULTIPOLYGON(((1 2 3,4 5 6,7 8 9,1 2 3)))'))));
+
+-- Collection
+--SELECT 'kml_13', ST_AsEWKT(ST_GeomFromKML(ST_AsKML(ST_AsEWKT('SRID=4326;GEOMETRYCOLLECTION(POINT(1 2))'))));
+
+-- Collection - 3D
+--SELECT 'kml_14', ST_AsEWKT(ST_GeomFromKML(ST_AsKML(ST_AsEWKT('SRID=4326;GEOMETRYCOLLECTION(POINT(1 2 3))'))));
+
+
+
+
+--
+-- Double
+--
+
+-- Several digits
+SELECT 'double_1', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,1234567890</kml:coordinates></kml:Point>'));
+
+-- Sign +/- 
+SELECT 'double_2', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,-1</kml:coordinates></kml:Point>'));
+SELECT 'double_3', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,+1</kml:coordinates></kml:Point>'));
+
+-- ERROR: double sign
+SELECT 'double_4', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,--1</kml:coordinates></kml:Point>'));
+
+-- ERROR: sign inside digit
+SELECT 'double_5', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,1-1</kml:coordinates></kml:Point>'));
+
+-- Decimal part
+SELECT 'double_6', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,1.2</kml:coordinates></kml:Point>'));
+SELECT 'double_7', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,1.23</kml:coordinates></kml:Point>'));
+
+-- no digit after dot
+SELECT 'double_8', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,1.</kml:coordinates></kml:Point>'));
+
+-- ERROR: several dots
+SELECT 'double_9', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,1.2.3</kml:coordinates></kml:Point>'));
+
+-- ERROR: no digit before dot
+SELECT 'double_10', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,.1</kml:coordinates></kml:Point>'));
+SELECT 'double_11', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,-.1</kml:coordinates></kml:Point>'));
+
+-- ERROR: not a digit
+SELECT 'double_12', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,a</kml:coordinates></kml:Point>'));
+SELECT 'double_13', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,1a</kml:coordinates></kml:Point>'));
+SELECT 'double_14', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,1a2</kml:coordinates></kml:Point>'));
+
+-- Exp 
+SELECT 'double_15', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,1e2</kml:coordinates></kml:Point>'));
+SELECT 'double_16', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,1E+2</kml:coordinates></kml:Point>'));
+SELECT 'double_17', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,1e-2</kml:coordinates></kml:Point>'));
+SELECT 'double_18', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,1E-2</kml:coordinates></kml:Point>'));
+
+-- Exp with decimal parts
+SELECT 'double_19', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,1.23E2</kml:coordinates></kml:Point>'));
+SELECT 'double_20', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,1.23e2</kml:coordinates></kml:Point>'));
+SELECT 'double_21', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,-1.23E2</kml:coordinates></kml:Point>'));
+
+-- ERROR: no exp digit
+SELECT 'double_22', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,1E</kml:coordinates></kml:Point>'));
+SELECT 'double_23', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,1e</kml:coordinates></kml:Point>'));
+
+-- ERROR: dot inside exp digits
+SELECT 'double_24', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,1e2.3</kml:coordinates></kml:Point>'));
+SELECT 'double_25', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,1E2.3</kml:coordinates></kml:Point>'));
+
+-- ERROR: spaces inside 
+SELECT 'double_26', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,- 1.23</kml:coordinates></kml:Point>'));
+SELECT 'double_27', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,-1 .23</kml:coordinates></kml:Point>'));
+SELECT 'double_28', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,-1. 23</kml:coordinates></kml:Point>'));
+SELECT 'double_29', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,-1.23 E2</kml:coordinates></kml:Point>'));
+SELECT 'double_30', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,-1.23E 2</kml:coordinates></kml:Point>'));
+
+-- ERROR: Junk 
+SELECT 'double_31', ST_AsEWKT(ST_GeomFromKML('<kml:Point><kml:coordinates>1,$0%@#$^%#</kml:coordinates></kml:Point>'));
+
+
+
+
+
+--
+-- Delete inserted spatial data
+--
+DELETE FROM spatial_ref_sys WHERE srid = 4326;
diff --git a/regress/in_kml_expected b/regress/in_kml_expected
new file mode 100644 (file)
index 0000000..f060946
--- /dev/null
@@ -0,0 +1,90 @@
+empty_geom|
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+point_1|SRID=4326;POINT(1 2)
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+linestring_1|SRID=4326;LINESTRING(1 2,3 4)
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+linestring_5|SRID=4326;LINESTRING(1 2,3 4)
+polygon_1|SRID=4326;POLYGON((1 2,3 4,5 6,1 2))
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+polygon_9|SRID=4326;POLYGON((1 2,3 4,5 6,1 2),(7 8,9 10,11 12,7 8))
+polygon_10|SRID=4326;POLYGON((1 2,3 4,5 6,1 2),(7 8,9 10,11 12,7 8))
+polygon_11|SRID=4326;POLYGON((1 2,3 4,5 6,1 2))
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+polygon_15|SRID=4326;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))
+multi_7|SRID=4326;GEOMETRYCOLLECTION(POINT(1 2),LINESTRING(3 4,5 6),POLYGON((7 8,9 10,11 12,7 8)))
+multi_8|SRID=4326;GEOMETRYCOLLECTION EMPTY
+multi_9|SRID=4326;GEOMETRYCOLLECTION(POINT(1 2),GEOMETRYCOLLECTION(LINESTRING(3 4,5 6),POLYGON((7 8,9 10,11 12,7 8))))
+multi_10|SRID=4326;GEOMETRYCOLLECTION(POINT(1 2),LINESTRING(3 4,5 6),POLYGON((7 8,9 10,11 12,7 8)))
+ns_1|SRID=4326;POINT(1 2)
+ns_2|SRID=4326;POINT(1 2)
+ERROR:  invalid KML representation
+ns_4|SRID=4326;POINT(1 2)
+ns_5|SRID=4326;POINT(1 2)
+coordinates_1|SRID=4326;POINT(1 2)
+ERROR:  invalid KML representation
+coordinates_3|SRID=4326;POINT(1 2 3)
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+coordinates_12|SRID=4326;LINESTRING(1 2,3 4)
+coordinates_13|SRID=4326;LINESTRING(1 2,3 4)
+ERROR:  invalid KML representation
+coordinates_15|SRID=4326;LINESTRING(1 2,3 4)
+coordinates_16|SRID=4326;LINESTRING(1 2,3 4)
+ERROR:  invalid KML representation
+kml_1|SRID=4326;POINT(1 2)
+kml_2|SRID=4326;POINT(1 2 3)
+kml_3|SRID=4326;LINESTRING(1 2,3 4)
+kml_4|SRID=4326;LINESTRING(1 2 3,4 5 6)
+kml_5|SRID=4326;POLYGON((1 2,3 4,5 6,1 2))
+kml_6|SRID=4326;POLYGON((1 2 3,4 5 6,7 8 9,1 2 3))
+double_1|SRID=4326;POINT(1 1234567890)
+double_2|SRID=4326;POINT(1 -1)
+double_3|SRID=4326;POINT(1 1)
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+double_6|SRID=4326;POINT(1 1.2)
+double_7|SRID=4326;POINT(1 1.23)
+double_8|SRID=4326;POINT(1 1)
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+double_15|SRID=4326;POINT(1 100)
+double_16|SRID=4326;POINT(1 100)
+double_17|SRID=4326;POINT(1 0.01)
+double_18|SRID=4326;POINT(1 0.01)
+double_19|SRID=4326;POINT(1 123)
+double_20|SRID=4326;POINT(1 123)
+double_21|SRID=4326;POINT(1 -123)
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation
+ERROR:  invalid KML representation