diff --git a/src/ol/format/KML.js b/src/ol/format/KML.js
index 46d4674911..8775ecf583 100644
--- a/src/ol/format/KML.js
+++ b/src/ol/format/KML.js
@@ -1117,7 +1117,8 @@ export function readFlatCoordinates(node) {
const flatCoordinates = [];
// The KML specification states that coordinate tuples should not include
// spaces, but we tolerate them.
- const re = /^\s*([+\-]?\d*\.?\d+(?:e[+\-]?\d+)?)\s*,\s*([+\-]?\d*\.?\d+(?:e[+\-]?\d+)?)(?:\s*,\s*([+\-]?\d*\.?\d+(?:e[+\-]?\d+)?))?\s*/i;
+ s = s.replace(/\s*,\s*/g, ',');
+ const re = /^\s*([+\-]?\d*\.?\d+(?:e[+\-]?\d+)?),([+\-]?\d*\.?\d+(?:e[+\-]?\d+)?)(?:\s+|,|$)(?:([+\-]?\d*\.?\d+(?:e[+\-]?\d+)?)(?:\s+|$))?\s*/i;
let m;
while ((m = re.exec(s))) {
const x = parseFloat(m[1]);
diff --git a/test/spec/ol/format/kml.test.js b/test/spec/ol/format/kml.test.js
index 8df3ea6e99..0fe434e3f6 100644
--- a/test/spec/ol/format/kml.test.js
+++ b/test/spec/ol/format/kml.test.js
@@ -468,6 +468,54 @@ describe('ol.format.KML', function () {
expect(g.get('altitudeMode')).to.be('absolute');
});
+ it('can read XY coordinates', function () {
+ const text =
+ '' +
+ ' ' +
+ ' ' +
+ ' 1,2 3,4' +
+ ' 0' +
+ ' 1' +
+ ' absolute' +
+ ' ' +
+ ' ' +
+ '';
+ const fs = format.readFeatures(text);
+ expect(fs).to.have.length(1);
+ const f = fs[0];
+ expect(f).to.be.an(Feature);
+ const g = f.getGeometry();
+ expect(g).to.be.an(LineString);
+ expect(g.getCoordinates()).to.eql([
+ [1, 2, 0],
+ [3, 4, 0],
+ ]);
+ });
+
+ it('can read empty Z coordinates', function () {
+ const text =
+ '' +
+ ' ' +
+ ' ' +
+ ' 1,2, 3,4,' +
+ ' 0' +
+ ' 1' +
+ ' absolute' +
+ ' ' +
+ ' ' +
+ '';
+ const fs = format.readFeatures(text);
+ expect(fs).to.have.length(1);
+ const f = fs[0];
+ expect(f).to.be.an(Feature);
+ const g = f.getGeometry();
+ expect(g).to.be.an(LineString);
+ expect(g.getCoordinates()).to.eql([
+ [1, 2, 0],
+ [3, 4, 0],
+ ]);
+ });
+
it('can write XY LineString geometries', function () {
const layout = 'XY';
const lineString = new LineString(