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