diff --git a/examples/data/countries.sld b/examples/data/countries.sld new file mode 100644 index 0000000000..79fb36d465 --- /dev/null +++ b/examples/data/countries.sld @@ -0,0 +1,42 @@ + + + + countries + + countries + A sample style for countries + 1 + A sample style for countries + + name + + Sample + Sample + + + #ff0000 + 0.6 + + + #00FF00 + 0.5 + 4 + + + + + + + name + + + Arial + 10 + Normal + + + + + + + diff --git a/examples/vector-layer-sld.html b/examples/vector-layer-sld.html new file mode 100644 index 0000000000..52b9b0e80d --- /dev/null +++ b/examples/vector-layer-sld.html @@ -0,0 +1,61 @@ + + + + + + + + + + + Vector layer with styling from SLD example + + + + + +
+ +
+
+
+
+
+ +
+ +
+

Vector layer example

+

Example of a countries vector layer with country information on hover and country labels at higher zoom levels.

+
+

See the vector-layer-sld.js source to see how this is done.

+
+
vector, geojson, style, SLD, Styled Layer Descriptor
+
+
+
+   +
+
+ +
+ +
+ + + + + + diff --git a/examples/vector-layer-sld.js b/examples/vector-layer-sld.js new file mode 100644 index 0000000000..aa8f9f5563 --- /dev/null +++ b/examples/vector-layer-sld.js @@ -0,0 +1,45 @@ +goog.require('ol.Map'); +goog.require('ol.RendererHint'); +goog.require('ol.View2D'); +goog.require('ol.layer.Tile'); +goog.require('ol.layer.Vector'); +goog.require('ol.parser.GeoJSON'); +goog.require('ol.parser.ogc.SLD'); +goog.require('ol.source.MapQuestOpenAerial'); +goog.require('ol.source.Vector'); + + +var raster = new ol.layer.Tile({ + source: new ol.source.MapQuestOpenAerial() +}); + +var xhr = new XMLHttpRequest(); +xhr.open('GET', 'data/countries.sld', true); + + +/** + * onload handler for the XHR request. + */ +xhr.onload = function() { + if (xhr.status == 200) { + var sld = new ol.parser.ogc.SLD().read(xhr.responseText); + var style = sld.namedLayers['countries'].userStyles[0]; + var vector = new ol.layer.Vector({ + source: new ol.source.Vector({ + parser: new ol.parser.GeoJSON(), + url: 'data/countries.geojson' + }), + style: style + }); + new ol.Map({ + layers: [raster, vector], + renderer: ol.RendererHint.CANVAS, + target: 'map', + view: new ol.View2D({ + center: [0, 0], + zoom: 1 + }) + }); + } +}; +xhr.send(); diff --git a/src/ol/parser/ogc/sldparser.js b/src/ol/parser/ogc/sldparser.js new file mode 100644 index 0000000000..8560cdc2e8 --- /dev/null +++ b/src/ol/parser/ogc/sldparser.js @@ -0,0 +1,38 @@ +goog.provide('ol.parser.ogc.SLD'); +goog.require('ol.parser.ogc.SLD_v1_0_0'); +goog.require('ol.parser.ogc.SLD_v1_0_0_GeoServer'); +goog.require('ol.parser.ogc.Versioned'); + + +/** + * @define {boolean} Whether to enable SLD version 1.0.0. + */ +ol.ENABLE_SLD_1_0_0 = true; + + +/** + * @define {boolean} Whether to enable SLD version 1.0.0. + * GeoServer profile. + */ +ol.ENABLE_SLD_1_0_0_GEOSERVER = true; + + + +/** + * @constructor + * @param {Object=} opt_options Options which will be set on this object. + * @extends {ol.parser.ogc.Versioned} + */ +ol.parser.ogc.SLD = function(opt_options) { + opt_options = opt_options || {}; + opt_options['defaultVersion'] = '1.0.0'; + this.parsers = {}; + if (ol.ENABLE_SLD_1_0_0) { + this.parsers['v1_0_0'] = ol.parser.ogc.SLD_v1_0_0; + } + if (ol.ENABLE_SLD_1_0_0_GEOSERVER) { + this.parsers['v1_0_0_GEOSERVER'] = ol.parser.ogc.SLD_v1_0_0_GeoServer; + } + goog.base(this, opt_options); +}; +goog.inherits(ol.parser.ogc.SLD, ol.parser.ogc.Versioned); diff --git a/src/ol/parser/ogc/sldparser_v1.js b/src/ol/parser/ogc/sldparser_v1.js new file mode 100644 index 0000000000..6917240dac --- /dev/null +++ b/src/ol/parser/ogc/sldparser_v1.js @@ -0,0 +1,429 @@ +goog.provide('ol.parser.ogc.SLD_v1'); +goog.require('goog.dom.xml'); +goog.require('goog.object'); +goog.require('ol.parser.XML'); +goog.require('ol.parser.ogc.Filter_v1_0_0'); +goog.require('ol.style.Fill'); +goog.require('ol.style.Rule'); +goog.require('ol.style.Shape'); +goog.require('ol.style.Stroke'); +goog.require('ol.style.Style'); +goog.require('ol.style.Text'); + + + +/** + * Read Styled Layer Descriptor (SLD). + * + * @constructor + * @extends {ol.parser.XML} + */ +ol.parser.ogc.SLD_v1 = function() { + this.defaultNamespaceURI = 'http://www.opengis.net/sld'; + this.readers = { + 'http://www.opengis.net/sld': { + 'StyledLayerDescriptor': function(node, sld) { + sld.version = node.getAttribute('version'); + this.readChildNodes(node, sld); + }, + 'Name': function(node, obj) { + obj.name = this.getChildValue(node); + }, + 'Title': function(node, obj) { + obj.title = this.getChildValue(node); + }, + 'Abstract': function(node, obj) { + obj.description = this.getChildValue(node); + }, + 'NamedLayer': function(node, sld) { + var layer = { + userStyles: [], + namedStyles: [] + }; + this.readChildNodes(node, layer); + sld.namedLayers[layer.name] = layer; + }, + 'NamedStyle': function(node, layer) { + layer.namedStyles.push( + this.getChildValue(node.firstChild) + ); + }, + 'UserStyle': function(node, layer) { + var obj = {rules: []}; + this.featureTypeCounter = -1; + this.readChildNodes(node, obj); + layer.userStyles.push(new ol.style.Style(obj)); + }, + 'IsDefault': function(node, style) { + if (this.getChildValue(node) === '1') { + style.isDefault = true; + } + }, + 'FeatureTypeStyle': function(node, style) { + ++this.featureTypeCounter; + var obj = { + rules: style.rules + }; + this.readChildNodes(node, obj); + }, + 'Rule': function(node, obj) { + var config = {symbolizers: []}; + this.readChildNodes(node, config); + var rule = new ol.style.Rule(config); + obj.rules.push(rule); + }, + 'ElseFilter': function(node, rule) { + rule.elseFilter = true; + }, + 'MinScaleDenominator': function(node, rule) { + rule.minScaleDenominator = parseFloat(this.getChildValue(node)); + }, + 'MaxScaleDenominator': function(node, rule) { + rule.maxScaleDenominator = parseFloat(this.getChildValue(node)); + }, + 'TextSymbolizer': function(node, rule) { + var config = {}; + this.readChildNodes(node, config); + config.zIndex = this.featureTypeCounter; + rule.symbolizers.push( + new ol.style.Text(/** @type {ol.style.TextOptions} */(config)) + ); + }, + 'LabelPlacement': function(node, symbolizer) { + this.readChildNodes(node, symbolizer); + }, + 'PointPlacement': function(node, symbolizer) { + var config = {}; + this.readChildNodes(node, config); + config.labelRotation = config.rotation; + delete config.rotation; + var labelAlign, + x = symbolizer.labelAnchorPointX, + y = symbolizer.labelAnchorPointY; + if (x <= 1 / 3) { + labelAlign = 'l'; + } else if (x > 1 / 3 && x < 2 / 3) { + labelAlign = 'c'; + } else if (x >= 2 / 3) { + labelAlign = 'r'; + } + if (y <= 1 / 3) { + labelAlign += 'b'; + } else if (y > 1 / 3 && y < 2 / 3) { + labelAlign += 'm'; + } else if (y >= 2 / 3) { + labelAlign += 't'; + } + config.labelAlign = labelAlign; + goog.object.extend(symbolizer, config); + }, + 'AnchorPoint': function(node, symbolizer) { + this.readChildNodes(node, symbolizer); + }, + 'AnchorPointX': function(node, symbolizer) { + var ogcreaders = this.readers['http://www.opengis.net/ogc']; + var labelAnchorPointX = ogcreaders._expression.call(this, node); + // always string, could be empty string + if (labelAnchorPointX) { + symbolizer.labelAnchorPointX = labelAnchorPointX; + } + }, + 'AnchorPointY': function(node, symbolizer) { + var ogcreaders = this.readers['http://www.opengis.net/ogc']; + var labelAnchorPointY = ogcreaders._expression.call(this, node); + // always string, could be empty string + if (labelAnchorPointY) { + symbolizer.labelAnchorPointY = labelAnchorPointY; + } + }, + 'Displacement': function(node, symbolizer) { + this.readChildNodes(node, symbolizer); + }, + 'DisplacementX': function(node, symbolizer) { + var ogcreaders = this.readers['http://www.opengis.net/ogc']; + var labelXOffset = ogcreaders._expression.call(this, node); + // always string, could be empty string + if (labelXOffset) { + symbolizer.labelXOffset = labelXOffset; + } + }, + 'DisplacementY': function(node, symbolizer) { + var ogcreaders = this.readers['http://www.opengis.net/ogc']; + var labelYOffset = ogcreaders._expression.call(this, node); + // always string, could be empty string + if (labelYOffset) { + symbolizer.labelYOffset = labelYOffset; + } + }, + 'LinePlacement': function(node, symbolizer) { + this.readChildNodes(node, symbolizer); + }, + 'PerpendicularOffset': function(node, symbolizer) { + var ogcreaders = this.readers['http://www.opengis.net/ogc']; + var labelPerpendicularOffset = ogcreaders._expression.call(this, node); + // always string, could be empty string + if (labelPerpendicularOffset) { + symbolizer.labelPerpendicularOffset = labelPerpendicularOffset; + } + }, + 'Label': function(node, symbolizer) { + var ogcreaders = this.readers['http://www.opengis.net/ogc']; + var value = ogcreaders._expression.call(this, node); + if (value) { + symbolizer.text = value; + } + }, + 'Font': function(node, symbolizer) { + this.readChildNodes(node, symbolizer); + }, + 'Halo': function(node, symbolizer) { + // halo has a fill, so send fresh object + var obj = {}; + this.readChildNodes(node, obj); + symbolizer.haloRadius = obj.haloRadius; + symbolizer.haloColor = obj['fillColor']; + symbolizer.haloOpacity = obj['fillOpacity']; + }, + 'Radius': function(node, symbolizer) { + var ogcreaders = this.readers['http://www.opengis.net/ogc']; + var radius = ogcreaders._expression.call(this, node); + if (goog.isDef(radius)) { + } + }, + 'RasterSymbolizer': function(node, rule) { + var config = {}; + this.readChildNodes(node, config); + config.zIndex = this.featureTypeCounter; + /* TODO + rule.symbolizers.push( + new OpenLayers.Symbolizer.Raster(config) + ); + */ + }, + 'Geometry': function(node, obj) { + obj.geometry = {}; + this.readChildNodes(node, obj.geometry); + }, + 'ColorMap': function(node, symbolizer) { + symbolizer.colorMap = []; + this.readChildNodes(node, symbolizer.colorMap); + }, + 'ColorMapEntry': function(node, colorMap) { + var q = node.getAttribute('quantity'); + var o = node.getAttribute('opacity'); + colorMap.push({ + color: node.getAttribute('color'), + quantity: q !== null ? parseFloat(q) : undefined, + label: node.getAttribute('label') || undefined, + opacity: o !== null ? parseFloat(o) : undefined + }); + }, + 'LineSymbolizer': function(node, rule) { + var config = {}; + this.readChildNodes(node, config); + config.zIndex = this.featureTypeCounter; + rule.symbolizers.push( + new ol.style.Stroke(config) + ); + }, + 'PolygonSymbolizer': function(node, rule) { + var config = { + fill: false, + stroke: false + }; + this.readChildNodes(node, config); + config.zIndex = this.featureTypeCounter; + if (config.fill === true) { + var fill = { + color: config['fillColor'], + opacity: config['fillOpacity'] + }; + rule.symbolizers.push( + new ol.style.Fill(fill) + ); + } + if (config.stroke === true) { + var stroke = { + color: config['strokeColor'], + opacity: config['strokeOpacity'], + width: config['strokeWidth'] + }; + rule.symbolizers.push( + new ol.style.Stroke(stroke) + ); + } + + }, + 'PointSymbolizer': function(node, rule) { + var config = { + fill: null, + stroke: null, + graphic: null + }; + this.readChildNodes(node, config); + config.zIndex = this.featureTypeCounter; + // TODO shape or icon? + rule.symbolizers.push( + new ol.style.Shape(config) + ); + }, + 'Stroke': function(node, symbolizer) { + symbolizer.stroke = true; + this.readChildNodes(node, symbolizer); + }, + 'Fill': function(node, symbolizer) { + symbolizer.fill = true; + this.readChildNodes(node, symbolizer); + }, + 'CssParameter': function(node, symbolizer) { + var cssProperty = node.getAttribute('name'); + var symProperty = ol.parser.ogc.SLD_v1.cssMap_[cssProperty]; + // for labels, fill should map to fontColor and fill-opacity + // to fontOpacity + if (symbolizer.label) { + if (cssProperty === 'fill') { + symProperty = 'fontColor'; + } else if (cssProperty === 'fill-opacity') { + symProperty = 'fontOpacity'; + } + } + if (symProperty) { + // Limited support for parsing of OGC expressions + var ogcreaders = this.readers['http://www.opengis.net/ogc']; + var value = ogcreaders._expression.call(this, node); + // always string, could be an empty string + if (value) { + symbolizer[symProperty] = value; + } + } + }, + 'Graphic': function(node, symbolizer) { + symbolizer.graphic = true; + var graphic = {}; + // painter's order not respected here, clobber previous with next + this.readChildNodes(node, graphic); + // directly properties with names that match symbolizer properties + var properties = [ + 'stroke', 'strokeColor', 'strokeWidth', 'strokeOpacity', + 'strokeLinecap', 'fill', 'fillColor', 'fillOpacity', + 'graphicName', 'rotation', 'graphicFormat' + ]; + var prop, value; + for (var i = 0, ii = properties.length; i < ii; ++i) { + prop = properties[i]; + value = graphic[prop]; + if (goog.isDef(value)) { + symbolizer[prop] = value; + } + } + // set other generic properties with specific graphic property names + if (goog.isDef(graphic.opacity)) { + symbolizer.graphicOpacity = graphic.opacity; + } + if (goog.isDef(graphic.size)) { + var pointRadius = graphic.size / 2; + if (isNaN(pointRadius)) { + // likely a property name + symbolizer.graphicWidth = graphic.size; + } else { + symbolizer.pointRadius = graphic.size / 2; + } + } + if (goog.isDef(graphic.href)) { + symbolizer.externalGraphic = graphic.href; + } + if (goog.isDef(graphic.rotation)) { + symbolizer.rotation = graphic.rotation; + } + }, + 'ExternalGraphic': function(node, graphic) { + this.readChildNodes(node, graphic); + }, + 'Mark': function(node, graphic) { + this.readChildNodes(node, graphic); + }, + 'WellKnownName': function(node, graphic) { + graphic.graphicName = this.getChildValue(node); + }, + 'Opacity': function(node, obj) { + var ogcreaders = this.readers['http://www.opengis.net/ogc']; + var opacity = ogcreaders._expression.call(this, node); + // always string, could be empty string + if (opacity) { + obj.opacity = opacity; + } + }, + 'Size': function(node, obj) { + var ogcreaders = this.readers['http://www.opengis.net/ogc']; + var size = ogcreaders._expression.call(this, node); + // always string, could be empty string + if (size) { + obj.size = size; + } + }, + 'Rotation': function(node, obj) { + var ogcreaders = this.readers['http://www.opengis.net/ogc']; + var rotation = ogcreaders._expression.call(this, node); + // always string, could be empty string + if (rotation) { + obj.rotation = rotation; + } + }, + 'OnlineResource': function(node, obj) { + obj.href = this.getAttributeNS( + node, 'http://www.w3.org/1999/xlink', 'href' + ); + }, + 'Format': function(node, graphic) { + graphic.graphicFormat = this.getChildValue(node); + } + } + }; + this.filter_ = new ol.parser.ogc.Filter_v1_0_0(); + for (var uri in this.filter_.readers) { + for (var key in this.filter_.readers[uri]) { + if (!goog.isDef(this.readers[uri])) { + this.readers[uri] = {}; + } + this.readers[uri][key] = goog.bind(this.filter_.readers[uri][key], + this.filter_); + } + } + goog.base(this); +}; +goog.inherits(ol.parser.ogc.SLD_v1, ol.parser.XML); + + +/** + * @private + */ +ol.parser.ogc.SLD_v1.cssMap_ = { + 'stroke': 'strokeColor', + 'stroke-opacity': 'strokeOpacity', + 'stroke-width': 'strokeWidth', + 'stroke-linecap': 'strokeLinecap', + 'stroke-dasharray': 'strokeDashstyle', + 'fill': 'fillColor', + 'fill-opacity': 'fillOpacity', + 'font-family': 'fontFamily', + 'font-size': 'fontSize', + 'font-weight': 'fontWeight', + 'font-style': 'fontStyle' +}; + + +/** + * @param {string|Document|Element} data Data to read. + * @return {Object} An object representing the document. + */ +ol.parser.ogc.SLD_v1.prototype.read = function(data) { + if (goog.isString(data)) { + data = goog.dom.xml.loadXml(data); + } + if (data && data.nodeType == 9) { + data = data.documentElement; + } + var obj = {namedLayers: {}}; + this.readNode(data, obj); + return obj; +}; diff --git a/src/ol/parser/ogc/sldparser_v1_0_0.js b/src/ol/parser/ogc/sldparser_v1_0_0.js new file mode 100644 index 0000000000..d86f897f6a --- /dev/null +++ b/src/ol/parser/ogc/sldparser_v1_0_0.js @@ -0,0 +1,18 @@ +goog.provide('ol.parser.ogc.SLD_v1_0_0'); + +goog.require('ol.parser.ogc.SLD_v1'); + + + +/** + * @constructor + * @extends {ol.parser.ogc.SLD_v1} + */ +ol.parser.ogc.SLD_v1_0_0 = function() { + goog.base(this); + this.version = '1.0.0'; + this.schemaLocation = 'http://www.opengis.net/sld ' + + 'http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd'; +}; +goog.inherits(ol.parser.ogc.SLD_v1_0_0, + ol.parser.ogc.SLD_v1); diff --git a/src/ol/parser/ogc/sldparser_v1_0_0_GeoServer.js b/src/ol/parser/ogc/sldparser_v1_0_0_GeoServer.js new file mode 100644 index 0000000000..77f58d1ab5 --- /dev/null +++ b/src/ol/parser/ogc/sldparser_v1_0_0_GeoServer.js @@ -0,0 +1,43 @@ +goog.provide('ol.parser.ogc.SLD_v1_0_0_GeoServer'); + +goog.require('goog.functions'); +goog.require('goog.object'); +goog.require('ol.parser.ogc.SLD_v1_0_0'); + + + +/** + * @constructor + * @extends {ol.parser.ogc.SLD_v1_0_0} + */ +ol.parser.ogc.SLD_v1_0_0_GeoServer = function() { + goog.base(this); + this.profile = 'GeoServer'; + goog.object.extend(this.readers['http://www.opengis.net/sld'], { + 'Priority': function(node, obj) { + var ogcreaders = this.readers['http://www.opengis.net/ogc']; + var value = ogcreaders._expression.call(this, node); + if (value) { + obj.priority = value; + } + }, + 'VendorOption': function(node, obj) { + if (!goog.isDef(obj.vendorOptions)) { + obj.vendorOptions = {}; + } + obj.vendorOptions[node.getAttribute('name')] = + this.getChildValue(node); + }, + 'TextSymbolizer': goog.functions.sequence( + this.readers['http://www.opengis.net/sld']['TextSymbolizer'], + function(node, rule) { + var symbolizer = rule.symbolizers[rule.symbolizers.length - 1]; + if (!goog.isDef(symbolizer.graphic)) { + symbolizer.graphic = false; + } + } + ) + }); +}; +goog.inherits(ol.parser.ogc.SLD_v1_0_0_GeoServer, + ol.parser.ogc.SLD_v1_0_0); diff --git a/test/spec/ol/parser/ogc/sld_v1_0_0.test.js b/test/spec/ol/parser/ogc/sld_v1_0_0.test.js new file mode 100644 index 0000000000..057d322062 --- /dev/null +++ b/test/spec/ol/parser/ogc/sld_v1_0_0.test.js @@ -0,0 +1,78 @@ +goog.provide('ol.test.parser.ogc.SLD_v1_0_0'); + + +describe('ol.parser.ogc.SLD_v1_0_0', function() { + + var parser = new ol.parser.ogc.SLD(); + + describe('reading and writing', function() { + it('Handles reading', function(done) { + var url = 'spec/ol/parser/ogc/xml/sld_v1_0_0.xml'; + afterLoadXml(url, function(xml) { + var obj = parser.read(xml); + expect(obj.version).to.equal('1.0.0'); + var style = obj.namedLayers['AAA161'].userStyles[0]; + expect(style).to.be.a(ol.style.Style); + expect(style.rules_.length).to.equal(2); + var first = style.rules_[0]; + expect(first).to.be.a(ol.style.Rule); + expect(first.filter_).to.be.a(ol.expr.Comparison); + expect(first.filter_.getLeft()).to.be.a(ol.expr.Identifier); + expect(first.filter_.getLeft().getName()).to.equal('CTE'); + expect(first.filter_.getOperator()).to.equal(ol.expr.ComparisonOp.EQ); + expect(first.filter_.getRight()).to.be.a(ol.expr.Literal); + expect(first.filter_.getRight().getValue()).to.equal('V0305'); + expect(first.getSymbolizers().length).to.equal(3); + expect(first.getSymbolizers()[0]).to.be.a(ol.style.Fill); + expect(first.getSymbolizers()[0].getColor().getValue()).to.equal( + '#ffffff'); + expect(first.getSymbolizers()[0].getOpacity().getValue()).to.equal(0.4); + expect(first.getSymbolizers()[1]).to.be.a(ol.style.Stroke); + expect(first.getSymbolizers()[1].getColor().getValue()).to.equal( + '#000000'); + expect(first.getSymbolizers()[2]).to.be.a(ol.style.Text); + expect(first.getSymbolizers()[2].getText()).to.be.a(ol.expr.Call); + expect(first.getSymbolizers()[2].getText().getArgs().length).to.equal( + 3); + expect(first.getSymbolizers()[2].getText().getArgs()[0]).to.be.a( + ol.expr.Literal); + expect(first.getSymbolizers()[2].getText().getArgs()[0].getValue()). + to.equal('A'); + expect(first.getSymbolizers()[2].getText().getArgs()[1]).to.be.a( + ol.expr.Identifier); + expect(first.getSymbolizers()[2].getText().getArgs()[1].getName()). + to.equal('FOO'); + expect(first.getSymbolizers()[2].getText().getArgs()[2]).to.be.a( + ol.expr.Literal); + expect(first.getSymbolizers()[2].getText().getArgs()[2].getValue()). + to.equal('label'); + expect(first.getSymbolizers()[2].getColor().getValue()).to.equal( + ol.style.TextDefaults.color); + expect(first.getSymbolizers()[2].getFontFamily().getValue()).to.equal( + 'Arial'); + // TODO add tests for haloRadius and haloColor + var second = style.rules_[1]; + expect(second.filter_).to.be.a(ol.expr.Comparison); + expect(second.getSymbolizers().length).to.equal(2); + expect(second.getSymbolizers()[0]).to.be.a(ol.style.Fill); + expect(second.getSymbolizers()[1]).to.be.a(ol.style.Stroke); + done(); + }); + }); + }); + +}); + +goog.require('goog.net.XhrIo'); +goog.require('ol.parser.ogc.SLD_v1_0_0'); +goog.require('ol.parser.ogc.SLD'); +goog.require('ol.expr.Call'); +goog.require('ol.expr.Comparison'); +goog.require('ol.expr.ComparisonOp'); +goog.require('ol.expr.Identifier'); +goog.require('ol.expr.Literal'); +goog.require('ol.style.Fill'); +goog.require('ol.style.Rule'); +goog.require('ol.style.Stroke'); +goog.require('ol.style.Style'); +goog.require('ol.style.Text'); diff --git a/test/spec/ol/parser/ogc/xml/sld_v1_0_0.xml b/test/spec/ol/parser/ogc/xml/sld_v1_0_0.xml new file mode 100644 index 0000000000..6bb9cc654f --- /dev/null +++ b/test/spec/ol/parser/ogc/xml/sld_v1_0_0.xml @@ -0,0 +1,129 @@ + + + + AAA161 + + + + stortsteen + + + CTE + V0305 + + + 50000 + + + #ffffff + + + #000000 + + + + + + Arial + 14 + bold + normal + + + + + 0.5 + 0.5 + + + 5 + 5 + + 45 + + + + 3 + + #ffffff + + + + #000000 + + + + + betonbekleding + + + CTE + 1000 + + + 50000 + + + #ffff00 + + + #0000ff + + + + + + + + Second Layer + + + + first rule second layer + + + + number + + 1064866676 + + + 1065512599 + + + + cat + *dog.food!*good + + + + FOO + 5000 + + + + + 10000 + + + + star + + lime + + + olive + 2 + + + SIZE + + + + + + +