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');