diff --git a/src/ol/format/GMLBase.js b/src/ol/format/GMLBase.js index c85107bca3..98c8c8d0c7 100644 --- a/src/ol/format/GMLBase.js +++ b/src/ol/format/GMLBase.js @@ -236,42 +236,77 @@ class GMLBase extends XMLFeature { /** * @param {Element} node Node. * @param {Array<*>} objectStack Object stack. - * @return {Feature} Feature. + * @param {boolean} asFeature whether result should be wrapped as a feature. + * @return {module:ol/Feature} Feature */ - readFeatureElement(node, objectStack) { - let n; - const fid = node.getAttribute('fid') || getAttributeNS(node, GMLNS, 'id'); - const values = {}; + readFeatureElementInternal(node, objectStack, asFeature) { let geometryName; - for (n = node.firstElementChild; n; n = n.nextElementSibling) { + const values = {}; + for (let n = node.firstElementChild; n; n = n.nextElementSibling) { + let value; const localName = n.localName; - // Assume attribute elements have one child node and that the child - // is a text or CDATA node (to be treated as text). - // Otherwise assume it is a geometry node. - if (n.childNodes.length === 0 || - (n.childNodes.length === 1 && - (n.firstChild.nodeType === 3 || n.firstChild.nodeType === 4))) { - let value = getAllTextContent(n, false); + // first, check if it is simple attribute + if (n.childNodes.length === 0 + || (n.childNodes.length === 1 && (n.firstChild.nodeType === 3 || n.firstChild.nodeType === 4))) { + value = getAllTextContent(n, false); if (ONLY_WHITESPACE_RE.test(value)) { value = undefined; } - values[localName] = value; } else { - // boundedBy is an extent and must not be considered as a geometry - if (localName !== 'boundedBy') { + if (asFeature) { + //if feature, try it as a geometry + value = this.readGeometryElement(n, objectStack); + } + if (!value) { //if not a geometry or not a feature, treat it as a complex attribute + value = this.readFeatureElementInternal(n, objectStack, false); + } else if (localName !== 'boundedBy') { + // boundedBy is an extent and must not be considered as a geometry geometryName = localName; } - values[localName] = this.readGeometryElement(n, objectStack); + } + + if (values[localName]) { + if (!(values[localName] instanceof Array)) { + values[localName] = [values[localName]]; + } + values[localName].push(value); + } else { + values[localName] = value; + } + + const len = n.attributes.length; + if (len > 0) { + values[localName] = {_content_: values[localName]}; + for (let i = 0; i < len; i++) { + const attName = n.attributes[i].name; + values[localName][attName] = n.attributes[i].value; + } } } - const feature = new Feature(values); - if (geometryName) { - feature.setGeometryName(geometryName); + if (!asFeature) { + return values; + } else { + const feature = new Feature(values); + if (geometryName) { + feature.setGeometryName(geometryName); + } + const fid = node.getAttribute('fid') || + getAttributeNS(node, this.namespace, 'id'); + if (fid) { + feature.setId(fid); + } + return feature; } - if (fid) { - feature.setId(fid); - } - return feature; + } + + + /** + * @param {Node} node Node. + * @param {Array.<*>} objectStack Object stack. + * @return {module:ol/Feature} Feature. + */ + readFeatureElement(node, objectStack) { + return this.readFeatureElementInternal(node, objectStack, true); } /** diff --git a/test/spec/ol/format/gml.test.js b/test/spec/ol/format/gml.test.js index d0355c6f6e..7ce96081b1 100644 --- a/test/spec/ol/format/gml.test.js +++ b/test/spec/ol/format/gml.test.js @@ -1601,6 +1601,41 @@ describe('ol.format.GML3', function() { }); + describe('when parsing complex', function() { + + let features, gmlFormat; + before(function(done) { + afterLoadText('spec/ol/format/gml/gml-complex.xml', function(xml) { + try { + gmlFormat = new GML(); + features = gmlFormat.readFeatures(xml); + } catch (e) { + done(e); + } + done(); + }); + }); + + it('creates 3 features', function() { + expect(features).to.have.length(3); + }); + + it('creates feature with two names', function() { + expect(features[0].values_['name']).to.have.length(2); + }); + + it('creates nested property', function() { + expect(features[0].values_['observationMethod']['CGI_TermValue']['value']['_content_']) + .to.eql('urn:ogc:def:nil:OGC:missing'); + }); + + it('creates nested attribute', function() { + expect(features[0].values_['observationMethod']['CGI_TermValue']['value']['codeSpace']) + .to.eql('urn:ietf:rfc:2141'); + }); + + }); + }); diff --git a/test/spec/ol/format/gml/gml-complex.xml b/test/spec/ol/format/gml/gml-complex.xml new file mode 100644 index 0000000000..9db7b6f937 --- /dev/null +++ b/test/spec/ol/format/gml/gml-complex.xml @@ -0,0 +1,120 @@ + + + + + Some basalt + urn:x-test:GeologicUnit:16777549126931093 + + + urn:ogc:def:nil:OGC:missing + + + + + urn:ogc:def:nil:OGC:missing + + + + + + + + 1610340.1935838535 4284512.166074015 + 1610314.9870748299 4284503.122122704 1610322.4187882338 + 4284519.894649132 1610316.759094497 4284523.101981014 + 1610321.0122971204 4284531.491206108 1610318.0495807002 + 4284532.8242770685 1610319.6410451748 4284536.6111539425 + 1610319.099298857 4284537.417781517 1610321.247194622 + 4284537.699439952 1610317.932103093 4284554.413021458 + 1610326.2462194602 4284557.157338472 1610328.402928607 + 4284555.819838275 1610343.9490912845 4284513.26614925 + 1610340.1935838535 4284512.166074015 + + + + + + + + + More basalt + urn:x-test:GeologicUnit:16777549126931093 + + + urn:ogc:def:nil:OGC:missing + + + + + urn:ogc:def:nil:OGC:missing + + + + + + + + 1610718.9221517597 4284805.42784805 + 1610707.3895121815 4284814.000918856 1610690.0555121175 + 4284839.544424725 1610688.6493659448 4284851.141369273 + 1610698.3130323582 4284852.813339175 1610705.8316511428 + 4284853.6639760295 1610706.7412747787 4284834.507828795 + 1610734.9743371184 4284830.61366508 1610750.0961105193 + 4284816.66263084 1610763.83073235 4284810.800250375 + 1610756.6916036862 4284789.441324945 1610725.3908253086 + 4284801.684887575 1610730.1263850513 4284820.332010645 + 1610726.08892804 4284821.659368354 1610723.710210181 + 4284814.359796638 1610718.9221517597 4284805.42784805 + + + + + + + + + + Some mudstone + urn:x-test:GeologicUnit:16777549126931077 + + + urn:ogc:def:nil:OGC:missing + + + + + urn:ogc:def:nil:OGC:missing + + + + + + + + 1610399.8069898037 4284790.189299587 + 1610398.8760062372 4284763.736632759 1610381.1448500715 + 4284763.369532419 1610380.8659049459 4284765.257112044 + 1610366.8844742253 4284767.069534708 1610366.554168919 + 4284778.402387972 1610363.857132307 4284780.276704736 + 1610358.2706932572 4284769.990881423 1610363.6662297642 + 4284765.9723890135 1610352.2305719855 4284744.319844696 + 1610332.5497155024 4284756.625971695 1610332.5306289664 + 4284760.134211061 1610339.4369314983 4284774.745249511 + 1610350.0724354137 4284795.313982406 1610366.7215974482 + 4284797.024567371 1610374.5176296765 4284796.257709886 + 1610399.8069898037 4284790.189299587 + + + + + + + \ No newline at end of file