diff --git a/externs/olx.js b/externs/olx.js index dc8bcce415..22c2c588f5 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -1679,7 +1679,7 @@ olx.format.KMLOptions.prototype.defaultStyle; /** - * @typedef {{featureNS: (string|undefined), + * @typedef {{featureNS: (Object.|string|undefined), * featureType: (Array.|string|undefined), * srsName: string, * surface: (boolean|undefined), @@ -1694,7 +1694,7 @@ olx.format.GMLOptions; /** * Feature namespace. If not defined will be derived from GML. - * @type {string|undefined} + * @type {Object.|string|undefined} * @api stable */ olx.format.GMLOptions.prototype.featureNS; @@ -1782,7 +1782,7 @@ olx.format.GPXOptions.prototype.readExtensions; /** - * @typedef {{featureNS: string, + * @typedef {{featureNS: (Object.|string|undefined), * featureType: (Array.|string|undefined), * gmlFormat: (ol.format.GMLBase|undefined), * schemaLocation: (string|undefined)}} @@ -1793,7 +1793,7 @@ olx.format.WFSOptions; /** * The namespace URI used for features. - * @type {string} + * @type {Object.|string|undefined} * @api stable */ olx.format.WFSOptions.prototype.featureNS; diff --git a/src/ol/format/gml/gmlbaseformat.js b/src/ol/format/gml/gmlbaseformat.js index 751f02f588..97333bf651 100644 --- a/src/ol/format/gml/gmlbaseformat.js +++ b/src/ol/format/gml/gmlbaseformat.js @@ -51,7 +51,7 @@ ol.format.GMLBase = function(opt_options) { /** * @protected - * @type {string|undefined} + * @type {Object.|string|undefined} */ this.featureNS = options.featureNS; @@ -107,33 +107,52 @@ ol.format.GMLBase.prototype.readFeaturesInternal = function(node, objectStack) { var context = objectStack[0]; goog.asserts.assert(goog.isObject(context)); var featureType = context['featureType']; - var i, ii, featureNS; + var featureNS = context['featureNS']; + var i, ii, prefix = 'p', defaultPrefix = 'p0'; if (!goog.isDef(featureType) && goog.isDefAndNotNull(node.childNodes)) { - featureType = []; + featureType = [], featureNS = {}; for (i = 0, ii = node.childNodes.length; i < ii; ++i) { var child = node.childNodes[i]; if (child.nodeType === 1) { var ft = child.nodeName.split(':').pop(); if (goog.array.indexOf(featureType, ft) === -1) { - featureType.push(ft); - if (!goog.isDef(featureNS)) { - featureNS = child.namespaceURI; + var key; + if (!goog.object.contains(featureNS, child.namespaceURI)) { + key = prefix + goog.object.getCount(featureNS); + featureNS[key] = child.namespaceURI; + } else { + key = goog.object.findKey(featureNS, function(value) { + return value === child.namespaceURI; + }); } + featureType.push(key + ':' + ft); } } } context['featureType'] = featureType; context['featureNS'] = featureNS; } - var parsers = {}; + if (goog.isString(featureNS)) { + var ns = featureNS; + featureNS = {}; + featureNS[defaultPrefix] = ns; + } var parsersNS = {}; var featureTypes = goog.isArray(featureType) ? featureType : [featureType]; - for (i = 0, ii = featureTypes.length; i < ii; ++i) { - parsers[featureTypes[i]] = (localName == 'featureMembers') ? - ol.xml.makeArrayPusher(this.readFeatureElement, this) : - ol.xml.makeReplacer(this.readFeatureElement, this); + for (var p in featureNS) { + var parsers = {}; + for (i = 0, ii = featureTypes.length; i < ii; ++i) { + var featurePrefix = featureTypes[i].indexOf(':') === -1 ? + defaultPrefix : featureTypes[i].split(':')[0]; + if (featurePrefix === p) { + parsers[featureTypes[i].split(':').pop()] = + (localName == 'featureMembers') ? + ol.xml.makeArrayPusher(this.readFeatureElement, this) : + ol.xml.makeReplacer(this.readFeatureElement, this); + } + } + parsersNS[featureNS[p]] = parsers; } - parsersNS[context['featureNS']] = parsers; features = ol.xml.pushParseAndPop([], parsersNS, node, objectStack); } if (!goog.isDef(features)) { diff --git a/src/ol/format/wfsformat.js b/src/ol/format/wfsformat.js index bc1b3394da..8bc16a317f 100644 --- a/src/ol/format/wfsformat.js +++ b/src/ol/format/wfsformat.js @@ -37,7 +37,7 @@ ol.format.WFS = function(opt_options) { /** * @private - * @type {string} + * @type {Object.|string|undefined} */ this.featureNS_ = options.featureNS; diff --git a/test/spec/ol/format/gml/multiple-typenames-ns.xml b/test/spec/ol/format/gml/multiple-typenames-ns.xml new file mode 100644 index 0000000000..e36469efcc --- /dev/null +++ b/test/spec/ol/format/gml/multiple-typenames-ns.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + 37.51099000000001 -88.071564 37.476273000000006 + -88.087883 37.442852 -88.311707 37.40930899999999 -88.359177 + 37.51099000000001 -88.071564 + + + + + + + Illinois + 17 + E N Cen + IL + 143986.61 + 1993.335 + 1.1430602E7 + 2924880.0 + 4202240.0 + 5552233.0 + 5878369.0 + 4199206.0 + 3741715.0 + 652603.0 + 538071.0 + 5417967.0 + 385040.0 + 1360159.0 + 828906.0 + 0.486 + 0.514 + 1747776.0 + + + + + + + 37.51099000000001 -88.071564 37.476273000000006 + -88.087883 37.442852 -88.311707 37.40930899999999 -88.359177 + 37.51099000000001 -88.071564 + + + + + 5 + unimproved road + + + diff --git a/test/spec/ol/format/gmlformat.test.js b/test/spec/ol/format/gmlformat.test.js index 45523a67b1..4a86a4f324 100644 --- a/test/spec/ol/format/gmlformat.test.js +++ b/test/spec/ol/format/gmlformat.test.js @@ -1150,6 +1150,54 @@ describe('ol.format.GML3', function() { }); + describe('when parsing multiple feature types / namespaces', function() { + + var features; + before(function(done) { + var url = 'spec/ol/format/gml/multiple-typenames-ns.xml'; + afterLoadText(url, function(xml) { + try { + features = new ol.format.GML({ + featureNS: { + 'topp': 'http://www.openplans.org/topp', + 'sf': 'http://www.openplans.org/spearfish' + }, + featureType: ['topp:states', 'sf:roads'] + }).readFeatures(xml); + } catch (e) { + done(e); + } + done(); + }); + }); + + it('reads all features', function() { + expect(features.length).to.be(2); + }); + + }); + + describe('when parsing multiple feature types / namespaces', function() { + + var features; + before(function(done) { + var url = 'spec/ol/format/gml/multiple-typenames-ns.xml'; + afterLoadText(url, function(xml) { + try { + features = new ol.format.GML().readFeatures(xml); + } catch (e) { + done(e); + } + done(); + }); + }); + + it('reads all features with autoconfigure', function() { + expect(features.length).to.be(2); + }); + + }); + });