diff --git a/src/ol/format/gml/gmlbase.js b/src/ol/format/gml/gmlbase.js index 5133badd8c..1e1e9dcfc7 100644 --- a/src/ol/format/gml/gmlbase.js +++ b/src/ol/format/gml/gmlbase.js @@ -100,8 +100,8 @@ ol.format.GMLBase.prototype.readFeatures_ = function(node, objectStack) { var parsers = {}; var parsersNS = {}; parsers[featureType] = (localName == 'featureMembers') ? - ol.xml.makeArrayPusher(this.readFeature_, this) : - ol.xml.makeReplacer(this.readFeature_, this); + ol.xml.makeArrayPusher(this.readFeatureElement, this) : + ol.xml.makeReplacer(this.readFeatureElement, this); parsersNS[goog.object.get(context, 'featureNS')] = parsers; features = ol.xml.pushParseAndPop([], parsersNS, node, objectStack); } @@ -150,9 +150,8 @@ ol.format.GMLBase.prototype.readGeometryElement = function(node, objectStack) { * @param {Node} node Node. * @param {Array.<*>} objectStack Object stack. * @return {ol.Feature} Feature. - * @private */ -ol.format.GMLBase.prototype.readFeature_ = function(node, objectStack) { +ol.format.GMLBase.prototype.readFeatureElement = function(node, objectStack) { var n; var fid = node.getAttribute('fid') || ol.xml.getAttributeNS(node, 'http://www.opengis.net/gml', 'id'); diff --git a/src/ol/format/wmsgetfeatureinfoformat.js b/src/ol/format/wmsgetfeatureinfoformat.js new file mode 100644 index 0000000000..0d928189e4 --- /dev/null +++ b/src/ol/format/wmsgetfeatureinfoformat.js @@ -0,0 +1,146 @@ +goog.provide('ol.format.WMSGetFeatureInfo'); + +goog.require('goog.array'); +goog.require('goog.asserts'); +goog.require('goog.dom'); +goog.require('goog.dom.NodeType'); +goog.require('goog.object'); +goog.require('goog.string'); +goog.require('ol.format.GML'); +goog.require('ol.format.GML2'); +goog.require('ol.format.XMLFeature'); +goog.require('ol.xml'); + + + +/** + * @classdesc + * Format for reading WMSGetFeatureInfo format. It uses + * {@link ol.format.GML2} to read features. + * + * @constructor + * @extends {ol.format.XMLFeature} + * @api + */ +ol.format.WMSGetFeatureInfo = function() { + + /** + * @private + * @type {string} + */ + this.featureNS_ = 'http://mapserver.gis.umn.edu/mapserver'; + + + /** + * @private + * @type {ol.format.GML2} + */ + this.gmlFormat_ = new ol.format.GML2(); + + goog.base(this); +}; +goog.inherits(ol.format.WMSGetFeatureInfo, ol.format.XMLFeature); + + +/** + * @const + * @type {string} + * @private + */ +ol.format.WMSGetFeatureInfo.featureIdentifier_ = '_feature'; + + +/** + * @const + * @type {string} + * @private + */ +ol.format.WMSGetFeatureInfo.layerIdentifier_ = '_layer'; + + +/** + * @param {Node} node Node. + * @param {Array.<*>} objectStack Object stack. + * @return {Array.} Features. + * @private + */ +ol.format.WMSGetFeatureInfo.prototype.readFeatures_ = + function(node, objectStack) { + + node.namespaceURI = this.featureNS_; + goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT); + var localName = ol.xml.getLocalName(node); + /** @type {Array.} */ + var features = []; + if (node.childNodes.length === 0) { + return features; + } + if (localName == 'msGMLOutput') { + goog.array.forEach(node.childNodes, function(layer) { + if (layer.nodeType !== goog.dom.NodeType.ELEMENT) { + return; + } + var context = objectStack[0]; + goog.asserts.assert(goog.isObject(context)); + + goog.asserts.assert(layer.localName.indexOf( + ol.format.WMSGetFeatureInfo.layerIdentifier_) >= 0); + + var featureType = goog.string.remove(layer.localName, + ol.format.WMSGetFeatureInfo.layerIdentifier_) + + ol.format.WMSGetFeatureInfo.featureIdentifier_; + + goog.object.set(context, 'featureType', featureType); + goog.object.set(context, 'featureNS', this.featureNS_); + + var parsers = {}; + parsers[featureType] = ol.xml.makeArrayPusher( + this.gmlFormat_.readFeatureElement, this.gmlFormat_); + var parsersNS = ol.xml.makeParsersNS( + [goog.object.get(context, 'featureNS'), null], parsers); + layer.namespaceURI = this.featureNS_; + var layerFeatures = ol.xml.pushParseAndPop( + [], parsersNS, layer, objectStack, this.gmlFormat_); + if (goog.isDef(layerFeatures)) { + goog.array.extend(features, layerFeatures); + } + }, this); + } + if (localName == 'FeatureCollection') { + var gmlFeatures = ol.xml.pushParseAndPop([], + this.gmlFormat_.FEATURE_COLLECTION_PARSERS, node, + [{}], this.gmlFormat_); + if (goog.isDef(gmlFeatures)) { + features = gmlFeatures; + } + } + return features; +}; + + +/** + * Read all features from a WMSGetFeatureInfo response. + * + * @function + * @param {ArrayBuffer|Document|Node|Object|string} source Source. + * @param {olx.format.ReadOptions=} opt_options Options. + * @return {Array.} Features. + * @api stable + */ +ol.format.WMSGetFeatureInfo.prototype.readFeatures; + + +/** + * @inheritDoc + */ +ol.format.WMSGetFeatureInfo.prototype.readFeaturesFromNode = + function(node, opt_options) { + var options = { + 'featureType': this.featureType, + 'featureNS': this.featureNS + }; + if (goog.isDef(opt_options)) { + goog.object.extend(options, this.getReadOptions(node, opt_options)); + } + return this.readFeatures_(node, [options]); +}; diff --git a/test/spec/ol/format/wms/getfeatureinfo.xml b/test/spec/ol/format/wms/getfeatureinfo.xml new file mode 100644 index 0000000000..f00c6c4f93 --- /dev/null +++ b/test/spec/ol/format/wms/getfeatureinfo.xml @@ -0,0 +1,45 @@ + + + + ADCP de coque 2001 + + + + -531138.686422,5386348.414671 -117252.819653,6144475.186022 + + + 1071 + 1020050 + ITSAS II + http://www.ifremer.fr/sismerData/jsp/visualisationMetadata2.jsp?strPortail=ifremer&langue=FR&pageOrigine=CAM&cle1=FI352001020050 + ITSASII_BB150_0_osite.nc + http://www.ifremer.fr/sismerData/jsp/visualisationMetadata3.jsp?strPortail=ifremer&langue=FR&pageOrigine=CS&cle1=71053_1&cle2=ADCP01 + + + + + -531138.686422,5386348.414671 -117252.819653,6144475.186022 + + + 22431 + 1020050 + ITSAS II + http://www.ifremer.fr/sismerData/jsp/visualisationMetadata2.jsp?strPortail=ifremer&langue=FR&pageOrigine=CAM&cle1=FI352001020050 + ITSASII_BB150_figures.tar + http://www.ifremer.fr/sismerData/jsp/visualisationMetadata3.jsp?strPortail=ifremer&langue=FR&pageOrigine=CS&cle1=108842_2&cle2=ADCP01 + + + + + -531138.686422,5386348.414671 -117252.819653,6144475.186022 + + + 22432 + 1020050 + ITSAS II + http://www.ifremer.fr/sismerData/jsp/visualisationMetadata2.jsp?strPortail=ifremer&langue=FR&pageOrigine=CAM&cle1=FI352001020050 + ITSASII_BB150_0_fhv12.nc + http://www.ifremer.fr/sismerData/jsp/visualisationMetadata3.jsp?strPortail=ifremer&langue=FR&pageOrigine=CS&cle1=108842_3&cle2=ADCP01 + + + diff --git a/test/spec/ol/format/wmsgetfeatureinfoformat.test.js b/test/spec/ol/format/wmsgetfeatureinfoformat.test.js new file mode 100644 index 0000000000..aff68e2dc0 --- /dev/null +++ b/test/spec/ol/format/wmsgetfeatureinfoformat.test.js @@ -0,0 +1,207 @@ +goog.provide('ol.test.format.WMSGetFeatureInfo'); + +describe('ol.format.WMSGetFeatureInfo', function() { + + describe('#readFormat', function() { + + describe('read Features', function() { + + var features; + + before(function(done) { + proj4.defs('urn:x-ogc:def:crs:EPSG:4326', proj4.defs('EPSG:4326')); + afterLoadText('spec/ol/format/wms/getfeatureinfo.xml', function(data) { + try { + features = new ol.format.WMSGetFeatureInfo().readFeatures(data); + } catch (e) { + done(e); + } + done(); + }); + }); + + after(function() { + proj4.defs('urn:x-ogc:def:crs:EPSG:4326', undefined); + }); + + it('creates 3 features', function() { + expect(features).to.have.length(3); + }); + + it('creates a feature for 1071', function() { + var feature = features[0]; + expect(feature.getId()).to.be(undefined); + expect(feature.get('FID')).to.equal('1071'); + expect(feature.get('NO_CAMPAGNE')).to.equal('1020050'); + }); + + it('read boundedBy but no geometry', function() { + var feature = features[0]; + expect(feature.getGeometry()).to.be(undefined); + expect(feature.get('boundedBy')).to.eql( + [-531138.686422, 5386348.414671, -117252.819653, 6144475.186022]); + }); + + it('read empty response', function() { + // read empty response + var text = '' + + '' + + ' ' + + ' ' + + ''; + var features = new ol.format.WMSGetFeatureInfo().readFeatures(text); + expect(features.length).to.be(0); + }); + + it('read empty attributes', function() { + text = + '' + + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' 107397.266000,460681.063000 116568.188000,480609.250000' + + ' ' + + ' ' + + ' ' + + ' bar' + + ' ' + + ' ' + + ' ' + + ''; + var features = new ol.format.WMSGetFeatureInfo().readFeatures(text); + expect(features.length).to.be(1); + expect(features[0].get('FOO')).to.be('bar'); + // FIXME is that really wanted ? + expect(features[0].get('EMPTY')).to.be(undefined); + }); + + it('read features from multiple layers', function() { + text = + '' + + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' 129799.109000,467950.250000 133199.906000,468904.063000' + + ' ' + + ' ' + + ' ' + + ' 287' + + ' N403' + + ' #N403' + + ' 1' + + ' P' + + ' 4091.25' + + ' <shape>' + + ' <null>' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' 129936.000000,468362.000000 131686.000000,473119.000000' + + ' ' + + ' ' + + ' ' + + ' 1251' + + ' 1515' + + ' 00:00:00 01/01/1998' + + ' 1472' + + ' 1309' + + ' D' + + ' 227' + + ' Vecht' + + ' 2' + + ' Vecht' + + ' 18.25' + + ' 23.995' + + ' 5745.09' + + ' <shape>' + + ' <null>' + + ' ' + + ' ' + + ''; + var features = new ol.format.WMSGetFeatureInfo().readFeatures(text); + expect(features.length).to.be(2); + expect(features[0].get('OBJECTID')).to.be('287'); + expect(features[1].get('OBJECTID')).to.be('1251'); + }); + + it('read geoserver’s response', function() { + text = + '' + + '' + + ' ' + + ' ' + + ' ' + + '591943.9375,4925605 593045.625,4925845' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' 3' + + ' secondary highway, hard surface' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + '593045.60746465,4925605.0059156 593024.32382915,4925606.79305411' + + ' 592907.54863574,4925624.85647524 592687.35111096,' + + '4925670.76834012 592430.76279218,4925678.79393165' + + ' 592285.97636109,4925715.70811767 592173.39165655,' + + '4925761.83511156 592071.1753393,4925793.95523514' + + ' 591985.96972625,4925831.59842486' + + ' 591943.98769455,4925844.93220071' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ''; + var features = new ol.format.WMSGetFeatureInfo().readFeatures(text); + expect(features.length).to.be(1); + expect(features[0].get('cat')).to.be('3'); + expect(features[0].getGeometry().getType()).to.be('MultiLineString'); + }); + + }); + }); +}); + + +goog.require('goog.dom'); +goog.require('ol.format.WMSGetFeatureInfo');