diff --git a/src/ol/format/KML.js b/src/ol/format/KML.js index 8775ecf583..84c9165075 100644 --- a/src/ol/format/KML.js +++ b/src/ol/format/KML.js @@ -126,7 +126,7 @@ const PLACEMARK_PARSERS = makeStructureNS( 'name': makeObjectPropertySetter(readString), 'open': makeObjectPropertySetter(readBoolean), 'phoneNumber': makeObjectPropertySetter(readString), - 'styleUrl': makeObjectPropertySetter(readURI), + 'styleUrl': makeObjectPropertySetter(readStyleURL), 'visibility': makeObjectPropertySetter(readBoolean), }, makeStructureNS(GX_NAMESPACE_URIS, { @@ -1074,12 +1074,6 @@ function findStyle(styleValue, defaultStyle, sharedStyles) { if (Array.isArray(styleValue)) { return styleValue; } else if (typeof styleValue === 'string') { - // KML files in the wild occasionally forget the leading `#` on styleUrls - // defined in the same document. Add a leading `#` if it enables to find - // a style. - if (!(styleValue in sharedStyles) && '#' + styleValue in sharedStyles) { - styleValue = '#' + styleValue; - } return findStyle(sharedStyles[styleValue], defaultStyle, sharedStyles); } else { return defaultStyle; @@ -1151,6 +1145,28 @@ function readURI(node) { } } +/** + * @param {Node} node Node. + * @return {string} URI. + */ +function readStyleURL(node) { + // KML files in the wild occasionally forget the leading + // `#` on styleUrlsdefined in the same document. + const s = getAllTextContent(node, false) + .trim() + .replace(/^(?!.*#)/, '#'); + let baseURI = node.baseURI; + if (!baseURI || baseURI == 'about:blank') { + baseURI = window.location.href; + } + if (baseURI) { + const url = new URL(s, baseURI); + return url.href; + } else { + return s; + } +} + /** * @param {Element} node Node. * @return {Vec2} Vec2. @@ -2021,7 +2037,7 @@ function regionParser(node, objectStack) { const PAIR_PARSERS = makeStructureNS(NAMESPACE_URIS, { 'Style': makeObjectPropertySetter(readStyle), 'key': makeObjectPropertySetter(readString), - 'styleUrl': makeObjectPropertySetter(readURI), + 'styleUrl': makeObjectPropertySetter(readStyleURL), }); /** diff --git a/test/spec/ol/format/kml.test.js b/test/spec/ol/format/kml.test.js index 0fe434e3f6..b92db81e39 100644 --- a/test/spec/ol/format/kml.test.js +++ b/test/spec/ol/format/kml.test.js @@ -3477,6 +3477,41 @@ describe('ol.format.KML', function () { expect(s.getFill().getColor()).to.eql([120, 86, 52, 18 / 255]); }); + it('can use Styles in StyleMaps if # is missing', function () { + const text = + '' + + ' ' + + ' ' + + ' ' + + ' normal' + + ' foo' + + ' ' + + ' ' + + ' ' + + ' ' + + ' fooMap' + + ' ' + + ' ' + + ''; + const fs = format.readFeatures(text); + expect(fs).to.have.length(1); + const f = fs[0]; + expect(f).to.be.an(Feature); + const styleFunction = f.getStyleFunction(); + expect(styleFunction).not.to.be(undefined); + const styleArray = styleFunction(f, 0); + expect(styleArray).to.be.an(Array); + expect(styleArray).to.have.length(1); + const s = styleArray[0]; + expect(s).to.be.an(Style); + expect(s.getFill()).not.to.be(null); + expect(s.getFill().getColor()).to.eql([120, 86, 52, 18 / 255]); + }); + it('can use IconStyles in StyleMaps before they are defined (and set the crossOrigin option)', function () { format = new KML({crossOrigin: null}); const text =