From 9b4fc06a5b411932a4f9ca48cecb43f9ae6e7d38 Mon Sep 17 00:00:00 2001 From: Bart van den Eijnden Date: Mon, 3 Mar 2014 14:01:07 +0100 Subject: [PATCH] Finish write support for features --- src/objectliterals.jsdoc | 2 + src/ol/format/gmlformat.js | 55 +++++++++++++++------------ test/spec/ol/format/gmlformat.test.js | 27 +++++++++---- 3 files changed, 53 insertions(+), 31 deletions(-) diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc index 4342676075..19ef7ded72 100644 --- a/src/objectliterals.jsdoc +++ b/src/objectliterals.jsdoc @@ -321,6 +321,8 @@ * @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 3ec268dca3..a3857bd141 100644 --- a/src/ol/format/gmlformat.js +++ b/src/ol/format/gmlformat.js @@ -80,6 +80,15 @@ ol.format.GML = function(opt_options) { this.multiSurface_ = goog.isDef(options.multiSurface) ? options.multiSurface : true; + /** + * @private + * @type {string} + */ + this.schemaLocation_ = goog.isDef(options.schemaLocation) ? + options.schemaLocation : ('http://www.opengis.net/gml ' + + 'http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/' + + '1.0.0/gmlsf.xsd'); + goog.base(this); }; goog.inherits(ol.format.GML, ol.format.XMLFeature); @@ -1472,8 +1481,12 @@ ol.format.GML.writeCurveSegments_ = function(node, line, objectStack) { * @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); + goog.object.set(item, 'node', node); ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ - ({node: node}), ol.format.GML.GEOMETRY_SERIALIZERS_, + (item), ol.format.GML.GEOMETRY_SERIALIZERS_, ol.format.GML.GEOMETRY_NODE_FACTORY_, [geometry], []); }; @@ -1485,6 +1498,10 @@ ol.format.GML.writeGeometry_ = function(node, geometry, objectStack) { * @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'); @@ -1504,8 +1521,10 @@ ol.format.GML.writeFeature_ = function(node, feature, objectStack) { ol.format.XSD.writeStringTextNode); } } + var item = goog.object.clone(context); + goog.object.set(item, 'node', node); ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ - ({node: node}), serializers, + (item), serializers, ol.xml.OBJECT_PROPERTY_NODE_FACTORY, values, objectStack, keys); @@ -1523,13 +1542,14 @@ ol.format.GML.writeFeatureMembers_ = function(node, features, objectStack) { goog.asserts.assert(goog.isObject(context)); var featureType = goog.object.get(context, 'featureType'); var featureNS = goog.object.get(context, 'featureNS'); - //featureNS = 'http://www.opengis.net/gml'; var serializers = {}; serializers[featureNS] = {}; serializers[featureNS][featureType] = ol.xml.makeChildAppender( ol.format.GML.writeFeature_); + var item = goog.object.clone(context); + goog.object.set(item, 'node', node); ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ - ({node: node, featureType: featureType, featureNS: featureNS}), + (item), serializers, ol.xml.makeSimpleNodeFactory(featureType, featureNS), features, []); }; @@ -1653,18 +1673,6 @@ ol.format.GML.GEOMETRY_SERIALIZERS_ = { }; -/** - * @type {Object.>} - * @private - */ -ol.format.GML.GML_SERIALIZERS_ = { - 'http://www.opengis.net/gml': { - 'featureMembers': ol.xml.makeChildAppender( - ol.format.GML.writeFeatureMembers_) - } -}; - - /** * @const * @param {*} value Value. @@ -1718,10 +1726,12 @@ ol.format.GML.prototype.writeGeometryNode = function(geometry) { * @inheritDoc */ ol.format.GML.prototype.writeFeaturesNode = function(features) { - var collection = ol.xml.createElementNS('http://www.opengis.net/wfs', - 'FeatureCollection'); + 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 = { - node: collection, + node: node, srsName: this.srsName_, curve: this.curve_, surface: this.surface_, @@ -1730,9 +1740,6 @@ ol.format.GML.prototype.writeFeaturesNode = function(features) { featureNS: this.featureNS_, featureType: this.featureType_ }; - ol.xml.pushSerializeAndPop(/** @type {ol.xml.NodeStackItem} */ - (context), ol.format.GML.GML_SERIALIZERS_, - ol.xml.makeSimpleNodeFactory('featureMembers', - 'http://www.opengis.net/gml'), [features], []); - return collection; + ol.format.GML.writeFeatureMembers_(node, features, [context]); + return node; }; diff --git a/test/spec/ol/format/gmlformat.test.js b/test/spec/ol/format/gmlformat.test.js index 334cdefb0f..93a075b19b 100644 --- a/test/spec/ol/format/gmlformat.test.js +++ b/test/spec/ol/format/gmlformat.test.js @@ -678,15 +678,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); } @@ -702,11 +712,16 @@ 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() { - var features, feature, text, wfsFormat; + var features, feature; before(function(done) { afterLoadText('spec/ol/format/gml/topp-states-wfs.xml', function(xml) { try { @@ -714,9 +729,7 @@ describe('ol.format.GML', function() { 'featureNS': 'http://www.openplans.org/topp', 'featureType': 'states' }; - text = xml; - wfsFormat = new ol.format.GML(config); - features = wfsFormat.readFeatures(xml); + features = new ol.format.GML(config).readFeatures(xml); } catch (e) { done(e); }