diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc index 55fbe40143..19ef7ded72 100644 --- a/src/objectliterals.jsdoc +++ b/src/objectliterals.jsdoc @@ -308,6 +308,21 @@ * @typedef {Object} olx.format.GMLOptions * @property {string} featureNS Feature namespace. * @property {string} featureType Feature type to parse. + * @property {string} srsName srsName to use when writing geometries. + * @property {boolean|undefined} surface Write gml:Surface instead of + * gml:Polygon elements. This also affects the elements in multi-part + * geometries. Default is `false´. + * @property {boolean|undefined} curve Write gml:Curve instead of + * gml:LineString elements. This also affects the elements in multi-part + * geometries. Default is `false´. + * @property {boolean|undefined} multiCurve Write gml:MultiCurve instead of + * gml:MultiLineString. Since the latter is deprecated in GML 3, the + * default is `true´. + * @property {boolean|undefined} multiSurface Write gml:multiSurface instead + * of gml:MultiPolygon. Since the latter is deprecated in GML 3, the + * default is `true´. + * @property {string|undefined} schemaLocation Optional schemaLocation to use + * when writing out the GML, this will override the default provided. */ /** diff --git a/src/ol/format/gmlformat.js b/src/ol/format/gmlformat.js index 3a91cf8b77..0eaeabf093 100644 --- a/src/ol/format/gmlformat.js +++ b/src/ol/format/gmlformat.js @@ -9,7 +9,10 @@ goog.require('goog.string'); goog.require('ol.Feature'); goog.require('ol.extent'); goog.require('ol.format.XMLFeature'); +goog.require('ol.format.XSD'); +goog.require('ol.geom.Geometry'); goog.require('ol.geom.LineString'); +goog.require('ol.geom.LinearRing'); goog.require('ol.geom.MultiLineString'); goog.require('ol.geom.MultiPoint'); goog.require('ol.geom.MultiPolygon'); @@ -43,11 +46,62 @@ ol.format.GML = function(opt_options) { */ this.featureNS_ = options.featureNS; + /** + * @private + * @type {string} + */ + this.srsName_ = options.srsName; + + /** + * @private + * @type {boolean} + */ + this.surface_ = goog.isDef(options.surface) ? + options.surface : false; + + /** + * @private + * @type {boolean} + */ + this.curve_ = goog.isDef(options.curve) ? + options.curve : false; + + /** + * @private + * @type {boolean} + */ + this.multiCurve_ = goog.isDef(options.multiCurve) ? + options.multiCurve : true; + + /** + * @private + * @type {boolean} + */ + this.multiSurface_ = goog.isDef(options.multiSurface) ? + options.multiSurface : true; + + /** + * @private + * @type {string} + */ + this.schemaLocation_ = goog.isDef(options.schemaLocation) ? + options.schemaLocation : ol.format.GML.schemaLocation_; + goog.base(this); }; goog.inherits(ol.format.GML, ol.format.XMLFeature); +/** + * @const + * @type {string} + * @private + */ +ol.format.GML.schemaLocation_ = 'http://www.opengis.net/gml ' + + 'http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/' + + '1.0.0/gmlsf.xsd'; + + /** * @param {Node} node Node. * @param {Array.<*>} objectStack Object stack. @@ -488,7 +542,7 @@ ol.format.GML.readFlatLinearRing_ = function(node, objectStack) { * @param {Node} node Node. * @param {Array.<*>} objectStack Object stack. * @private - * @return {ol.geom.Polygon|undefined} Polygon. + * @return {ol.geom.LinearRing|undefined} LinearRing. */ ol.format.GML.readLinearRing_ = function(node, objectStack) { goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT); @@ -496,10 +550,9 @@ ol.format.GML.readLinearRing_ = function(node, objectStack) { var flatCoordinates = ol.format.GML.readFlatCoordinatesFromNode_(node, objectStack); if (goog.isDef(flatCoordinates)) { - var polygon = new ol.geom.Polygon(null); - polygon.setFlatCoordinates(ol.geom.GeometryLayout.XYZ, flatCoordinates, - [flatCoordinates.length]); - return polygon; + var ring = new ol.geom.LinearRing(null); + ring.setFlatCoordinates(ol.geom.GeometryLayout.XYZ, flatCoordinates); + return ring; } else { return undefined; } @@ -672,17 +725,23 @@ ol.format.GML.readFlatPosList_ = function(node, objectStack) { } var coords = s.split(/\s+/); // The "dimension" attribute is from the GML 3.0.1 spec. - var dim = parseInt(node.getAttribute('srsDimension') || - node.getAttribute('dimension'), 10) || - (!goog.isNull(containerDimension)) ? - parseInt(containerDimension, 10) : 2; + var dim = 2; + if (!goog.isNull(node.getAttribute('srsDimension'))) { + dim = ol.format.XSD.readNonNegativeIntegerString( + node.getAttribute('srsDimension')); + } else if (!goog.isNull(node.getAttribute('dimension'))) { + dim = ol.format.XSD.readNonNegativeIntegerString( + node.getAttribute('dimension')); + } else if (!goog.isNull(containerDimension)) { + dim = ol.format.XSD.readNonNegativeIntegerString(containerDimension); + } var x, y, z; var flatCoordinates = []; for (var i = 0, ii = coords.length; i < ii; i += dim) { x = parseFloat(coords[i]); y = parseFloat(coords[i + 1]); z = (dim === 3) ? parseFloat(coords[i + 2]) : 0; - if (axisOrientation === 'enu') { + if (axisOrientation.substr(0, 2) === 'en') { flatCoordinates.push(x, y, z); } else { flatCoordinates.push(y, x, z); @@ -973,3 +1032,601 @@ ol.format.GML.prototype.readFeaturesFromNode = function(node) { }]; return ol.format.GML.readFeatures_(node, objectStack); }; + + +/** + * @param {Node} node Node. + * @param {ol.geom.Point} value Point geometry. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GML.writePos_ = function(node, value, objectStack) { + var context = objectStack[objectStack.length - 1]; + goog.asserts.assert(goog.isObject(context)); + var srsName = goog.object.get(context, 'srsName'); + var axisOrientation = 'enu'; + if (goog.isDefAndNotNull(srsName)) { + axisOrientation = ol.proj.get(srsName).getAxisOrientation(); + } + var point = value.getCoordinates(); + var coords; + // only 2d for simple features profile + if (axisOrientation.substr(0, 2) === 'en') { + coords = (point[0] + ' ' + point[1]); + } else { + coords = (point[1] + ' ' + point[0]); + } + ol.format.XSD.writeStringTextNode(node, coords); +}; + + +/** + * @param {Array.} point Point geometry. + * @param {string=} opt_srsName Optional srsName + * @return {string} + * @private + */ +ol.format.GML.getCoords_ = function(point, opt_srsName) { + var axisOrientation = 'enu'; + if (goog.isDefAndNotNull(opt_srsName)) { + axisOrientation = ol.proj.get(opt_srsName).getAxisOrientation(); + } + return ((axisOrientation.substr(0, 2) === 'en') ? + point[0] + ' ' + point[1] : + point[1] + ' ' + point[0]); +}; + + +/** + * @param {Node} node Node. + * @param {ol.geom.LineString|ol.geom.LinearRing} value Geometry. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GML.writePosList_ = function(node, value, objectStack) { + var context = objectStack[objectStack.length - 1]; + goog.asserts.assert(goog.isObject(context)); + var srsName = goog.object.get(context, 'srsName'); + // only 2d for simple features profile + var points = value.getCoordinates(); + var len = points.length; + var parts = new Array(len); + var point; + for (var i = 0; i < len; ++i) { + point = points[i]; + parts[i] = ol.format.GML.getCoords_(point, srsName); + } + ol.format.XSD.writeStringTextNode(node, parts.join(' ')); +}; + + +/** + * @param {Node} node Node. + * @param {ol.geom.Point} geometry Point geometry. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GML.writePoint_ = function(node, geometry, objectStack) { + var context = objectStack[objectStack.length - 1]; + goog.asserts.assert(goog.isObject(context)); + var srsName = goog.object.get(context, 'srsName'); + if (goog.isDefAndNotNull(srsName)) { + node.setAttribute('srsName', srsName); + } + var pos = ol.xml.createElementNS(node.namespaceURI, 'pos'); + node.appendChild(pos); + ol.format.GML.writePos_(pos, geometry, objectStack); +}; + + +/** + * @param {Node} node Node. + * @param {ol.geom.LinearRing} geometry LinearRing geometry. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GML.writeLinearRing_ = function(node, geometry, objectStack) { + var context = objectStack[objectStack.length - 1]; + goog.asserts.assert(goog.isObject(context)); + var srsName = goog.object.get(context, 'srsName'); + if (goog.isDefAndNotNull(srsName)) { + node.setAttribute('srsName', srsName); + } + var posList = ol.xml.createElementNS(node.namespaceURI, 'posList'); + node.appendChild(posList); + ol.format.GML.writePosList_(posList, geometry, objectStack); +}; + + +/** + * @param {*} value Value. + * @param {Array.<*>} objectStack Object stack. + * @param {string=} opt_nodeName Node name. + * @return {Node} Node. + * @private + */ +ol.format.GML.RING_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) { + var context = objectStack[objectStack.length - 1]; + var parentNode = context.node; + goog.asserts.assert(goog.isObject(context)); + var exteriorWritten = goog.object.get(context, 'exteriorWritten'); + if (!goog.isDef(exteriorWritten)) { + goog.object.set(context, 'exteriorWritten', true); + } + return ol.xml.createElementNS(parentNode.namespaceURI, + goog.isDef(exteriorWritten) ? 'interior' : 'exterior'); +}; + + +/** + * @param {Node} node Node. + * @param {ol.geom.Polygon} geometry Polygon geometry. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GML.writeSurfaceOrPolygon_ = function(node, geometry, objectStack) { + var context = objectStack[objectStack.length - 1]; + goog.asserts.assert(goog.isObject(context)); + var srsName = goog.object.get(context, 'srsName'); + if (node.nodeName !== 'PolygonPatch' && goog.isDefAndNotNull(srsName)) { + node.setAttribute('srsName', srsName); + } + if (node.nodeName === 'Polygon' || node.nodeName === 'PolygonPatch') { + var rings = geometry.getLinearRings(); + ol.xml.pushSerializeAndPop( + {node: node, srsName: srsName}, + ol.format.GML.RING_SERIALIZERS_, ol.format.GML.RING_NODE_FACTORY_, + rings, objectStack); + } else if (node.nodeName === 'Surface') { + var patches = ol.xml.createElementNS(node.namespaceURI, 'patches'); + node.appendChild(patches); + ol.format.GML.writeSurfacePatches_(patches, geometry, objectStack); + } +}; + + +/** + * @param {Node} node Node. + * @param {ol.geom.LineString} geometry LineString geometry. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GML.writeCurveOrLineString_ = function(node, geometry, objectStack) { + var context = objectStack[objectStack.length - 1]; + goog.asserts.assert(goog.isObject(context)); + var srsName = goog.object.get(context, 'srsName'); + if (node.nodeName !== 'LineStringSegment' && goog.isDefAndNotNull(srsName)) { + node.setAttribute('srsName', srsName); + } + if (node.nodeName === 'LineString' || node.nodeName === 'LineStringSegment') { + var posList = ol.xml.createElementNS(node.namespaceURI, 'posList'); + node.appendChild(posList); + ol.format.GML.writePosList_(posList, geometry, objectStack); + } else if (node.nodeName === 'Curve') { + var segments = ol.xml.createElementNS(node.namespaceURI, 'segments'); + node.appendChild(segments); + ol.format.GML.writeCurveSegments_(segments, geometry, objectStack); + } +}; + + +/** + * @param {Node} node Node. + * @param {ol.geom.MultiPolygon} geometry MultiPolygon geometry. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GML.writeMultiSurfaceOrPolygon_ = function(node, geometry, + objectStack) { + var context = objectStack[objectStack.length - 1]; + goog.asserts.assert(goog.isObject(context)); + var srsName = goog.object.get(context, 'srsName'); + var surface = goog.object.get(context, 'surface'); + if (goog.isDefAndNotNull(srsName)) { + node.setAttribute('srsName', srsName); + } + var polygons = geometry.getPolygons(); + ol.xml.pushSerializeAndPop({node: node, srsName: srsName, surface: surface}, + ol.format.GML.SURFACEORPOLYGONMEMBER_SERIALIZERS_, + ol.format.GML.MULTIGEOMETRY_MEMBER_NODE_FACTORY_, polygons, + objectStack); +}; + + +/** + * @param {Node} node Node. + * @param {ol.geom.MultiPoint} geometry MultiPoint geometry. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GML.writeMultiPoint_ = function(node, geometry, + objectStack) { + var context = objectStack[objectStack.length - 1]; + goog.asserts.assert(goog.isObject(context)); + var srsName = goog.object.get(context, 'srsName'); + if (goog.isDefAndNotNull(srsName)) { + node.setAttribute('srsName', srsName); + } + var points = geometry.getPoints(); + ol.xml.pushSerializeAndPop({node: node, srsName: srsName}, + ol.format.GML.POINTMEMBER_SERIALIZERS_, + ol.xml.makeSimpleNodeFactory('pointMember'), points, + objectStack); +}; + + +/** + * @param {Node} node Node. + * @param {ol.geom.MultiLineString} geometry MultiLineString geometry. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GML.writeMultiCurveOrLineString_ = function(node, geometry, + objectStack) { + var context = objectStack[objectStack.length - 1]; + goog.asserts.assert(goog.isObject(context)); + var srsName = goog.object.get(context, 'srsName'); + var curve = goog.object.get(context, 'curve'); + if (goog.isDefAndNotNull(srsName)) { + node.setAttribute('srsName', srsName); + } + var lines = geometry.getLineStrings(); + ol.xml.pushSerializeAndPop({node: node, srsName: srsName, curve: curve}, + ol.format.GML.LINESTRINGORCURVEMEMBER_SERIALIZERS_, + ol.format.GML.MULTIGEOMETRY_MEMBER_NODE_FACTORY_, lines, + objectStack); +}; + + +/** + * @param {Node} node Node. + * @param {ol.geom.LinearRing} ring LinearRing geometry. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GML.writeRing_ = function(node, ring, objectStack) { + var linearRing = ol.xml.createElementNS(node.namespaceURI, 'LinearRing'); + node.appendChild(linearRing); + ol.format.GML.writeLinearRing_(linearRing, ring, objectStack); +}; + + +/** + * @param {Node} node Node. + * @param {ol.geom.Polygon} polygon Polygon geometry. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GML.writeSurfaceOrPolygonMember_ = function(node, polygon, + objectStack) { + var context = objectStack[objectStack.length - 1]; + goog.asserts.assert(goog.isObject(context)); + var child = ol.format.GML.GEOMETRY_NODE_FACTORY_(polygon, objectStack); + if (goog.isDef(child)) { + node.appendChild(child); + ol.format.GML.writeSurfaceOrPolygon_(child, polygon, objectStack); + } +}; + + +/** + * @param {Node} node Node. + * @param {ol.geom.Point} point Point geometry. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GML.writePointMember_ = function(node, point, objectStack) { + var child = ol.xml.createElementNS(node.namespaceURI, 'Point'); + node.appendChild(child); + ol.format.GML.writePoint_(child, point, objectStack); +}; + + +/** + * @param {Node} node Node. + * @param {ol.geom.LineString} line LineString geometry. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GML.writeLineStringOrCurveMember_ = function(node, line, + objectStack) { + var context = objectStack[objectStack.length - 1]; + goog.asserts.assert(goog.isObject(context)); + var child = ol.format.GML.GEOMETRY_NODE_FACTORY_(line, objectStack); + if (goog.isDef(child)) { + node.appendChild(child); + ol.format.GML.writeCurveOrLineString_(child, line, objectStack); + } +}; + + +/** + * @param {Node} node Node. + * @param {ol.geom.Polygon} polygon Polygon geometry. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GML.writeSurfacePatches_ = function(node, polygon, objectStack) { + var child = ol.xml.createElementNS(node.namespaceURI, 'PolygonPatch'); + node.appendChild(child); + ol.format.GML.writeSurfaceOrPolygon_(child, polygon, objectStack); +}; + + +/** + * @param {Node} node Node. + * @param {ol.geom.LineString} line LineString geometry. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GML.writeCurveSegments_ = function(node, line, objectStack) { + var child = ol.xml.createElementNS(node.namespaceURI, 'LineStringSegment'); + node.appendChild(child); + ol.format.GML.writeCurveOrLineString_(child, line, objectStack); +}; + + +/** + * @param {Node} node Node. + * @param {ol.geom.Geometry} geometry Geometry. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GML.writeGeometry_ = function(node, geometry, objectStack) { + var context = objectStack[objectStack.length - 1]; + goog.asserts.assert(goog.isObject(context)); + var item = goog.object.clone(context); + item.node = node; + ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ + (item), ol.format.GML.GEOMETRY_SERIALIZERS_, + ol.format.GML.GEOMETRY_NODE_FACTORY_, [geometry], objectStack); +}; + + +/** + * @param {Node} node Node. + * @param {ol.Feature} feature Feature. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GML.writeFeature_ = function(node, feature, objectStack) { + var fid = feature.getId(); + if (goog.isDef(fid)) { + node.setAttribute('fid', fid); + } + var context = objectStack[objectStack.length - 1]; + goog.asserts.assert(goog.isObject(context)); + var featureNS = goog.object.get(context, 'featureNS'); + var geometryName = feature.getGeometryName(); + if (!goog.isDef(context.serializers)) { + context.serializers = {}; + context.serializers[featureNS] = {}; + } + var properties = feature.getProperties(); + var keys = [], values = []; + for (var key in properties) { + keys.push(key); + values.push(properties[key]); + if (key == geometryName) { + if (!(key in context.serializers[featureNS])) { + context.serializers[featureNS][key] = ol.xml.makeChildAppender( + ol.format.GML.writeGeometry_); + } + } else { + if (!(key in context.serializers[featureNS])) { + context.serializers[featureNS][key] = ol.xml.makeChildAppender( + ol.format.XSD.writeStringTextNode); + } + } + } + var item = goog.object.clone(context); + item.node = node; + ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ + (item), context.serializers, + ol.xml.OBJECT_PROPERTY_NODE_FACTORY, + values, + objectStack, keys); +}; + + +/** + * @param {Node} node Node. + * @param {Array.} features Features. + * @param {Array.<*>} objectStack Node stack. + * @private + */ +ol.format.GML.writeFeatureMembers_ = function(node, features, objectStack) { + var context = objectStack[objectStack.length - 1]; + goog.asserts.assert(goog.isObject(context)); + var featureType = goog.object.get(context, 'featureType'); + var featureNS = goog.object.get(context, 'featureNS'); + var serializers = {}; + serializers[featureNS] = {}; + serializers[featureNS][featureType] = ol.xml.makeChildAppender( + ol.format.GML.writeFeature_); + var item = goog.object.clone(context); + item.node = node; + ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ + (item), + serializers, + ol.xml.makeSimpleNodeFactory(featureType, featureNS), features, + objectStack); +}; + + +/** + * @type {Object.>} + * @private + */ +ol.format.GML.SURFACEORPOLYGONMEMBER_SERIALIZERS_ = { + 'http://www.opengis.net/gml': { + 'surfaceMember': ol.xml.makeChildAppender( + ol.format.GML.writeSurfaceOrPolygonMember_), + 'polygonMember': ol.xml.makeChildAppender( + ol.format.GML.writeSurfaceOrPolygonMember_) + } +}; + + +/** + * @type {Object.>} + * @private + */ +ol.format.GML.POINTMEMBER_SERIALIZERS_ = { + 'http://www.opengis.net/gml': { + 'pointMember': ol.xml.makeChildAppender(ol.format.GML.writePointMember_) + } +}; + + +/** + * @type {Object.>} + * @private + */ +ol.format.GML.LINESTRINGORCURVEMEMBER_SERIALIZERS_ = { + 'http://www.opengis.net/gml': { + 'lineStringMember': ol.xml.makeChildAppender( + ol.format.GML.writeLineStringOrCurveMember_), + 'curveMember': ol.xml.makeChildAppender( + ol.format.GML.writeLineStringOrCurveMember_) + } +}; + + +/** + * @type {Object.>} + * @private + */ +ol.format.GML.RING_SERIALIZERS_ = { + 'http://www.opengis.net/gml': { + 'exterior': ol.xml.makeChildAppender(ol.format.GML.writeRing_), + 'interior': ol.xml.makeChildAppender(ol.format.GML.writeRing_) + } +}; + + +/** + * @type {Object.>} + * @private + */ +ol.format.GML.GEOMETRY_SERIALIZERS_ = { + 'http://www.opengis.net/gml': { + 'Curve': ol.xml.makeChildAppender(ol.format.GML.writeCurveOrLineString_), + 'MultiCurve': ol.xml.makeChildAppender( + ol.format.GML.writeMultiCurveOrLineString_), + 'Point': ol.xml.makeChildAppender(ol.format.GML.writePoint_), + 'MultiPoint': ol.xml.makeChildAppender(ol.format.GML.writeMultiPoint_), + 'LineString': ol.xml.makeChildAppender( + ol.format.GML.writeCurveOrLineString_), + 'MultiLineString': ol.xml.makeChildAppender( + ol.format.GML.writeMultiCurveOrLineString_), + 'LinearRing': ol.xml.makeChildAppender(ol.format.GML.writeLinearRing_), + 'Polygon': ol.xml.makeChildAppender(ol.format.GML.writeSurfaceOrPolygon_), + 'MultiPolygon': ol.xml.makeChildAppender( + ol.format.GML.writeMultiSurfaceOrPolygon_), + 'Surface': ol.xml.makeChildAppender(ol.format.GML.writeSurfaceOrPolygon_), + 'MultiSurface': ol.xml.makeChildAppender( + ol.format.GML.writeMultiSurfaceOrPolygon_) + } +}; + + +/** + * @const + * @type {Object.} + * @private + */ +ol.format.GML.MULTIGEOMETRY_TO_MEMBER_NODENAME_ = { + 'MultiLineString': 'lineStringMember', + 'MultiCurve': 'curveMember', + 'MultiPolygon': 'polygonMember', + 'MultiSurface': 'surfaceMember' +}; + + +/** + * @const + * @param {*} value Value. + * @param {Array.<*>} objectStack Object stack. + * @param {string=} opt_nodeName Node name. + * @return {Node|undefined} Node. + * @private + */ +ol.format.GML.MULTIGEOMETRY_MEMBER_NODE_FACTORY_ = function(value, + objectStack, opt_nodeName) { + var parentNode = objectStack[objectStack.length - 1].node; + goog.asserts.assert(ol.xml.isNode(parentNode)); + return ol.xml.createElementNS('http://www.opengis.net/gml', + ol.format.GML.MULTIGEOMETRY_TO_MEMBER_NODENAME_[parentNode.nodeName]); +}; + + +/** + * @const + * @param {*} value Value. + * @param {Array.<*>} objectStack Object stack. + * @param {string=} opt_nodeName Node name. + * @return {Node|undefined} Node. + * @private + */ +ol.format.GML.GEOMETRY_NODE_FACTORY_ = function(value, objectStack, + opt_nodeName) { + var context = objectStack[objectStack.length - 1]; + goog.asserts.assert(goog.isObject(context)); + var multiSurface = goog.object.get(context, 'multiSurface'); + var surface = goog.object.get(context, 'surface'); + var curve = goog.object.get(context, 'curve'); + var multiCurve = goog.object.get(context, 'multiCurve'); + goog.asserts.assertInstanceof(value, ol.geom.Geometry); + var parentNode = objectStack[objectStack.length - 1].node; + goog.asserts.assert(ol.xml.isNode(parentNode)); + var nodeName = value.getType(); + if (nodeName === 'MultiPolygon' && multiSurface === true) { + nodeName = 'MultiSurface'; + } else if (nodeName === 'Polygon' && surface === true) { + nodeName = 'Surface'; + } else if (nodeName === 'LineString' && curve === true) { + nodeName = 'Curve'; + } else if (nodeName === 'MultiLineString' && multiCurve === true) { + nodeName = 'MultiCurve'; + } + return ol.xml.createElementNS('http://www.opengis.net/gml', + nodeName); +}; + + +/** + * @inheritDoc + */ +ol.format.GML.prototype.writeGeometryNode = function(geometry) { + var geom = ol.xml.createElementNS('http://www.opengis.net/gml', 'geom'); + var context = {node: geom, srsName: this.srsName_, + curve: this.curve_, surface: this.surface_, + multiSurface: this.multiSurface_, multiCurve: this.multiCurve_}; + ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ + (context), ol.format.GML.GEOMETRY_SERIALIZERS_, + ol.format.GML.GEOMETRY_NODE_FACTORY_, [geometry], []); + return geom; +}; + + +/** + * @inheritDoc + */ +ol.format.GML.prototype.writeFeaturesNode = function(features) { + var node = ol.xml.createElementNS('http://www.opengis.net/gml', + 'featureMembers'); + ol.xml.setAttributeNS(node, 'http://www.w3.org/2001/XMLSchema-instance', + 'xsi:schemaLocation', this.schemaLocation_); + var context = { + srsName: this.srsName_, + curve: this.curve_, + surface: this.surface_, + multiSurface: this.multiSurface_, + multiCurve: this.multiCurve_, + featureNS: this.featureNS_, + featureType: this.featureType_ + }; + ol.format.GML.writeFeatureMembers_(node, features, [context]); + return node; +}; diff --git a/test/spec/ol/format/gml/topp-states-gml.xml b/test/spec/ol/format/gml/topp-states-gml.xml index 33eb7c684e..2090909512 100644 --- a/test/spec/ol/format/gml/topp-states-gml.xml +++ b/test/spec/ol/format/gml/topp-states-gml.xml @@ -7,9 +7,9 @@ - + - + 37.5101 -88.0711 37.5831 -88.1341 37.6281 -88.1571 37.6601 -88.1591 37.7001 -88.1331 37.7351 -88.0721 37.8051 -88.0351 37.8171 -88.0861 37.8311 -88.0891 37.8271 -88.0421 @@ -138,9 +138,9 @@ - + - + 38.9661 -77.0081 38.9931 -77.0421 38.9321 -77.1221 38.9151 -77.0781 38.8861 -77.0671 38.8621 -77.0391 38.8381 -77.0401 38.8291 -77.0451 38.8131 -77.0351 38.7881 -77.0451 @@ -179,9 +179,9 @@ - + - + 38.5571 -75.7071 38.4631 -75.6991 38.4551 -75.3501 38.4501 -75.0931 38.4491 -75.0681 38.4491 -75.0451 38.7991 -75.0831 38.8081 -75.1901 38.9451 -75.3071 39.0121 -75.3241 @@ -227,9 +227,9 @@ - + - + 38.4801 -79.2311 38.6581 -79.1271 38.6631 -79.1211 38.6591 -79.0881 38.7071 -79.0871 38.7611 -79.0561 38.7901 -79.0551 38.7991 -79.0331 38.8461 -78.9871 38.7631 -78.8661 @@ -378,9 +378,9 @@ - + - + 38.6491 -75.7111 38.8301 -75.7241 39.1411 -75.7521 39.2471 -75.7611 39.2951 -75.7641 39.3831 -75.7721 39.7231 -75.7911 39.7221 -76.1391 39.7211 -76.2331 39.7201 -76.5701 @@ -456,9 +456,9 @@ - + - + 38.9071 -76.2931 38.9491 -76.2731 38.9231 -76.2461 38.9781 -76.2481 39.0401 -76.2991 38.9581 -76.3561 38.8541 -76.3751 38.8751 -76.3291 38.9241 -76.3421 38.9121 -76.3221 @@ -469,9 +469,9 @@ - + - + 38.4491 -75.0681 38.3221 -75.0871 38.4491 -75.0451 38.4491 -75.0681 @@ -479,9 +479,9 @@ - + - + 38.0271 -75.2701 38.0281 -75.2421 38.1241 -75.1731 38.3201 -75.0941 38.2041 -75.1641 38.0941 -75.2091 38.0371 -75.2441 38.0271 -75.2701 @@ -519,9 +519,9 @@ - + - + 37.6411 -102.0431 37.7341 -102.0431 38.2531 -102.0451 38.2631 -102.0451 38.6151 -102.0471 38.6921 -102.0471 39.0361 -102.0481 39.1261 -102.0471 39.5621 -102.0481 39.5681 -102.0481 @@ -573,9 +573,9 @@ - + - + 36.6551 -86.5101 36.6501 -86.4151 36.6431 -86.1991 36.6331 -85.9801 36.6261 -85.7851 36.6181 -85.4371 36.6261 -85.3001 36.6251 -85.2721 36.6201 -84.9981 36.6051 -84.7911 @@ -681,9 +681,9 @@ - + - + 36.4981 -89.5331 36.4981 -89.4751 36.5041 -89.4811 36.5251 -89.4711 36.5471 -89.4811 36.5591 -89.4931 36.5641 -89.5301 36.5571 -89.5561 36.5411 -89.5681 36.5181 -89.5661 @@ -722,9 +722,9 @@ - + - + 37.0011 -95.0711 37.0001 -95.0321 36.9961 -94.6201 37.0601 -94.6201 37.3271 -94.6181 37.3601 -94.6181 37.6501 -94.6181 37.6791 -94.6191 38.0301 -94.6161 38.0551 -94.6171 @@ -795,9 +795,9 @@ - + - + 36.5461 -79.1441 36.5431 -78.7961 36.5461 -78.7371 36.5411 -78.4581 36.5451 -78.3211 36.5521 -78.0511 36.5521 -77.8981 36.5531 -77.7631 36.5531 -77.3201 36.5561 -77.1771 @@ -907,9 +907,9 @@ - + - + 38.0271 -75.2701 37.9181 -75.3461 37.9001 -75.3781 37.9011 -75.3441 37.8751 -75.3861 37.8881 -75.3391 37.9621 -75.2981 38.0281 -75.2421 38.0271 -75.2701 @@ -918,9 +918,9 @@ - + - + 37.5521 -75.8671 37.5561 -75.9301 37.5211 -75.9541 37.4791 -75.9651 37.4841 -75.9341 37.3081 -76.0181 37.1261 -75.9701 37.1421 -75.9311 37.3671 -75.8971 37.4181 -75.8261 @@ -965,9 +965,9 @@ - + - + 36.9531 -89.1041 36.9771 -89.1071 36.9881 -89.1291 36.9861 -89.1931 37.0281 -89.2101 37.0411 -89.2371 37.0871 -89.2641 37.0911 -89.2841 37.0851 -89.3031 37.0601 -89.3091 diff --git a/test/spec/ol/format/gmlformat.test.js b/test/spec/ol/format/gmlformat.test.js index 6f952fe3ed..473fbcc9a6 100644 --- a/test/spec/ol/format/gmlformat.test.js +++ b/test/spec/ol/format/gmlformat.test.js @@ -10,16 +10,17 @@ var readGeometry = function(format, text) { describe('ol.format.GML', function() { - var format; + var format, formatWGS84; beforeEach(function() { - format = new ol.format.GML(); + format = new ol.format.GML({srsName: 'CRS:84'}); + formatWGS84 = new ol.format.GML({srsName: 'urn:x-ogc:def:crs:EPSG:4326'}); }); describe('#readGeometry', function() { describe('point', function() { - it('can read a point geometry', function() { + it('can read and write a point geometry', function() { var text = '' + @@ -28,13 +29,15 @@ describe('ol.format.GML', function() { var g = readGeometry(format, text); expect(g).to.be.an(ol.geom.Point); expect(g.getCoordinates()).to.eql([1, 2, 0]); + var serialized = format.writeGeometry(g); + expect(serialized.firstElementChild).to.xmleql(ol.xml.load(text)); }); }); describe('linestring', function() { - it('can read a linestring geometry', function() { + it('can read and write a linestring geometry', function() { var text = '' + @@ -43,56 +46,71 @@ describe('ol.format.GML', function() { var g = readGeometry(format, text); expect(g).to.be.an(ol.geom.LineString); expect(g.getCoordinates()).to.eql([[1, 2, 0], [3, 4, 0]]); + var serialized = format.writeGeometry(g); + expect(serialized.firstElementChild).to.xmleql(ol.xml.load(text)); }); }); describe('axis order', function() { - it('can read a linestring geometry with correct axis order', function() { - var text = - '' + - ' -90 -180 90 180' + - ''; - var g = readGeometry(format, text); - expect(g).to.be.an(ol.geom.LineString); - expect(g.getCoordinates()).to.eql([[-180, -90, 0], [180, 90, 0]]); - }); + it('can read and write a linestring geometry with ' + + 'correct axis order', function() { + var text = + '' + + ' -90 -180 90 180' + + ''; + var g = readGeometry(format, text); + expect(g).to.be.an(ol.geom.LineString); + expect(g.getCoordinates()).to.eql([[-180, -90, 0], [180, 90, 0]]); + var serialized = formatWGS84.writeGeometry(g); + expect(serialized.firstElementChild).to.xmleql(ol.xml.load(text)); + }); - it('can read a point geometry with correct axis order', function() { - var text = - '' + - ' -90 -180' + - ''; - var g = readGeometry(format, text); - expect(g).to.be.an(ol.geom.Point); - expect(g.getCoordinates()).to.eql([-180, -90, 0]); - }); + it('can read and write a point geometry with correct axis order', + function() { + var text = + '' + + ' -90 -180' + + ''; + var g = readGeometry(format, text); + expect(g).to.be.an(ol.geom.Point); + expect(g.getCoordinates()).to.eql([-180, -90, 0]); + var serialized = formatWGS84.writeGeometry(g); + expect(serialized.firstElementChild).to.xmleql(ol.xml.load(text)); + }); - it('can read multi surface geometry with right axis order', function() { - var text = - '' + - ' ' + - ' ' + - ' ' + - ' ' + - ' 38.9661 -77.0081 38.9931 -77.0421 ' + - ' 38.9321 -77.1221 38.9151 -77.0781 38.8861 -77.0671 ' + - ' 38.8621 -77.0391 38.8381 -77.0401 38.8291 -77.0451 ' + - ' 38.8131 -77.0351 38.7881 -77.0451' + - ' 38.8891 -76.9111 38.9661 -77.0081' + - ' ' + - ' ' + - ' ' + - ' ' + - ''; - var g = readGeometry(format, text); - expect(g.getCoordinates()[0][0][0][0]).to.equal(-77.0081); - expect(g.getCoordinates()[0][0][0][1]).to.equal(38.9661); - }); + it('can read and write a surface geometry with right axis order', + function() { + var text = + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' 38.9661 -77.0081 38.9931 -77.0421 ' + + ' 38.9321 -77.1221 38.9151 -77.0781 38.8861 ' + + ' -77.0671 38.8621 -77.0391 38.8381 -77.0401 ' + + ' 38.8291 -77.0451 38.8131 -77.0351 38.7881 ' + + ' -77.0451 38.8891 -76.9111 38.9661 -77.0081' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ''; + var g = readGeometry(format, text); + expect(g.getCoordinates()[0][0][0][0]).to.equal(-77.0081); + expect(g.getCoordinates()[0][0][0][1]).to.equal(38.9661); + format = new ol.format.GML({srsName: 'urn:x-ogc:def:crs:EPSG:4326', + surface: false}); + var serialized = format.writeGeometry(g); + expect(serialized.firstElementChild).to.xmleql(ol.xml.load(text)); + }); }); @@ -113,38 +131,40 @@ describe('ol.format.GML', function() { describe('linearring', function() { - it('can read a linearring geometry', function() { + it('can read and write a linearring geometry', function() { var text = '' + ' 1 2 3 4 5 6 1 2' + ''; var g = readGeometry(format, text); - expect(g).to.be.an(ol.geom.Polygon); + expect(g).to.be.an(ol.geom.LinearRing); expect(g.getCoordinates()).to.eql( - [[[1, 2, 0], [3, 4, 0], [5, 6, 0], [1, 2, 0]]]); + [[1, 2, 0], [3, 4, 0], [5, 6, 0], [1, 2, 0]]); + var serialized = format.writeGeometry(g); + expect(serialized.firstElementChild).to.xmleql(ol.xml.load(text)); }); }); describe('polygon', function() { - it('can read a polygon geometry', function() { + it('can read and write a polygon geometry', function() { var text = '' + ' ' + - ' ' + + ' ' + ' 1 2 3 2 3 4 1 2' + ' ' + ' ' + ' ' + - ' ' + + ' ' + ' 2 3 2 5 4 5 2 3' + ' ' + ' ' + ' ' + - ' ' + + ' ' + ' 3 4 3 6 5 6 3 4' + ' ' + ' ' + @@ -154,30 +174,32 @@ describe('ol.format.GML', function() { expect(g.getCoordinates()).to.eql([[[1, 2, 0], [3, 2, 0], [3, 4, 0], [1, 2, 0]], [[2, 3, 0], [2, 5, 0], [4, 5, 0], [2, 3, 0]], [[3, 4, 0], [3, 6, 0], [5, 6, 0], [3, 4, 0]]]); + var serialized = format.writeGeometry(g); + expect(serialized.firstElementChild).to.xmleql(ol.xml.load(text)); }); }); describe('surface', function() { - it('can read a surface geometry', function() { + it('can read and write a surface geometry', function() { var text = '' + ' ' + - ' ' + + ' ' + ' ' + - ' ' + + ' ' + ' 1 2 3 2 3 4 1 2' + ' ' + ' ' + ' ' + - ' ' + + ' ' + ' 2 3 2 5 4 5 2 3' + ' ' + ' ' + ' ' + - ' ' + + ' ' + ' 3 4 3 6 5 6 3 4' + ' ' + ' ' + @@ -189,13 +211,16 @@ describe('ol.format.GML', function() { expect(g.getCoordinates()).to.eql([[[1, 2, 0], [3, 2, 0], [3, 4, 0], [1, 2, 0]], [[2, 3, 0], [2, 5, 0], [4, 5, 0], [2, 3, 0]], [[3, 4, 0], [3, 6, 0], [5, 6, 0], [3, 4, 0]]]); + format = new ol.format.GML({srsName: 'CRS:84', surface: true}); + var serialized = format.writeGeometry(g); + expect(serialized.firstElementChild).to.xmleql(ol.xml.load(text)); }); }); describe('curve', function() { - it('can read a curve geometry', function() { + it('can read and write a curve geometry', function() { var text = '' + @@ -208,6 +233,9 @@ describe('ol.format.GML', function() { var g = readGeometry(format, text); expect(g).to.be.an(ol.geom.LineString); expect(g.getCoordinates()).to.eql([[1, 2, 0], [3, 4, 0]]); + format = new ol.format.GML({srsName: 'CRS:84', curve: true}); + var serialized = format.writeGeometry(g); + expect(serialized.firstElementChild).to.xmleql(ol.xml.load(text)); }); }); @@ -229,22 +257,22 @@ describe('ol.format.GML', function() { describe('multipoint', function() { - it('can read a singular multipoint geometry', function() { + it('can read and write a singular multipoint geometry', function() { var text = '' + ' ' + - ' ' + + ' ' + ' 1 2' + ' ' + ' ' + ' ' + - ' ' + + ' ' + ' 2 3' + ' ' + ' ' + ' ' + - ' ' + + ' ' + ' 3 4' + ' ' + ' ' + @@ -252,6 +280,8 @@ describe('ol.format.GML', function() { var g = readGeometry(format, text); expect(g).to.be.an(ol.geom.MultiPoint); expect(g.getCoordinates()).to.eql([[1, 2, 0], [2, 3, 0], [3, 4, 0]]); + var serialized = format.writeGeometry(g); + expect(serialized.firstElementChild).to.xmleql(ol.xml.load(text)); }); it('can read a plural multipoint geometry', function() { @@ -279,17 +309,17 @@ describe('ol.format.GML', function() { describe('multilinestring', function() { - it('can read a singular multilinestring geometry', function() { + it('can read and write a singular multilinestring geometry', function() { var text = '' + ' ' + - ' ' + + ' ' + ' 1 2 2 3' + ' ' + ' ' + ' ' + - ' ' + + ' ' + ' 3 4 4 5' + ' ' + ' ' + @@ -298,6 +328,9 @@ describe('ol.format.GML', function() { expect(g).to.be.an(ol.geom.MultiLineString); expect(g.getCoordinates()).to.eql( [[[1, 2, 0], [2, 3, 0]], [[3, 4, 0], [4, 5, 0]]]); + format = new ol.format.GML({srsName: 'CRS:84', multiCurve: false}); + var serialized = format.writeGeometry(g); + expect(serialized.firstElementChild).to.xmleql(ol.xml.load(text)); }); it('can read a plural multilinestring geometry', function() { @@ -323,33 +356,33 @@ describe('ol.format.GML', function() { describe('multipolygon', function() { - it('can read a singular multipolygon geometry', function() { + it('can read and write a singular multipolygon geometry', function() { var text = '' + ' ' + - ' ' + + ' ' + ' ' + - ' ' + + ' ' + ' 1 2 3 2 3 4 1 2' + ' ' + ' ' + ' ' + - ' ' + + ' ' + ' 2 3 2 5 4 5 2 3' + ' ' + ' ' + ' ' + - ' ' + + ' ' + ' 3 4 3 6 5 6 3 4' + ' ' + ' ' + ' ' + ' ' + ' ' + - ' ' + + ' ' + ' ' + - ' ' + + ' ' + ' 1 2 3 2 3 4 1 2' + ' ' + ' ' + @@ -363,6 +396,9 @@ describe('ol.format.GML', function() { [1, 2, 0]], [[2, 3, 0], [2, 5, 0], [4, 5, 0], [2, 3, 0]], [[3, 4, 0], [3, 6, 0], [5, 6, 0], [3, 4, 0]]], [[[1, 2, 0], [3, 2, 0], [3, 4, 0], [1, 2, 0]]]]); + format = new ol.format.GML({srsName: 'CRS:84', multiSurface: false}); + var serialized = format.writeGeometry(g); + expect(serialized.firstElementChild).to.xmleql(ol.xml.load(text)); }); it('can read a plural multipolygon geometry', function() { @@ -409,33 +445,36 @@ describe('ol.format.GML', function() { describe('multicurve', function() { - it('can read a singular multicurve-linestring geometry', function() { - var text = - '' + - ' ' + - ' ' + - ' 1 2 2 3' + - ' ' + - ' ' + - ' ' + - ' ' + - ' 3 4 4 5' + - ' ' + - ' ' + - ''; - var g = readGeometry(format, text); - expect(g).to.be.an(ol.geom.MultiLineString); - expect(g.getCoordinates()).to.eql( - [[[1, 2, 0], [2, 3, 0]], [[3, 4, 0], [4, 5, 0]]]); - }); + it('can read and write a singular multicurve-linestring geometry', + function() { + var text = + '' + + ' ' + + ' ' + + ' 1 2 2 3' + + ' ' + + ' ' + + ' ' + + ' ' + + ' 3 4 4 5' + + ' ' + + ' ' + + ''; + var g = readGeometry(format, text); + expect(g).to.be.an(ol.geom.MultiLineString); + expect(g.getCoordinates()).to.eql( + [[[1, 2, 0], [2, 3, 0]], [[3, 4, 0], [4, 5, 0]]]); + var serialized = format.writeGeometry(g); + expect(serialized.firstElementChild).to.xmleql(ol.xml.load(text)); + }); - it('can read a singular multicurve-curve geometry', function() { + it('can read and write a singular multicurve-curve geometry', function() { var text = '' + ' ' + - ' ' + + ' ' + ' ' + ' ' + ' 1 2 2 3' + @@ -444,7 +483,7 @@ describe('ol.format.GML', function() { ' ' + ' ' + ' ' + - ' ' + + ' ' + ' ' + ' ' + ' 3 4 4 5' + @@ -457,39 +496,42 @@ describe('ol.format.GML', function() { expect(g).to.be.an(ol.geom.MultiLineString); expect(g.getCoordinates()).to.eql( [[[1, 2, 0], [2, 3, 0]], [[3, 4, 0], [4, 5, 0]]]); + format = new ol.format.GML({srsName: 'CRS:84', curve: true}); + var serialized = format.writeGeometry(g); + expect(serialized.firstElementChild).to.xmleql(ol.xml.load(text)); }); }); describe('multisurface', function() { - it('can read a singular multisurface geometry', function() { + it('can read and write a singular multisurface geometry', function() { var text = '' + ' ' + - ' ' + + ' ' + ' ' + - ' ' + + ' ' + ' 1 2 3 2 3 4 1 2' + ' ' + ' ' + ' ' + - ' ' + + ' ' + ' 2 3 2 5 4 5 2 3' + ' ' + ' ' + ' ' + - ' ' + + ' ' + ' 3 4 3 6 5 6 3 4' + ' ' + ' ' + ' ' + ' ' + ' ' + - ' ' + + ' ' + ' ' + - ' ' + + ' ' + ' 1 2 3 2 3 4 1 2' + ' ' + ' ' + @@ -503,6 +545,8 @@ describe('ol.format.GML', function() { [1, 2, 0]], [[2, 3, 0], [2, 5, 0], [4, 5, 0], [2, 3, 0]], [[3, 4, 0], [3, 6, 0], [5, 6, 0], [3, 4, 0]]], [[[1, 2, 0], [3, 2, 0], [3, 4, 0], [1, 2, 0]]]]); + var serialized = format.writeGeometry(g); + expect(serialized.firstElementChild).to.xmleql(ol.xml.load(text)); }); it('can read a plural multisurface geometry', function() { @@ -547,26 +591,26 @@ describe('ol.format.GML', function() { [[[1, 2, 0], [3, 2, 0], [3, 4, 0], [1, 2, 0]]]]); }); - it('can read a multisurface-surface geometry', function() { + it('can read and write a multisurface-surface geometry', function() { var text = '' + ' ' + - ' ' + + ' ' + ' ' + - ' ' + + ' ' + ' ' + - ' ' + + ' ' + ' 1 2 3 2 3 4 1 2' + ' ' + ' ' + ' ' + - ' ' + + ' ' + ' 2 3 2 5 4 5 2 3' + ' ' + ' ' + ' ' + - ' ' + + ' ' + ' 3 4 3 6 5 6 3 4' + ' ' + ' ' + @@ -575,11 +619,11 @@ describe('ol.format.GML', function() { ' ' + ' ' + ' ' + - ' ' + + ' ' + ' ' + - ' ' + + ' ' + ' ' + - ' ' + + ' ' + ' 1 2 3 2 3 4 1 2' + ' ' + ' ' + @@ -595,6 +639,9 @@ describe('ol.format.GML', function() { [1, 2, 0]], [[2, 3, 0], [2, 5, 0], [4, 5, 0], [2, 3, 0]], [[3, 4, 0], [3, 6, 0], [5, 6, 0], [3, 4, 0]]], [[[1, 2, 0], [3, 2, 0], [3, 4, 0], [1, 2, 0]]]]); + format = new ol.format.GML({srsName: 'CRS:84', surface: true}); + var serialized = format.writeGeometry(g); + expect(serialized.firstElementChild).to.xmleql(ol.xml.load(text)); }); }); @@ -632,15 +679,25 @@ describe('ol.format.GML', function() { describe('when parsing TOPP states GML', function() { - var features; + var features, text, gmlFormat; before(function(done) { afterLoadText('spec/ol/format/gml/topp-states-gml.xml', function(xml) { try { + var schemaLoc = 'http://www.openplans.org/topp ' + + 'http://demo.opengeo.org/geoserver/wfs?service=WFS&version=' + + '1.1.0&request=DescribeFeatureType&typeName=topp:states ' + + 'http://www.opengis.net/gml ' + + 'http://schemas.opengis.net/gml/3.2.1/gml.xsd'; var config = { 'featureNS': 'http://www.openplans.org/topp', - 'featureType': 'states' + 'featureType': 'states', + 'multiSurface': true, + 'srsName': 'urn:x-ogc:def:crs:EPSG:4326', + 'schemaLocation': schemaLoc }; - features = new ol.format.GML(config).readFeatures(xml); + text = xml; + gmlFormat = new ol.format.GML(config); + features = gmlFormat.readFeatures(xml); } catch (e) { done(e); } @@ -656,6 +713,11 @@ describe('ol.format.GML', function() { expect(features[0].getId()).to.equal('states.1'); }); + it('writes back features as GML', function() { + var serialized = gmlFormat.writeFeatures(features); + expect(serialized).to.xmleql(ol.xml.load(text)); + }); + }); describe('when parsing TOPP states GML from WFS', function() { @@ -747,6 +809,7 @@ goog.require('goog.dom'); goog.require('goog.dom.TagName'); goog.require('ol.format.GML'); goog.require('ol.geom.LineString'); +goog.require('ol.geom.LinearRing'); goog.require('ol.geom.MultiPoint'); goog.require('ol.geom.MultiLineString'); goog.require('ol.geom.MultiPolygon');