OpenLayers OpenLayers

Ticket #533: sld-newapi.diff

File sld-newapi.diff, 98.3 kB (added by ahocevar, 9 months ago)

Alternative patch using the new API propsed by crschmidt in #1154. All tests pass in FF and IE.

  • tests/Format/test_SLD.html

    old new  
     1<html>  
     2<head>  
     3    <script src="../../lib/OpenLayers.js"></script>  
     4    <script type="text/javascript"> 
     5 
     6    var test_content = '<sld:StyledLayerDescriptor xmlns:sld="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml"><sld:NamedLayer><sld:Name>TestLayer</sld:Name><sld:UserStyle><sld:Name>foo</sld:Name><sld:FeatureTypeStyle><sld:Rule><sld:Name>bar</sld:Name><ogc:Filter></ogc:Filter><sld:PolygonSymbolizer><sld:Fill><sld:CssParameter name="fill"><ogc:Literal>blue</ogc:Literal></sld:CssParameter></sld:Fill></sld:PolygonSymbolizer></sld:Rule></sld:FeatureTypeStyle></sld:UserStyle></sld:NamedLayer></sld:StyledLayerDescriptor>'; 
     7 
     8    function test_Format_SLD_constructor(t) {  
     9        t.plan(3);  
     10          
     11        var options = {'foo': 'bar'};  
     12        var format = new OpenLayers.Format.SLD(options);  
     13        t.ok(format instanceof OpenLayers.Format.SLD,  
     14             "new OpenLayers.Format.SLD returns object" );  
     15        t.eq(format.foo, "bar", "constructor sets options correctly");  
     16        t.eq(typeof format.read, "function", "format has a read function");  
     17    } 
     18 
     19    function test_Format_SLD_read(t) { 
     20        t.plan(5); 
     21        var styles = new OpenLayers.Format.SLD().read(this.test_content, 
     22                {withNamedLayer: true}); 
     23         
     24        var testLayer = styles[1].TestLayer; 
     25         
     26        t.ok(testLayer.foo != undefined, "SLD correctly reads a UserStyle named \"foo\""); 
     27        t.eq(testLayer.foo.rules.length, 1, "The number of rules for the UserStyle is correct"); 
     28        t.eq(testLayer.foo.rules[0].name, "bar", "The first rule's name is \"bar\""); 
     29        t.eq(testLayer.foo.rules[0].symbolizer.Polygon.fillColor, "blue", "The fillColor for the Polygon symbolizer is correct"); 
     30        t.eq(testLayer.foo.name, styles[0][0].name, "The content hash of the Format contains the correct rules."); 
     31    } 
     32 
     33    </script>  
     34</head>  
     35<body>  
     36</body>  
     37</html>  
  • tests/list-tests.html

    old new  
    2222    <li>test_Format.html</li> 
    2323    <li>Format/test_XML.html</li> 
    2424    <li>Format/test_KML.html</li> 
     25    <li>Format/test_SLD.html</li> 
    2526    <li>Format/test_GeoRSS.html</li> 
    2627    <li>Format/test_JSON.html</li> 
    2728    <li>Format/test_GeoJSON.html</li> 
  • lib/OpenLayers/Format/SLD.js

    old new  
     1/* Copyright (c) 2006 MetaCarta, Inc., published under a modified BSD license. 
     2 * See http://svn.openlayers.org/trunk/openlayers/repository-license.txt  
     3 * for the full text of the license. */ 
     4 
     5/** 
     6 * @requires OpenLayers/Format/XML.js 
     7 * @requires OpenLayers/Style.js 
     8 * @requires OpenLayers/Rule.js 
     9 * @requires OpenLayers/Rule/FeatureId.js 
     10 * @requires OpenLayers/Rule/Logical.js 
     11 * @requires OpenLayers/Rule/Comparison.js 
     12 * 
     13 * Class: OpenLayers.Format.SLD 
     14 * Read/Wite SLD. Create a new instance with the <OpenLayers.Format.SLD> 
     15 *     constructor. 
     16 *  
     17 * Inherits from: 
     18 *  - <OpenLayers.Format.XML> 
     19 */ 
     20OpenLayers.Format.SLD = OpenLayers.Class(OpenLayers.Format.XML, { 
     21     
     22    /** 
     23     * APIProperty: sldns 
     24     * Namespace used for sld. 
     25     */ 
     26    sldns: "http://www.opengis.net/sld", 
     27     
     28    /** 
     29     * APIProperty: ogcns 
     30     * Namespace used for ogc. 
     31     */ 
     32    ogcns: "http://www.opengis.net/ogc", 
     33     
     34    /** 
     35     * APIProperty: gmlns 
     36     * Namespace used for gml. 
     37     */ 
     38    gmlns: "http://www.opengis.net/gml", 
     39     
     40    /** 
     41     * APIProperty: defaultStyle. 
     42     * {Object} 
     43     * A simple style, preset with the SLD defaults 
     44     */ 
     45    defaultStyle: { 
     46            fillColor: "#808080", 
     47            fillOpacity: 1, 
     48            strokeColor: "#000000", 
     49            strokeOpacity: 1, 
     50            strokeWidth: 1, 
     51            pointRadius: 6 
     52    }, 
     53     
     54    /** 
     55     */ 
     56    withNamedLayer: false, 
     57      
     58    /** 
     59     * APIProperty: overrideDefaultStyleKey 
     60     * {Boolean} if true, userStyles with sld:IsDefault==1 will be stored with 
     61     * key "default" instead of the sld:UserStyle/Name in the style map. 
     62     * Default is true. 
     63     */ 
     64    overrideDefaultStyleKey: true, 
     65 
     66 
     67    /** 
     68     * Constructor: OpenLayers.Format.SLD 
     69     * Create a new parser for SLD 
     70     * 
     71     * Parameters: 
     72     * options - {Object} An optional object whose properties will be set on 
     73     *                    this instance. 
     74     */ 
     75    initialize: function(options) { 
     76        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]); 
     77    }, 
     78 
     79    /** 
     80     * APIMethod: read 
     81     * Read data from a string, and return a list of features.  
     82     *  
     83     * Parameters: 
     84     * data    - {String} or {XMLNode} data to read/parse. 
     85     * options - {Object} Hash of withNamedLayer, overrideDefaultStyleKey: 
     86     *     - withNamedLayer - {Boolean} if true, output of read() will be 
     87     *           [styles, namedLayer] 
     88     *           - styles - {Array(<OpenLayers.Style>)} 
     89     *           - namedLayer - {Object} hash of userStyles, keyed by 
     90     *                 sld:NamedLayer/Name, each again keyed by  
     91     *                 sld:UserStyle/Name. Each entry of namedLayer is a 
     92     *                 StyleMap for a layer, with the userStyle names as style 
     93     *                 keys. 
     94     *           Default is false. 
     95     *     - overrideDefaultStyleKey - {Boolean} if true, userStyles with 
     96     *           sld:IsDefault==1 will be stored with key "default" instead of 
     97     *           the sld:UserStyle/Name in the style map. Default is true. 
     98     * 
     99     * Returns: 
     100     * {Array(<OpenLayers.Style>)} unless withNamedLayer option is true. 
     101     */ 
     102    read: function(data, options) { 
     103        if (typeof data == "string") {  
     104            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]); 
     105        } 
     106         
     107        options = OpenLayers.Util.extend({ 
     108                withNamedLayer: false, 
     109                overrideDefaultStyleKey: true}, options) 
     110         
     111        var userStyles = this.getElementsByTagNameNS(data, this.sldns, 
     112                "UserStyle"); 
     113        if (userStyles.length == 0) { 
     114            return {}; 
     115        } 
     116 
     117        var namedLayer = {}; 
     118        var styles = []; 
     119 
     120        for (var i=0; i<userStyles.length; i++) { 
     121            var styleName = this.parseProperty(userStyles[i], this.sldns, "Name"); 
     122            var style = this.parseUserStyle(userStyles[i], styleName); 
     123 
     124            if (options.overrideDefaultStyleKey && style.isDefault == true) { 
     125                styleName = "default"; 
     126            } 
     127 
     128            if (!namedLayer[style.layerName]) { 
     129                namedLayer[style.layerName] = {}; 
     130            } 
     131            namedLayer[style.layerName][styleName] = style; 
     132            styles.push(style); 
     133        } 
     134         
     135        return options.withNamedLayer ? [styles, namedLayer] : styles; 
     136    }, 
     137 
     138    /** 
     139     * Method: parseUserStyle 
     140     * parses a sld userStyle for rules 
     141     *  
     142     * Parameters: 
     143     * xmlNode - {<DOMElement>} xml node to read the style from 
     144     * name - {<String>} name of the style 
     145     *  
     146     * Returns: 
     147     * {<OpenLayers.Style>} 
     148     */ 
     149    parseUserStyle: function(xmlNode, name) { 
     150        var userStyle = new OpenLayers.Style(this.defaultStyle, {name: name}); 
     151         
     152        userStyle.isDefault = this.parseProperty(xmlNode, this.sldns, 
     153                "IsDefault") == 1 ? true : false; 
     154         
     155        // get the name of the layer if we have a NamedLayer 
     156        var namedLayerNode = xmlNode.parentNode; 
     157        var nameNodes = this.getElementsByTagNameNS(namedLayerNode, this.sldns, "Name"); 
     158        if (namedLayerNode.nodeName.indexOf("NamedLayer") != -1 && 
     159                nameNodes && 
     160                nameNodes.length > 0 && 
     161                nameNodes[0].parentNode == namedLayerNode) { 
     162            userStyle.layerName = this.getChildValue(nameNodes[0]); 
     163        } 
     164          
     165        var ruleNodes = this.getElementsByTagNameNS(xmlNode, this.sldns, 
     166                "Rule"); 
     167        if (ruleNodes.length == 0) { return []; } 
     168 
     169        var rules = userStyle.rules; 
     170        for (var i=0; i<ruleNodes.length; i++) { 
     171            var name = this.parseProperty(ruleNodes[i], this.sldns, "Name"); 
     172            rules.push(this.parseRule(ruleNodes[i], name)); 
     173        } 
     174 
     175        return userStyle; 
     176    },         
     177     
     178    /** 
     179     * Method: parseRule 
     180     * This function is the core of the SLD parsing code in OpenLayers. 
     181     * It creates the rule with its constraints and symbolizers. 
     182     * 
     183     * Parameters: 
     184     * xmlNode - {<DOMElement>} 
     185     *  
     186     * Returns: 
     187     * {Object} Hash of rule properties 
     188     */ 
     189    parseRule: function(xmlNode, name) { 
     190 
     191        // FILTERS 
     192         
     193        var filter = this.getElementsByTagNameNS(xmlNode, this.ogcns, "Filter"); 
     194        if (filter && filter.length > 0) { 
     195            var rule = this.parseFilter(filter[0]); 
     196        } else { 
     197            // rule applies to all features 
     198            var rule = new OpenLayers.Rule(); 
     199        } 
     200        rule.name = name; 
     201         
     202        // SCALE DENOMINATORS 
     203         
     204        // MinScaleDenominator 
     205        var minScale = this.getElementsByTagNameNS(xmlNode, 
     206                this.sldns, "MinScaleDenominator"); 
     207        if (minScale && minScale.length > 0) { 
     208            rule.minScale = parseFloat( 
     209                    this.getChildValue(minScale[0])); 
     210        } 
     211         
     212        // MaxScaleDenominator 
     213        var maxScale = this.getElementsByTagNameNS(xmlNode, 
     214                this.sldns, "MaxScaleDenominator"); 
     215        if (maxScale && maxScale.length > 0) { 
     216            rule.maxScale = parseFloat( 
     217                    this.getChildValue(maxScale[0])); 
     218        } 
     219         
     220        // STYLES 
     221         
     222        // walk through all symbolizers 
     223        var prefixes = OpenLayers.Style.SYMBOLIZER_PREFIXES; 
     224        for (var s=0; s<prefixes.length; s++) { 
     225             
     226            // symbolizer type 
     227            var symbolizer = this.getElementsByTagNameNS(xmlNode, this.sldns, 
     228                    prefixes[s]+"Symbolizer"); 
     229             
     230            if (symbolizer && symbolizer.length > 0) { 
     231             
     232                var style = {}; 
     233             
     234                // externalGraphic 
     235                var graphic = this.getElementsByTagNameNS(symbolizer[0], 
     236                        this.sldns, "Graphic"); 
     237                if (graphic && graphic.length > 0) { 
     238                    style.externalGraphic = this.parseProperty(graphic[0], 
     239                            this.sldns, "OnlineResource", "xlink:href"); 
     240                    style.pointRadius = this.parseProperty(graphic[0], 
     241                            this.sldns, "Size"); 
     242                    style.graphicOpacity = this.parseProperty(graphic[0], 
     243                            this.sldns, "Opacity"); 
     244                } 
     245                 
     246                // fill 
     247                var fill = this.getElementsByTagNameNS(symbolizer[0], 
     248                        this.sldns, "Fill"); 
     249                if (fill && fill.length > 0) { 
     250                    style.fillColor = this.parseProperty(fill[0], this.sldns, 
     251                            "CssParameter", "name", "fill"); 
     252                    style.fillOpacity = this.parseProperty(fill[0], 
     253                            this.sldns, "CssParameter", "name", 
     254                            "fill-opacity") || 1; 
     255                } 
     256             
     257                // stroke 
     258                var stroke = this.getElementsByTagNameNS(symbolizer[0], 
     259                        this.sldns, "Stroke"); 
     260                if (stroke && stroke.length > 0) { 
     261                    style.strokeColor = this.parseProperty(stroke[0], 
     262                            this.sldns, "CssParameter", "name", "stroke"); 
     263                    style.strokeOpacity = this.parseProperty(stroke[0], 
     264                            this.sldns, "CssParameter", "name", 
     265                            "stroke-opacity") || 1; 
     266                    style.strokeWidth = this.parseProperty(stroke[0], 
     267                            this.sldns, "CssParameter", "name", 
     268                            "stroke-width"); 
     269                    style.strokeLinecap = this.parseProperty(stroke[0], 
     270                            this.sldns, "CssParameter", "name", 
     271                            "stroke-linecap"); 
     272                } 
     273                 
     274                // set the [point|line|polygon]Symbolizer property of the rule 
     275                rule.symbolizer[prefixes[s]] = style; 
     276            } 
     277        } 
     278 
     279        return rule; 
     280    }, 
     281     
     282    /** 
     283     * Method: parseFilter 
     284     * Parses ogc fiters. 
     285     * 
     286     * Parameters: 
     287     * xmlNode - {<DOMElement>} 
     288     *  
     289     * Returns: 
     290     * {<OpenLayers.Rule>} rule representing the filter 
     291     */ 
     292    parseFilter: function(xmlNode) { 
     293        // ogc:FeatureId filter 
     294        var filter = this.getNodeOrChildrenByTagName(xmlNode, "FeatureId"); 
     295        if (filter) { 
     296            var rule = new OpenLayers.Rule.FeatureId(); 
     297            for (var i=0; i<filter.length; i++) { 
     298                rule.fids.push(filter[i].getAttribute("fid")); 
     299            } 
     300            return rule; 
     301        } 
     302         
     303        // ogc:And filter 
     304        filter = this.getNodeOrChildrenByTagName(xmlNode, "And"); 
     305        if (filter) { 
     306            var rule = new OpenLayers.Rule.Logical( 
     307                    {type: OpenLayers.Rule.Logical.AND}); 
     308            var filters = filter[0].childNodes;  
     309            for (var i=0; i<filters.length; i++) { 
     310                if (filters[i].nodeType == 1) { 
     311                    rule.children.push(this.parseFilter(filters[i])); 
     312                } 
     313            } 
     314            return rule; 
     315        } 
     316 
     317        // ogc:Or filter 
     318        filter = this.getNodeOrChildrenByTagName(xmlNode, "Or"); 
     319        if (filter) { 
     320            var rule = new OpenLayers.Rule.Logical( 
     321                    {type: OpenLayers.Rule.Logical.OR}) 
     322            var filters = filter[0].childNodes;  
     323            for (var i=0; i<filters.length; i++) { 
     324                if (filters[i].nodeType == 1) { 
     325                    rule.children.push(this.parseFilter(filters[i])); 
     326                } 
     327            } 
     328            return rule; 
     329        } 
     330 
     331        // ogc:Not filter 
     332        filter = this.getNodeOrChildrenByTagName(xmlNode, "Not"); 
     333        if (filter) { 
     334            var rule = new OpenLayers.Rule.Logical( 
     335                    {type: OpenLayers.Rule.Logical.NOT}); 
     336            rule.children.push(this.parseFilter(filter[0])); 
     337            return rule; 
     338        } 
     339         
     340        // Comparison filters 
     341        for (var type in this.TYPES) { 
     342            var filter = this.getNodeOrChildrenByTagName(xmlNode, type); 
     343            if (filter) { 
     344                filter = filter[0]; 
     345                var rule = new OpenLayers.Rule.Comparison({ 
     346                        type: OpenLayers.Rule.Comparison[this.TYPES[type]], 
     347                        property: this.parseProperty( 
     348                                filter, this.ogcns, "PropertyName")}); 
     349                // ogc:PropertyIsBetween 
     350                if (this.TYPES[type] == "BETWEEN") { 
     351                    rule.lowerBoundary = this.parseProperty( 
     352                            filter, this.ogcns, "LowerBoundary"); 
     353                    rule.upperBoudary = this.parseProperty( 
     354                            filter, this.ogcns, "UpperBoundary"); 
     355                } else { 
     356                    rule.value = this.parseProperty( 
     357                            filter, this.ogcns, "Literal"); 
     358                    // ogc:PropertyIsLike 
     359                    if (this.TYPES[type] == "LIKE") { 
     360                        var wildCard = filter.getAttribute("wildCard"); 
     361                        var singleChar = filter.getAttribute("singleChar"); 
     362                        var escape = filter.getAttribute("escape"); 
     363                        rule.value2regex(wildCard, singleChar, escape); 
     364                    } 
     365                } 
     366                return rule; 
     367            } 
     368        } 
     369         
     370        // if we get here, the filter was empty 
     371        return new OpenLayers.Rule(); 
     372    }, 
     373     
     374    /** 
     375     * Method: getNodeOrChildrenByTagName 
     376     * Convenience method to get a node or its child nodes, but only 
     377     * those matching a tag name. 
     378     *  
     379     * Returns: 
     380     * {Array(<DOMElement>)} or null if no matching content is found 
     381     */ 
     382    getNodeOrChildrenByTagName: function(xmlNode, tagName) { 
     383        var nodeName = (xmlNode.prefix) ? 
     384               xmlNode.nodeName.split(":")[1] : 
     385               xmlNode.nodeName; 
     386 
     387        if (nodeName == tagName) { 
     388            return [xmlNode]; 
     389        } else { 
     390            var nodelist = this.getElementsByTagNameNS( 
     391                    xmlNode, this.ogcns, tagName); 
     392        } 
     393 
     394        // make a new list which only contains matching child nodes 
     395        if (nodelist.length > 0) { 
     396            var node; 
     397            var list = []; 
     398            for (var i=0; i<nodelist.length; i++) { 
     399                node = nodelist[i]; 
     400                if (node.parentNode == xmlNode) { 
     401                    list.push(node); 
     402                } 
     403            } 
     404            return list.length > 0 ? list : null; 
     405        } 
     406         
     407        return null; 
     408    }, 
     409     
     410    /** 
     411     * Method: parseProperty 
     412     * Convenience method to parse the different kinds of properties 
     413     * found in the sld and ogc namespace. 
     414     * Parses an ogc node that can either contain a value directly, 
     415     * or inside a <Literal> property. The parsing can also be limited 
     416     * to nodes with certain attribute names and/or values 
     417     * 
     418     * Parameters: 
     419     * xmlNode        - {<DOMElement>} 
     420     * namespace      - {String} namespace of the node to find 
     421     * propertyName   - {String} name of the property to parse 
     422     * attributeName  - {String} optional name of the property to match 
     423     * attributeValue - {String} optional value of the specified attribute 
     424     *  
     425     * Returns: 
     426     * {String} The value for the requested property 
     427     */     
     428    parseProperty: function(xmlNode, namespace, propertyName, attributeName, 
     429                                                              attributeValue) { 
     430        var result = null; 
     431        var propertyNodeList = this.getElementsByTagNameNS( 
     432                xmlNode, namespace, propertyName); 
     433                 
     434        if (propertyNodeList && propertyNodeList.length > 0) { 
     435            var propertyNode = attributeName ? 
     436                    this.getNodeWithAttribute(propertyNodeList,  
     437                            attributeName) : 
     438                    propertyNodeList[0]; 
     439 
     440            // strip namespace from attribute name for Opera browsers 
     441            if (window.opera && attributeName) { 
     442                var nsDelimiterPos = attributeName.indexOf(":"); 
     443                if (nsDelimiterPos != -1) { 
     444                    attributeName = attributeName.substring(++nsDelimiterPos); 
     445                } 
     446            } 
     447             
     448            // get the property value from the node matching attributeName 
     449            // and attributeValue, eg.: 
     450            // <CssParameter name="stroke"> 
     451            //     <ogc:Literal>red</ogc:Literal> 
     452            // </CssParameter> 
     453            // or: 
     454            // <CssParameter name="stroke">red</CssParameter> 
     455            if (attributeName && attributeValue) { 
     456                propertyNode = this.getNodeWithAttribute(propertyNodeList, 
     457                        attributeName, attributeValue); 
     458                result = this.parseParameter(propertyNode); 
     459            } 
     460 
     461            // get the attribute value and use it as result, eg.: 
     462            // <sld:OnlineResource xlink:href="../img/marker.png"/> 
     463            if (attributeName && !attributeValue) { 
     464                var propertyNode = this.getNodeWithAttribute(propertyNodeList, 
     465                        attributeName); 
     466                result = propertyNode.getAttribute(attributeName);                 
     467            } 
     468             
     469            // get the property value directly or from an ogc:propertyName, 
     470            // ogc:Literal or any other property at the level of the property 
     471            // node, eg.: 
     472            // <sld:Opacity>0.5</sld:Opacity> 
     473            if (!attributeName) { 
     474                var result = this.parseParameter(propertyNode); 
     475            } 
     476        } 
     477         
     478        // adjust the result to be a trimmed string or a number 
     479        if (result) { 
     480            result = OpenLayers.String.trim(result); 
     481            if (!isNaN(result)) { 
     482                result = parseFloat(result); 
     483            } 
     484        } 
     485         
     486        return result; 
     487    }, 
     488     
     489    /** 
     490     * Method: parseParameter 
     491     * parses a property for propertyNames, Literals and textContent and 
     492     * creates the according value string. 
     493     *  
     494     * Parameters: 
     495     * xmlNode - {<DOMElement>} 
     496     *  
     497     * Returns: 
     498     * {String} a string holding a value suitable for OpenLayers.Style.value 
     499     */ 
     500    parseParameter: function(xmlNode) { 
     501        if (!xmlNode) { 
     502            return null; 
     503        } 
     504        var childNodes = xmlNode.childNodes; 
     505        if (!childNodes) { 
     506            return null; 
     507        } 
     508 
     509        var value = new Array(childNodes.length); 
     510        for (var i=0; i<childNodes.length; i++) { 
     511            if (childNodes[i].nodeName.indexOf("Literal") != -1) { 
     512                value[i] = this.getChildValue(childNodes[i]); 
     513            } else 
     514            if (childNodes[i].nodeName.indexOf("propertyName") != -1) { 
     515                value[i] = "${" + this.getChildValue(childNodes[i]) + "}"; 
     516            } else 
     517            if (childNodes[i].nodeType == 3) { 
     518                value[i] = childNodes[i].text || childNodes[i].textContent; 
     519            } 
     520        } 
     521        return value.join(""); 
     522    }, 
     523         
     524    /** 
     525     * Method: getNodeWithAttribute 
     526     * Walks through a list of xml nodes and returns the fist node that has an 
     527     * attribute with the name and optional value specified. 
     528     *  
     529     * Parameters: 
     530     * xmlNodeList    - {Array(<DOMElement>)} list to search 
     531     * attributeName  - {String} name of the attribute to match 
     532     * attributeValue - {String} optional value of the attribute 
     533     */ 
     534    getNodeWithAttribute: function(xmlNodeList, attributeName, attributeValue) { 
     535        for (var i=0; i<xmlNodeList.length; i++) { 
     536            var currentAttributeValue = 
     537                    xmlNodeList[i].getAttribute(attributeName); 
     538            if (currentAttributeValue) { 
     539                if (!attributeValue) { 
     540                    return xmlNodeList[i]; 
     541                } else if (currentAttributeValue == attributeValue) { 
     542                    return xmlNodeList[i]; 
     543                } 
     544            } 
     545        } 
     546    }, 
     547     
     548    /** 
     549     * Constant: TYPES 
     550     * {Object} Mapping between SLD rule names and rule type constants. 
     551     *  
     552     */ 
     553    TYPES: {'PropertyIsEqualTo': 'EQUAL_TO', 
     554            'PropertyIsNotEqualTo': 'NOT_EQUAL_TO', 
     555            'PropertyIsLessThan': 'LESS_THAN', 
     556            'PropertyIsGreaterThan': 'GREATER_THAN', 
     557            'PropertyIsLessThanOrEqualTo': 'LESS_THAN_OR_EQUAL_TO', 
     558            'PropertyIsGreaterThanOrEqualTo': 'GREATER_THAN_OR_EQUAL_TO', 
     559            'PropertyIsBetween': 'BETWEEN', 
     560            'PropertyIsLike': 'LIKE'}, 
     561 
     562    CLASS_NAME: "OpenLayers.Format.SLD"  
     563}); 
  • lib/OpenLayers.js

    old new  
    176176            "OpenLayers/Format/GeoRSS.js", 
    177177            "OpenLayers/Format/WFS.js", 
    178178            "OpenLayers/Format/WKT.js", 
     179            "OpenLayers/Format/SLD.js", 
    179180            "OpenLayers/Format/Text.js", 
    180181            "OpenLayers/Format/JSON.js", 
    181182            "OpenLayers/Format/GeoJSON.js", 
  • examples/sld.html

    old new  
     1<html xmlns="http://www.w3.org/1999/xhtml"> 
     2  <head> 
     3    <style type="text/css"> 
     4        #map { 
     5            width: 800px; 
     6            height: 475px; 
     7            border: 1px solid black; 
     8        } 
     9    </style> 
     10    <script src="../lib/Firebug/firebug.js"></script> 
     11    <script src="../lib/OpenLayers.js"></script> 
     12    <script type="text/javascript"> 
     13        var lon = 5; 
     14        var lat = 40; 
     15        var zoom = 5; 
     16        var map, layer, gmlLayers, styles, waterStyle, hover; 
     17 
     18        function load(){ 
     19           OpenLayers.loadURL("tasmania/sld-tasmania.xml", "", null, init); 
     20        } 
     21         
     22        function init(req){ 
     23            map = new OpenLayers.Map('map'); 
     24            layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",  
     25                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} ); 
     26            map.addLayer(layer);            
     27                  map.zoomToExtent(new OpenLayers.Bounds(143,-39,150,-45)); 
     28 
     29            sld = new OpenLayers.Format.SLD().read(req.responseText, 
     30                    {withNamedLayer: true}); 
     31             
     32            styles = sld[1]; 
     33             
     34            waterStyle = styles["WaterBodies"]; 
     35             
     36            gmlLayers = [ 
     37                    // use the sld UserStyle named "Default Styler" 
     38                    new OpenLayers.Layer.GML("StateBoundaries", 
     39                            "tasmania/TasmaniaStateBoundaries.xml", { 
     40                            style: waterStyle["default"]}), 
     41                    new OpenLayers.Layer.GML("Roads", 
     42                            "tasmania/TasmaniaRoads.xml", { 
     43                            style: waterStyle["default"]}), 
     44                    new OpenLayers.Layer.GML("WaterBodies", 
     45                            "tasmania/TasmaniaWaterBodies.xml", { 
     46                            style: waterStyle["default"]}), 
     47                    new OpenLayers.Layer.GML("Cities", 
     48                            "tasmania/TasmaniaCities.xml", { 
     49                            style: waterStyle["default"]})]; 
     50  
     51            // add the first layer with the style passed to the constructor 
     52            map.addLayer(gmlLayers[0]); 
     53            // add the other layers after setting the style using the 
     54            // setStyle() method, which will pick the correct default style 
     55            // from the styles hash we got back from 
     56            // OpenLayers.Format.SLD.read() 
     57            for (var i=1; i<gmlLayers.length; i++) { 
     58                gmlLayers[i].style = styles[gmlLayers[i].name]["default"]; 
     59                      map.addLayer(gmlLayers[i]); 
     60                gmlLayers[i].redraw(); 
     61            } 
     62             
     63            // SLD can also be used for the SelectFeature control 
     64            waterStyle["Hover Styler"].defaultStyle = 
     65                    OpenLayers.Feature.Vector.style["select"]; 
     66            hover = new OpenLayers.Control.SelectFeature(gmlLayers[2], { 
     67                    selectStyle: waterStyle["Hover Styler"], 
     68                    hover: true, 
     69                    select: select 
     70                }); 
     71            map.addControl(hover); 
     72            hover.activate(); 
     73        } 
     74 
     75        // replaces OpenLayers.Control.Select.select 
     76        var select = function(feature) { 
     77            // store layer style 
     78            var style = feature.layer.style; 
     79            // set temporary layer style for hover rendering 
     80            feature.layer.style = hover.selectStyle; 
     81            OpenLayers.Control.SelectFeature.prototype.select.apply(hover, arguments); 
     82            // restore layer style 
     83            feature.layer.style = style; 
     84        } 
     85         
     86        // set a new style when the radio button changes 
     87        function setStyle(styleName) { 
     88            // change the style of the features of the WaterBodies layer 
     89            var features = gmlLayers[2].features; 
     90            for (var i=0; i<features.length; i++) { 
     91                features[i].style = waterStyle[styleName]; 
     92            } 
     93            gmlLayers[2].redraw(); 
     94        } 
     95    </script> 
     96  </head> 
     97  <body onload="load()"> 
     98    <div id="map"></div> 
     99    <p>This example uses a <a target="_blank" href="xml/sld-tasmania.xml">SLD 
     100    file</a> to style the vector features. The style to be used is either 
     101    determined by the NamedLayer and IsDefault properties in the sld file, or 
     102    can directly be applied by addressing a style from the styles 
     103    hash with the UserStyle name from the sld file as key. Select a new style for the WaterBodies layer below:<p> 
     104    <form> 
     105      <input type="radio" name="style" onclick="setStyle(this.value)" checked="checked" value="default">Default Styler (zoom in to see more features)</input><br/> 
     106      <input type="radio" name="style" onclick="setStyle(this.value)" value="Styler Test PropertyIsEqualTo">Styler Test PropertyIsEqualTo</input><br/> 
     107      <input type="radio" name="style" onclick="setStyle(this.value)" value="Styler Test Not FeatureId">Styler Test Not FeatureId</input><br/> 
     108      <input type="radio" name="style" onclick="setStyle(this.value)" value="Styler Test WATER_TYPE">Styler Test WATER_TYPE</input><br/> 
     109      <input type="radio" name="style" onclick="setStyle(this.value)" value="Styler Test PropertyIsGreaterThanOrEqualTo">Styler Test PropertyIsGreaterThanOrEqualTo</input><br/> 
     110      <input type="radio" name="style" onclick="setStyle(this.value)" value="Styler Test PropertyIsLessThanOrEqualTo">Styler Test PropertyIsLessThanOrEqualTo</input><br/> 
     111      <input type="radio" name="style" onclick="setStyle(this.value)" value="Styler Test PropertyIsGreaterThan">Styler Test PropertyIsGreaterThan</input><br/> 
     112      <input type="radio" name="style" onclick="setStyle(this.value)" value="Styler Test PropertyIsLessThan">Styler Test PropertyIsLessThan</input><br/> 
     113      <input type="radio" name="style" onclick="setStyle(this.value)" value="Styler Test PropertyIsLike">Styler Test PropertyIsLike</input><br/> 
     114    </form> 
     115  </body> 
     116</html> 
  • examples/tasmania/TasmaniaRoads.xml

    <
    old new  
     1<?xml version="1.0" encoding="UTF-8"?> 
     2<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:topp="http://www.openplans.org/topp" xmlns:gml="http://www.opengis.net/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openplans.org/topp http://192.168.0.100:8080/geoserver-1.4.0-RC3/wfs/DescribeFeatureType?typeName=topp:tasmania_roads http://www.opengis.net/wfs http://192.168.0.100:8080/geoserver-1.4.0-RC3/schemas/wfs/1.0.0/WFS-basic.xsd"> 
     3  <gml:boundedBy> 
     4    <gml:Box srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> 
     5      <gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs="," ts=" ">145.19754,-43.423512 148.27298,-40.852802</gml:coordinates> 
     6    </gml:Box> 
     7  </gml:boundedBy> 
     8  <gml:featureMember> 
     9    <topp:tasmania_roads fid="tasmania_roads.1"> 
     10      <topp:the_geom> 
     11        <gml:MultiLineString srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> 
     12          <gml:lineStringMember> 
     13            <gml:LineString> 
     14              <gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs="," ts=" ">146.468582,-41.241478 146.574768,-41.251186 146.640411,-41.255154 146.766129,-41.332348 146.794189,-41.34417 146.822174,-41.362988 146.863434,-41.380234 146.899521,-41.379452 146.929504,-41.378227 147.008041,-41.356079 147.098343,-41.362919</gml:coordinates> 
     15            </gml:LineString> 
     16          </gml:lineStringMember> 
     17        </gml:MultiLineString> 
     18      </topp:the_geom> 
     19      <topp:TYPE>alley</topp:TYPE> 
     20    </topp:tasmania_roads> 
     21  </gml:featureMember> 
     22  <gml:featureMember> 
     23    <topp:tasmania_roads fid="tasmania_roads.2"> 
     24      <topp:the_geom> 
     25        <gml:MultiLineString srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> 
     26          <gml:lineStringMember> 
     27            <gml:LineString> 
     28              <gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs="," ts=" ">147.098343,-41.362919 147.17305,-41.452778 147.213867,-41.503773 147.234894,-41.546661 147.251129,-41.573826 147.264664,-41.602474 147.284485,-41.617554 147.300583,-41.637878</gml:coordinates> 
     29            </gml:LineString> 
     30          </gml:lineStringMember> 
     31        </gml:MultiLineString> 
     32      </topp:the_geom> 
     33      <topp:TYPE>highway</topp:TYPE> 
     34    </topp:tasmania_roads> 
     35  </gml:featureMember> 
     36  <gml:featureMember> 
     37    <topp:tasmania_roads fid="tasmania_roads.3"> 
     38      <topp:the_geom> 
     39        <gml:MultiLineString srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> 
     40          <gml:lineStringMember> 
     41            <gml:LineString> 
     42              <gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs="," ts=" ">147.300583,-41.637878 147.225815,-41.626938 147.183319,-41.619236 147.082367,-41.577755 147.031326,-41.565205 146.961487,-41.564186 146.924545,-41.568565 146.876328,-41.569614 146.783722,-41.56073 146.684937,-41.536232 146.614258,-41.478153 146.619995,-41.423958 146.582581,-41.365482 146.52478,-41.29541 146.477493,-41.277622 146.468582,-41.241478</gml:coordinates> 
     43            </gml:LineString> 
     44          </gml:lineStringMember> 
     45        </gml:MultiLineString> 
     46      </topp:the_geom> 
     47      <topp:TYPE>lane</topp:TYPE> 
     48    </topp:tasmania_roads> 
     49  </gml:featureMember> 
     50  <gml:featureMember> 
     51    <topp:tasmania_roads fid="tasmania_roads.4"> 
     52      <topp:the_geom> 
     53        <gml:MultiLineString srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> 
     54          <gml:lineStringMember> 
     55            <gml:LineString> 
     56              <gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs="," ts=" ">147.522247,-41.859921 147.551865,-41.927834 147.597321,-42.017418 147.578644,-42.113216 147.541656,-42.217743 147.468674,-42.22662</gml:coordinates> 
     57            </gml:LineString> 
     58          </gml:lineStringMember> 
     59        </gml:MultiLineString> 
     60      </topp:the_geom> 
     61      <topp:TYPE>highway</topp:TYPE> 
     62    </topp:tasmania_roads> 
     63  </gml:featureMember> 
     64  <gml:featureMember> 
     65    <topp:tasmania_roads fid="tasmania_roads.5"> 
     66      <topp:the_geom> 
     67        <gml:MultiLineString srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> 
     68          <gml:lineStringMember> 
     69            <gml:LineString> 
     70              <gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs="," ts=" ">146.103699,-41.171677 146.303619,-41.237202 146.362228,-41.236279 146.39418,-41.245384 146.443726,-41.244308 146.468582,-41.241478</gml:coordinates> 
     71            </gml:LineString> 
     72          </gml:lineStringMember> 
     73        </gml:MultiLineString> 
     74      </topp:the_geom> 
     75      <topp:TYPE>gravel</topp:TYPE> 
     76    </topp:tasmania_roads> 
     77  </gml:featureMember> 
     78  <gml:featureMember> 
     79    <topp:tasmania_roads fid="tasmania_roads.6"> 
     80      <topp:the_geom> 
     81        <gml:MultiLineString srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> 
     82          <gml:lineStringMember> 
     83            <gml:LineString> 
     84              <gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs="," ts=" ">145.856018,-41.08007 145.944839,-41.119896 146.037994,-41.150059 146.103699,-41.171677</gml:coordinates> 
     85            </gml:LineString> 
     86          </gml:lineStringMember> 
     87        </gml:MultiLineString> 
     88      </topp:the_geom> 
     89      <topp:TYPE>road</topp:TYPE> 
     90    </topp:tasmania_roads> 
     91  </gml:featureMember> 
     92  <gml:featureMember> 
     93    <topp:tasmania_roads fid="tasmania_roads.7"> 
     94      <topp:the_geom> 
     95        <gml:MultiLineString srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> 
     96          <gml:lineStringMember> 
     97            <gml:LineString> 
     98              <gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs="," ts=" ">147.468674,-42.22662 147.474945,-42.292259 147.467697,-42.301292 147.451828,-42.341656 147.424545,-42.378723 147.366013,-42.412552 147.345779,-42.432449 147.289322,-42.476475 147.264511,-42.503899 147.259918,-42.547539 147.249405,-42.614006 147.278351,-42.693249 147.284271,-42.757759 147.256744,-42.778393</gml:coordinates> 
     99            </gml:LineString> 
     100          </gml:lineStringMember> 
     101        </gml:MultiLineString> 
     102      </topp:the_geom> 
     103      <topp:TYPE>highway</topp:TYPE> 
     104    </topp:tasmania_roads> 
     105  </gml:featureMember> 
     106  <gml:featureMember> 
     107    <topp:tasmania_roads fid="tasmania_roads.8"> 
     108      <topp:the_geom> 
     109        <gml:MultiLineString srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> 
     110          <gml:lineStringMember> 
     111            <gml:LineString> 
     112              <gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs="," ts=" ">148.249252,-41.860851 148.234436,-41.901783 148.192123,-41.93721 148.155762,-41.953667 148.127731,-41.994537 148.053131,-42.100563</gml:coordinates> 
     113            </gml:LineString> 
     114          </gml:lineStringMember> 
     115        </gml:MultiLineString> 
     116      </topp:the_geom> 
     117      <topp:TYPE>road</topp:TYPE> 
     118    </topp:tasmania_roads> 
     119  </gml:featureMember> 
     120  <gml:featureMember> 
     121    <topp:tasmania_roads fid="tasmania_roads.9"> 
     122      <topp:the_geom> 
     123        <gml:MultiLineString srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> 
     124          <gml:lineStringMember> 
     125            <gml:LineString> 
     126              <gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs="," ts=" ">145.19754,-40.878323 145.246674,-40.86021 145.293289,-40.852802 145.465225,-40.897865 145.538498,-40.936264 145.554062,-40.939201 145.602112,-40.962936 145.646362,-40.98243 145.683838,-40.989883 145.710587,-40.996201 145.744293,-41.007545 145.801956,-41.041782 145.856018,-41.08007</gml:coordinates> 
     127            </gml:LineString> 
     128          </gml:lineStringMember> 
     129        </gml:MultiLineString> 
     130      </topp:the_geom> 
     131      <topp:TYPE>logging</topp:TYPE> 
     132    </topp:tasmania_roads> 
     133  </gml:featureMember> 
     134  <gml:featureMember> 
     135    <topp:tasmania_roads fid="tasmania_roads.10"> 
     136      <topp:the_geom> 
     137        <gml:MultiLineString srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> 
     138          <gml:lineStringMember> 
     139            <gml:LineString> 
     140              <gml:coordinates xmlns:gml="http://www.opengis.net/gml" decimal="." cs="," ts=" ">147.360001,-42.91993 147.348816,-42.93726 147.285049,-42.979027 147.220886,-42.995876 147.164429,-43.027004 147.068237,-43.06319 146.96463,-43.116447 146.949554,-43.17004 146.95369,-43.209591 146.964127,-43.224545 146.975723,-43.250484 146.980759,-43.2701 146.982605,-43.287716 146.970871,-43.31691 146.940521,-43.33812 146.943054,-43.362263 146.952194,-43.39278 146.955429,-43.423512</gml:coordinates> 
     141            </gml:LineString> 
     142          </gml:lineStringMember> 
     143        </gml:MultiLineString> 
     144      </topp:the_geom> 
     145      <topp:TYPE>road</topp:TYPE> 
     146    </topp:tasmania_roads> 
     147  </gml:featureMember> 
     148  <gml:featureMember> 
     149    <topp:tasmania_roads fid="tasmania_roads.11"> 
     150      <topp:the_geom> 
     151        <gml:MultiLineString srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"> 
     152          <gml:lineStringMember>