v1.js 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309
  1. /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
  2. * full list of contributors). Published under the 2-clause BSD license.
  3. * See license.txt in the OpenLayers distribution or repository for the
  4. * full text of the license. */
  5. /**
  6. * @requires OpenLayers/Rule.js
  7. * @requires OpenLayers/Format/SLD.js
  8. * @requires OpenLayers/Format/Filter/v1_0_0.js
  9. * @requires OpenLayers/Symbolizer/Point.js
  10. * @requires OpenLayers/Symbolizer/Line.js
  11. * @requires OpenLayers/Symbolizer/Polygon.js
  12. * @requires OpenLayers/Symbolizer/Text.js
  13. * @requires OpenLayers/Symbolizer/Raster.js
  14. */
  15. /**
  16. * Class: OpenLayers.Format.SLD.v1
  17. * Superclass for SLD version 1 parsers.
  18. *
  19. * Inherits from:
  20. * - <OpenLayers.Format.Filter.v1_0_0>
  21. */
  22. OpenLayers.Format.SLD.v1 = OpenLayers.Class(OpenLayers.Format.Filter.v1_0_0, {
  23. /**
  24. * Property: namespaces
  25. * {Object} Mapping of namespace aliases to namespace URIs.
  26. */
  27. namespaces: {
  28. sld: "http://www.opengis.net/sld",
  29. ogc: "http://www.opengis.net/ogc",
  30. gml: "http://www.opengis.net/gml",
  31. xlink: "http://www.w3.org/1999/xlink",
  32. xsi: "http://www.w3.org/2001/XMLSchema-instance"
  33. },
  34. /**
  35. * Property: defaultPrefix
  36. */
  37. defaultPrefix: "sld",
  38. /**
  39. * Property: schemaLocation
  40. * {String} Schema location for a particular minor version.
  41. */
  42. schemaLocation: null,
  43. /**
  44. * APIProperty: multipleSymbolizers
  45. * {Boolean} Support multiple symbolizers per rule. Default is false. if
  46. * true, an OpenLayers.Style2 instance will be created to represent
  47. * user styles instead of an OpenLayers.Style instace. The
  48. * OpenLayers.Style2 class allows collections of rules with multiple
  49. * symbolizers, but is not currently useful for client side rendering.
  50. * If multiple symbolizers is true, multiple FeatureTypeStyle elements
  51. * are preserved in reading/writing by setting symbolizer zIndex values.
  52. * In addition, the <defaultSymbolizer> property is ignored if
  53. * multiple symbolizers are supported (defaults should be applied
  54. * when rendering).
  55. */
  56. multipleSymbolizers: false,
  57. /**
  58. * Property: featureTypeCounter
  59. * {Number} Private counter for multiple feature type styles.
  60. */
  61. featureTypeCounter: null,
  62. /**
  63. * APIProperty: defaultSymbolizer.
  64. * {Object} A symbolizer with the SLD defaults.
  65. */
  66. defaultSymbolizer: {
  67. fillColor: "#808080",
  68. fillOpacity: 1,
  69. strokeColor: "#000000",
  70. strokeOpacity: 1,
  71. strokeWidth: 1,
  72. strokeDashstyle: "solid",
  73. pointRadius: 3,
  74. graphicName: "square"
  75. },
  76. /**
  77. * Constructor: OpenLayers.Format.SLD.v1
  78. * Instances of this class are not created directly. Use the
  79. * <OpenLayers.Format.SLD> constructor instead.
  80. *
  81. * Parameters:
  82. * options - {Object} An optional object whose properties will be set on
  83. * this instance.
  84. */
  85. /**
  86. * Method: read
  87. *
  88. * Parameters:
  89. * data - {DOMElement} An SLD document element.
  90. * options - {Object} Options for the reader.
  91. *
  92. * Valid options:
  93. * namedLayersAsArray - {Boolean} Generate a namedLayers array. If false,
  94. * the namedLayers property value will be an object keyed by layer name.
  95. * Default is false.
  96. *
  97. * Returns:
  98. * {Object} An object representing the SLD.
  99. */
  100. read: function(data, options) {
  101. options = OpenLayers.Util.applyDefaults(options, this.options);
  102. var sld = {
  103. namedLayers: options.namedLayersAsArray === true ? [] : {}
  104. };
  105. this.readChildNodes(data, sld);
  106. return sld;
  107. },
  108. /**
  109. * Property: readers
  110. * Contains public functions, grouped by namespace prefix, that will
  111. * be applied when a namespaced node is found matching the function
  112. * name. The function will be applied in the scope of this parser
  113. * with two arguments: the node being read and a context object passed
  114. * from the parent.
  115. */
  116. readers: OpenLayers.Util.applyDefaults({
  117. "sld": {
  118. "StyledLayerDescriptor": function(node, sld) {
  119. sld.version = node.getAttribute("version");
  120. this.readChildNodes(node, sld);
  121. },
  122. "Name": function(node, obj) {
  123. obj.name = this.getChildValue(node);
  124. },
  125. "Title": function(node, obj) {
  126. obj.title = this.getChildValue(node);
  127. },
  128. "Abstract": function(node, obj) {
  129. obj.description = this.getChildValue(node);
  130. },
  131. "NamedLayer": function(node, sld) {
  132. var layer = {
  133. userStyles: [],
  134. namedStyles: []
  135. };
  136. this.readChildNodes(node, layer);
  137. // give each of the user styles this layer name
  138. for(var i=0, len=layer.userStyles.length; i<len; ++i) {
  139. layer.userStyles[i].layerName = layer.name;
  140. }
  141. if(OpenLayers.Util.isArray(sld.namedLayers)) {
  142. sld.namedLayers.push(layer);
  143. } else {
  144. sld.namedLayers[layer.name] = layer;
  145. }
  146. },
  147. "NamedStyle": function(node, layer) {
  148. layer.namedStyles.push(
  149. this.getChildName(node.firstChild)
  150. );
  151. },
  152. "UserStyle": function(node, layer) {
  153. var obj = {defaultsPerSymbolizer: true, rules: []};
  154. this.featureTypeCounter = -1;
  155. this.readChildNodes(node, obj);
  156. var style;
  157. if (this.multipleSymbolizers) {
  158. delete obj.defaultsPerSymbolizer;
  159. style = new OpenLayers.Style2(obj);
  160. } else {
  161. style = new OpenLayers.Style(this.defaultSymbolizer, obj);
  162. }
  163. layer.userStyles.push(style);
  164. },
  165. "IsDefault": function(node, style) {
  166. if(this.getChildValue(node) == "1") {
  167. style.isDefault = true;
  168. }
  169. },
  170. "FeatureTypeStyle": function(node, style) {
  171. ++this.featureTypeCounter;
  172. var obj = {
  173. rules: this.multipleSymbolizers ? style.rules : []
  174. };
  175. this.readChildNodes(node, obj);
  176. if (!this.multipleSymbolizers) {
  177. style.rules = obj.rules;
  178. }
  179. },
  180. "Rule": function(node, obj) {
  181. var config;
  182. if (this.multipleSymbolizers) {
  183. config = {symbolizers: []};
  184. }
  185. var rule = new OpenLayers.Rule(config);
  186. this.readChildNodes(node, rule);
  187. obj.rules.push(rule);
  188. },
  189. "ElseFilter": function(node, rule) {
  190. rule.elseFilter = true;
  191. },
  192. "MinScaleDenominator": function(node, rule) {
  193. rule.minScaleDenominator = parseFloat(this.getChildValue(node));
  194. },
  195. "MaxScaleDenominator": function(node, rule) {
  196. rule.maxScaleDenominator = parseFloat(this.getChildValue(node));
  197. },
  198. "TextSymbolizer": function(node, rule) {
  199. var config = {};
  200. this.readChildNodes(node, config);
  201. if (this.multipleSymbolizers) {
  202. config.zIndex = this.featureTypeCounter;
  203. rule.symbolizers.push(
  204. new OpenLayers.Symbolizer.Text(config)
  205. );
  206. } else {
  207. rule.symbolizer["Text"] = OpenLayers.Util.applyDefaults(
  208. config, rule.symbolizer["Text"]
  209. );
  210. }
  211. },
  212. "LabelPlacement": function(node, symbolizer) {
  213. this.readChildNodes(node, symbolizer);
  214. },
  215. "PointPlacement": function(node, symbolizer) {
  216. var config = {};
  217. this.readChildNodes(node, config);
  218. config.labelRotation = config.rotation;
  219. delete config.rotation;
  220. var labelAlign,
  221. x = symbolizer.labelAnchorPointX,
  222. y = symbolizer.labelAnchorPointY;
  223. if (x <= 1/3) {
  224. labelAlign = 'l';
  225. } else if (x > 1/3 && x < 2/3) {
  226. labelAlign = 'c';
  227. } else if (x >= 2/3) {
  228. labelAlign = 'r';
  229. }
  230. if (y <= 1/3) {
  231. labelAlign += 'b';
  232. } else if (y > 1/3 && y < 2/3) {
  233. labelAlign += 'm';
  234. } else if (y >= 2/3) {
  235. labelAlign += 't';
  236. }
  237. config.labelAlign = labelAlign;
  238. OpenLayers.Util.applyDefaults(symbolizer, config);
  239. },
  240. "AnchorPoint": function(node, symbolizer) {
  241. this.readChildNodes(node, symbolizer);
  242. },
  243. "AnchorPointX": function(node, symbolizer) {
  244. var labelAnchorPointX = this.readers.ogc._expression.call(this, node);
  245. // always string, could be empty string
  246. if(labelAnchorPointX) {
  247. symbolizer.labelAnchorPointX = labelAnchorPointX;
  248. }
  249. },
  250. "AnchorPointY": function(node, symbolizer) {
  251. var labelAnchorPointY = this.readers.ogc._expression.call(this, node);
  252. // always string, could be empty string
  253. if(labelAnchorPointY) {
  254. symbolizer.labelAnchorPointY = labelAnchorPointY;
  255. }
  256. },
  257. "Displacement": function(node, symbolizer) {
  258. this.readChildNodes(node, symbolizer);
  259. },
  260. "DisplacementX": function(node, symbolizer) {
  261. var labelXOffset = this.readers.ogc._expression.call(this, node);
  262. // always string, could be empty string
  263. if(labelXOffset) {
  264. symbolizer.labelXOffset = labelXOffset;
  265. }
  266. },
  267. "DisplacementY": function(node, symbolizer) {
  268. var labelYOffset = this.readers.ogc._expression.call(this, node);
  269. // always string, could be empty string
  270. if(labelYOffset) {
  271. symbolizer.labelYOffset = labelYOffset;
  272. }
  273. },
  274. "LinePlacement": function(node, symbolizer) {
  275. this.readChildNodes(node, symbolizer);
  276. },
  277. "PerpendicularOffset": function(node, symbolizer) {
  278. var labelPerpendicularOffset = this.readers.ogc._expression.call(this, node);
  279. // always string, could be empty string
  280. if(labelPerpendicularOffset) {
  281. symbolizer.labelPerpendicularOffset = labelPerpendicularOffset;
  282. }
  283. },
  284. "Label": function(node, symbolizer) {
  285. var value = this.readers.ogc._expression.call(this, node);
  286. if (value) {
  287. symbolizer.label = value;
  288. }
  289. },
  290. "Font": function(node, symbolizer) {
  291. this.readChildNodes(node, symbolizer);
  292. },
  293. "Halo": function(node, symbolizer) {
  294. // halo has a fill, so send fresh object
  295. var obj = {};
  296. this.readChildNodes(node, obj);
  297. symbolizer.haloRadius = obj.haloRadius;
  298. symbolizer.haloColor = obj.fillColor;
  299. symbolizer.haloOpacity = obj.fillOpacity;
  300. },
  301. "Radius": function(node, symbolizer) {
  302. var radius = this.readers.ogc._expression.call(this, node);
  303. if(radius != null) {
  304. // radius is only used for halo
  305. symbolizer.haloRadius = radius;
  306. }
  307. },
  308. "RasterSymbolizer": function(node, rule) {
  309. var config = {};
  310. this.readChildNodes(node, config);
  311. if (this.multipleSymbolizers) {
  312. config.zIndex = this.featureTypeCounter;
  313. rule.symbolizers.push(
  314. new OpenLayers.Symbolizer.Raster(config)
  315. );
  316. } else {
  317. rule.symbolizer["Raster"] = OpenLayers.Util.applyDefaults(
  318. config, rule.symbolizer["Raster"]
  319. );
  320. }
  321. },
  322. "Geometry": function(node, obj) {
  323. obj.geometry = {};
  324. this.readChildNodes(node, obj.geometry);
  325. },
  326. "ColorMap": function(node, symbolizer) {
  327. symbolizer.colorMap = [];
  328. this.readChildNodes(node, symbolizer.colorMap);
  329. },
  330. "ColorMapEntry": function(node, colorMap) {
  331. var q = node.getAttribute("quantity");
  332. var o = node.getAttribute("opacity");
  333. colorMap.push({
  334. color: node.getAttribute("color"),
  335. quantity: q !== null ? parseFloat(q) : undefined,
  336. label: node.getAttribute("label") || undefined,
  337. opacity: o !== null ? parseFloat(o) : undefined
  338. });
  339. },
  340. "LineSymbolizer": function(node, rule) {
  341. var config = {};
  342. this.readChildNodes(node, config);
  343. if (this.multipleSymbolizers) {
  344. config.zIndex = this.featureTypeCounter;
  345. rule.symbolizers.push(
  346. new OpenLayers.Symbolizer.Line(config)
  347. );
  348. } else {
  349. rule.symbolizer["Line"] = OpenLayers.Util.applyDefaults(
  350. config, rule.symbolizer["Line"]
  351. );
  352. }
  353. },
  354. "PolygonSymbolizer": function(node, rule) {
  355. var config = {
  356. fill: false,
  357. stroke: false
  358. };
  359. if (!this.multipleSymbolizers) {
  360. config = rule.symbolizer["Polygon"] || config;
  361. }
  362. this.readChildNodes(node, config);
  363. if (this.multipleSymbolizers) {
  364. config.zIndex = this.featureTypeCounter;
  365. rule.symbolizers.push(
  366. new OpenLayers.Symbolizer.Polygon(config)
  367. );
  368. } else {
  369. rule.symbolizer["Polygon"] = config;
  370. }
  371. },
  372. "PointSymbolizer": function(node, rule) {
  373. var config = {
  374. fill: false,
  375. stroke: false,
  376. graphic: false
  377. };
  378. if (!this.multipleSymbolizers) {
  379. config = rule.symbolizer["Point"] || config;
  380. }
  381. this.readChildNodes(node, config);
  382. if (this.multipleSymbolizers) {
  383. config.zIndex = this.featureTypeCounter;
  384. rule.symbolizers.push(
  385. new OpenLayers.Symbolizer.Point(config)
  386. );
  387. } else {
  388. rule.symbolizer["Point"] = config;
  389. }
  390. },
  391. "Stroke": function(node, symbolizer) {
  392. symbolizer.stroke = true;
  393. this.readChildNodes(node, symbolizer);
  394. },
  395. "Fill": function(node, symbolizer) {
  396. symbolizer.fill = true;
  397. this.readChildNodes(node, symbolizer);
  398. },
  399. "CssParameter": function(node, symbolizer) {
  400. var cssProperty = node.getAttribute("name");
  401. var symProperty = this.cssMap[cssProperty];
  402. // for labels, fill should map to fontColor and fill-opacity
  403. // to fontOpacity
  404. if (symbolizer.label) {
  405. if (cssProperty === 'fill') {
  406. symProperty = "fontColor";
  407. } else if (cssProperty === 'fill-opacity') {
  408. symProperty = "fontOpacity";
  409. }
  410. }
  411. if(symProperty) {
  412. // Limited support for parsing of OGC expressions
  413. var value = this.readers.ogc._expression.call(this, node);
  414. // always string, could be an empty string
  415. if(value) {
  416. symbolizer[symProperty] = value;
  417. }
  418. }
  419. },
  420. "Graphic": function(node, symbolizer) {
  421. symbolizer.graphic = true;
  422. var graphic = {};
  423. // painter's order not respected here, clobber previous with next
  424. this.readChildNodes(node, graphic);
  425. // directly properties with names that match symbolizer properties
  426. var properties = [
  427. "stroke", "strokeColor", "strokeWidth", "strokeOpacity",
  428. "strokeLinecap", "fill", "fillColor", "fillOpacity",
  429. "graphicName", "rotation", "graphicFormat"
  430. ];
  431. var prop, value;
  432. for(var i=0, len=properties.length; i<len; ++i) {
  433. prop = properties[i];
  434. value = graphic[prop];
  435. if(value != undefined) {
  436. symbolizer[prop] = value;
  437. }
  438. }
  439. // set other generic properties with specific graphic property names
  440. if(graphic.opacity != undefined) {
  441. symbolizer.graphicOpacity = graphic.opacity;
  442. }
  443. if(graphic.size != undefined) {
  444. var pointRadius = graphic.size / 2;
  445. if (isNaN(pointRadius)) {
  446. // likely a property name
  447. symbolizer.graphicWidth = graphic.size;
  448. } else {
  449. symbolizer.pointRadius = graphic.size / 2;
  450. }
  451. }
  452. if(graphic.href != undefined) {
  453. symbolizer.externalGraphic = graphic.href;
  454. }
  455. if(graphic.rotation != undefined) {
  456. symbolizer.rotation = graphic.rotation;
  457. }
  458. },
  459. "ExternalGraphic": function(node, graphic) {
  460. this.readChildNodes(node, graphic);
  461. },
  462. "Mark": function(node, graphic) {
  463. this.readChildNodes(node, graphic);
  464. },
  465. "WellKnownName": function(node, graphic) {
  466. graphic.graphicName = this.getChildValue(node);
  467. },
  468. "Opacity": function(node, obj) {
  469. var opacity = this.readers.ogc._expression.call(this, node);
  470. // always string, could be empty string
  471. if(opacity) {
  472. obj.opacity = opacity;
  473. }
  474. },
  475. "Size": function(node, obj) {
  476. var size = this.readers.ogc._expression.call(this, node);
  477. // always string, could be empty string
  478. if(size) {
  479. obj.size = size;
  480. }
  481. },
  482. "Rotation": function(node, obj) {
  483. var rotation = this.readers.ogc._expression.call(this, node);
  484. // always string, could be empty string
  485. if(rotation) {
  486. obj.rotation = rotation;
  487. }
  488. },
  489. "OnlineResource": function(node, obj) {
  490. obj.href = this.getAttributeNS(
  491. node, this.namespaces.xlink, "href"
  492. );
  493. },
  494. "Format": function(node, graphic) {
  495. graphic.graphicFormat = this.getChildValue(node);
  496. }
  497. }
  498. }, OpenLayers.Format.Filter.v1_0_0.prototype.readers),
  499. /**
  500. * Property: cssMap
  501. * {Object} Object mapping supported css property names to OpenLayers
  502. * symbolizer property names.
  503. */
  504. cssMap: {
  505. "stroke": "strokeColor",
  506. "stroke-opacity": "strokeOpacity",
  507. "stroke-width": "strokeWidth",
  508. "stroke-linecap": "strokeLinecap",
  509. "stroke-dasharray": "strokeDashstyle",
  510. "fill": "fillColor",
  511. "fill-opacity": "fillOpacity",
  512. "font-family": "fontFamily",
  513. "font-size": "fontSize",
  514. "font-weight": "fontWeight",
  515. "font-style": "fontStyle"
  516. },
  517. /**
  518. * Method: getCssProperty
  519. * Given a symbolizer property, get the corresponding CSS property
  520. * from the <cssMap>.
  521. *
  522. * Parameters:
  523. * sym - {String} A symbolizer property name.
  524. *
  525. * Returns:
  526. * {String} A CSS property name or null if none found.
  527. */
  528. getCssProperty: function(sym) {
  529. var css = null;
  530. for(var prop in this.cssMap) {
  531. if(this.cssMap[prop] == sym) {
  532. css = prop;
  533. break;
  534. }
  535. }
  536. return css;
  537. },
  538. /**
  539. * Method: getGraphicFormat
  540. * Given a href for an external graphic, try to determine the mime-type.
  541. * This method doesn't try too hard, and will fall back to
  542. * <defaultGraphicFormat> if one of the known <graphicFormats> is not
  543. * the file extension of the provided href.
  544. *
  545. * Parameters:
  546. * href - {String}
  547. *
  548. * Returns:
  549. * {String} The graphic format.
  550. */
  551. getGraphicFormat: function(href) {
  552. var format, regex;
  553. for(var key in this.graphicFormats) {
  554. if(this.graphicFormats[key].test(href)) {
  555. format = key;
  556. break;
  557. }
  558. }
  559. return format || this.defaultGraphicFormat;
  560. },
  561. /**
  562. * Property: defaultGraphicFormat
  563. * {String} If none other can be determined from <getGraphicFormat>, this
  564. * default will be returned.
  565. */
  566. defaultGraphicFormat: "image/png",
  567. /**
  568. * Property: graphicFormats
  569. * {Object} Mapping of image mime-types to regular extensions matching
  570. * well-known file extensions.
  571. */
  572. graphicFormats: {
  573. "image/jpeg": /\.jpe?g$/i,
  574. "image/gif": /\.gif$/i,
  575. "image/png": /\.png$/i
  576. },
  577. /**
  578. * Method: write
  579. *
  580. * Parameters:
  581. * sld - {Object} An object representing the SLD.
  582. *
  583. * Returns:
  584. * {DOMElement} The root of an SLD document.
  585. */
  586. write: function(sld) {
  587. return this.writers.sld.StyledLayerDescriptor.apply(this, [sld]);
  588. },
  589. /**
  590. * Property: writers
  591. * As a compliment to the readers property, this structure contains public
  592. * writing functions grouped by namespace alias and named like the
  593. * node names they produce.
  594. */
  595. writers: OpenLayers.Util.applyDefaults({
  596. "sld": {
  597. "_OGCExpression": function(nodeName, value) {
  598. // only the simplest of ogc:expression handled
  599. // {label: "some text and a ${propertyName}"}
  600. var node = this.createElementNSPlus(nodeName);
  601. var tokens = typeof value == "string" ?
  602. value.split("${") :
  603. [value];
  604. node.appendChild(this.createTextNode(tokens[0]));
  605. var item, last;
  606. for(var i=1, len=tokens.length; i<len; i++) {
  607. item = tokens[i];
  608. last = item.indexOf("}");
  609. if(last > 0) {
  610. this.writeNode(
  611. "ogc:PropertyName",
  612. {property: item.substring(0, last)},
  613. node
  614. );
  615. node.appendChild(
  616. this.createTextNode(item.substring(++last))
  617. );
  618. } else {
  619. // no ending }, so this is a literal ${
  620. node.appendChild(
  621. this.createTextNode("${" + item)
  622. );
  623. }
  624. }
  625. return node;
  626. },
  627. "StyledLayerDescriptor": function(sld) {
  628. var root = this.createElementNSPlus(
  629. "sld:StyledLayerDescriptor",
  630. {attributes: {
  631. "version": this.VERSION,
  632. "xsi:schemaLocation": this.schemaLocation
  633. }}
  634. );
  635. // For ArcGIS Server it is necessary to define this
  636. // at the root level (see ticket:2166).
  637. root.setAttribute("xmlns:ogc", this.namespaces.ogc);
  638. root.setAttribute("xmlns:gml", this.namespaces.gml);
  639. // add in optional name
  640. if(sld.name) {
  641. this.writeNode("Name", sld.name, root);
  642. }
  643. // add in optional title
  644. if(sld.title) {
  645. this.writeNode("Title", sld.title, root);
  646. }
  647. // add in optional description
  648. if(sld.description) {
  649. this.writeNode("Abstract", sld.description, root);
  650. }
  651. // add in named layers
  652. // allow namedLayers to be an array
  653. if(OpenLayers.Util.isArray(sld.namedLayers)) {
  654. for(var i=0, len=sld.namedLayers.length; i<len; ++i) {
  655. this.writeNode("NamedLayer", sld.namedLayers[i], root);
  656. }
  657. } else {
  658. for(var name in sld.namedLayers) {
  659. this.writeNode("NamedLayer", sld.namedLayers[name], root);
  660. }
  661. }
  662. return root;
  663. },
  664. "Name": function(name) {
  665. return this.createElementNSPlus("sld:Name", {value: name});
  666. },
  667. "Title": function(title) {
  668. return this.createElementNSPlus("sld:Title", {value: title});
  669. },
  670. "Abstract": function(description) {
  671. return this.createElementNSPlus(
  672. "sld:Abstract", {value: description}
  673. );
  674. },
  675. "NamedLayer": function(layer) {
  676. var node = this.createElementNSPlus("sld:NamedLayer");
  677. // add in required name
  678. this.writeNode("Name", layer.name, node);
  679. // optional sld:LayerFeatureConstraints here
  680. // add in named styles
  681. if(layer.namedStyles) {
  682. for(var i=0, len=layer.namedStyles.length; i<len; ++i) {
  683. this.writeNode(
  684. "NamedStyle", layer.namedStyles[i], node
  685. );
  686. }
  687. }
  688. // add in user styles
  689. if(layer.userStyles) {
  690. for(var i=0, len=layer.userStyles.length; i<len; ++i) {
  691. this.writeNode(
  692. "UserStyle", layer.userStyles[i], node
  693. );
  694. }
  695. }
  696. return node;
  697. },
  698. "NamedStyle": function(name) {
  699. var node = this.createElementNSPlus("sld:NamedStyle");
  700. this.writeNode("Name", name, node);
  701. return node;
  702. },
  703. "UserStyle": function(style) {
  704. var node = this.createElementNSPlus("sld:UserStyle");
  705. // add in optional name
  706. if(style.name) {
  707. this.writeNode("Name", style.name, node);
  708. }
  709. // add in optional title
  710. if(style.title) {
  711. this.writeNode("Title", style.title, node);
  712. }
  713. // add in optional description
  714. if(style.description) {
  715. this.writeNode("Abstract", style.description, node);
  716. }
  717. // add isdefault
  718. if(style.isDefault) {
  719. this.writeNode("IsDefault", style.isDefault, node);
  720. }
  721. // add FeatureTypeStyles
  722. if (this.multipleSymbolizers && style.rules) {
  723. // group style objects by symbolizer zIndex
  724. var rulesByZ = {
  725. 0: []
  726. };
  727. var zValues = [0];
  728. var rule, ruleMap, symbolizer, zIndex, clone;
  729. for (var i=0, ii=style.rules.length; i<ii; ++i) {
  730. rule = style.rules[i];
  731. if (rule.symbolizers) {
  732. ruleMap = {};
  733. for (var j=0, jj=rule.symbolizers.length; j<jj; ++j) {
  734. symbolizer = rule.symbolizers[j];
  735. zIndex = symbolizer.zIndex;
  736. if (!(zIndex in ruleMap)) {
  737. clone = rule.clone();
  738. clone.symbolizers = [];
  739. ruleMap[zIndex] = clone;
  740. }
  741. ruleMap[zIndex].symbolizers.push(symbolizer.clone());
  742. }
  743. for (zIndex in ruleMap) {
  744. if (!(zIndex in rulesByZ)) {
  745. zValues.push(zIndex);
  746. rulesByZ[zIndex] = [];
  747. }
  748. rulesByZ[zIndex].push(ruleMap[zIndex]);
  749. }
  750. } else {
  751. // no symbolizers in rule
  752. rulesByZ[0].push(rule.clone());
  753. }
  754. }
  755. // write one FeatureTypeStyle per zIndex
  756. zValues.sort();
  757. var rules;
  758. for (var i=0, ii=zValues.length; i<ii; ++i) {
  759. rules = rulesByZ[zValues[i]];
  760. if (rules.length > 0) {
  761. clone = style.clone();
  762. clone.rules = rulesByZ[zValues[i]];
  763. this.writeNode("FeatureTypeStyle", clone, node);
  764. }
  765. }
  766. } else {
  767. this.writeNode("FeatureTypeStyle", style, node);
  768. }
  769. return node;
  770. },
  771. "IsDefault": function(bool) {
  772. return this.createElementNSPlus(
  773. "sld:IsDefault", {value: (bool) ? "1" : "0"}
  774. );
  775. },
  776. "FeatureTypeStyle": function(style) {
  777. var node = this.createElementNSPlus("sld:FeatureTypeStyle");
  778. // OpenLayers currently stores no Name, Title, Abstract,
  779. // FeatureTypeName, or SemanticTypeIdentifier information
  780. // related to FeatureTypeStyle
  781. // add in rules
  782. for(var i=0, len=style.rules.length; i<len; ++i) {
  783. this.writeNode("Rule", style.rules[i], node);
  784. }
  785. return node;
  786. },
  787. "Rule": function(rule) {
  788. var node = this.createElementNSPlus("sld:Rule");
  789. // add in optional name
  790. if(rule.name) {
  791. this.writeNode("Name", rule.name, node);
  792. }
  793. // add in optional title
  794. if(rule.title) {
  795. this.writeNode("Title", rule.title, node);
  796. }
  797. // add in optional description
  798. if(rule.description) {
  799. this.writeNode("Abstract", rule.description, node);
  800. }
  801. // add in LegendGraphic here
  802. // add in optional filters
  803. if(rule.elseFilter) {
  804. this.writeNode("ElseFilter", null, node);
  805. } else if(rule.filter) {
  806. this.writeNode("ogc:Filter", rule.filter, node);
  807. }
  808. // add in scale limits
  809. if(rule.minScaleDenominator != undefined) {
  810. this.writeNode(
  811. "MinScaleDenominator", rule.minScaleDenominator, node
  812. );
  813. }
  814. if(rule.maxScaleDenominator != undefined) {
  815. this.writeNode(
  816. "MaxScaleDenominator", rule.maxScaleDenominator, node
  817. );
  818. }
  819. var type, symbolizer;
  820. if (this.multipleSymbolizers && rule.symbolizers) {
  821. var symbolizer;
  822. for (var i=0, ii=rule.symbolizers.length; i<ii; ++i) {
  823. symbolizer = rule.symbolizers[i];
  824. type = symbolizer.CLASS_NAME.split(".").pop();
  825. this.writeNode(
  826. type + "Symbolizer", symbolizer, node
  827. );
  828. }
  829. } else {
  830. // add in symbolizers (relies on geometry type keys)
  831. var types = OpenLayers.Style.SYMBOLIZER_PREFIXES;
  832. for(var i=0, len=types.length; i<len; ++i) {
  833. type = types[i];
  834. symbolizer = rule.symbolizer[type];
  835. if(symbolizer) {
  836. this.writeNode(
  837. type + "Symbolizer", symbolizer, node
  838. );
  839. }
  840. }
  841. }
  842. return node;
  843. },
  844. "ElseFilter": function() {
  845. return this.createElementNSPlus("sld:ElseFilter");
  846. },
  847. "MinScaleDenominator": function(scale) {
  848. return this.createElementNSPlus(
  849. "sld:MinScaleDenominator", {value: scale}
  850. );
  851. },
  852. "MaxScaleDenominator": function(scale) {
  853. return this.createElementNSPlus(
  854. "sld:MaxScaleDenominator", {value: scale}
  855. );
  856. },
  857. "LineSymbolizer": function(symbolizer) {
  858. var node = this.createElementNSPlus("sld:LineSymbolizer");
  859. this.writeNode("Stroke", symbolizer, node);
  860. return node;
  861. },
  862. "Stroke": function(symbolizer) {
  863. var node = this.createElementNSPlus("sld:Stroke");
  864. // GraphicFill here
  865. // GraphicStroke here
  866. // add in CssParameters
  867. if(symbolizer.strokeColor != undefined) {
  868. this.writeNode(
  869. "CssParameter",
  870. {symbolizer: symbolizer, key: "strokeColor"},
  871. node
  872. );
  873. }
  874. if(symbolizer.strokeOpacity != undefined) {
  875. this.writeNode(
  876. "CssParameter",
  877. {symbolizer: symbolizer, key: "strokeOpacity"},
  878. node
  879. );
  880. }
  881. if(symbolizer.strokeWidth != undefined) {
  882. this.writeNode(
  883. "CssParameter",
  884. {symbolizer: symbolizer, key: "strokeWidth"},
  885. node
  886. );
  887. }
  888. if(symbolizer.strokeDashstyle != undefined && symbolizer.strokeDashstyle !== "solid") {
  889. // assumes valid stroke-dasharray value
  890. this.writeNode(
  891. "CssParameter",
  892. {symbolizer: symbolizer, key: "strokeDashstyle"},
  893. node
  894. );
  895. }
  896. if(symbolizer.strokeLinecap != undefined) {
  897. this.writeNode(
  898. "CssParameter",
  899. {symbolizer: symbolizer, key: "strokeLinecap"},
  900. node
  901. );
  902. }
  903. return node;
  904. },
  905. "CssParameter": function(obj) {
  906. // not handling ogc:expressions for now
  907. return this.createElementNSPlus("sld:CssParameter", {
  908. attributes: {name: this.getCssProperty(obj.key)},
  909. value: obj.symbolizer[obj.key]
  910. });
  911. },
  912. "TextSymbolizer": function(symbolizer) {
  913. var node = this.createElementNSPlus("sld:TextSymbolizer");
  914. // add in optional Label
  915. if(symbolizer.label != null) {
  916. this.writeNode("Label", symbolizer.label, node);
  917. }
  918. // add in optional Font
  919. if(symbolizer.fontFamily != null ||
  920. symbolizer.fontSize != null ||
  921. symbolizer.fontWeight != null ||
  922. symbolizer.fontStyle != null) {
  923. this.writeNode("Font", symbolizer, node);
  924. }
  925. // add in optional LabelPlacement
  926. if (symbolizer.labelAnchorPointX != null ||
  927. symbolizer.labelAnchorPointY != null ||
  928. symbolizer.labelAlign != null ||
  929. symbolizer.labelXOffset != null ||
  930. symbolizer.labelYOffset != null ||
  931. symbolizer.labelRotation != null ||
  932. symbolizer.labelPerpendicularOffset != null) {
  933. this.writeNode("LabelPlacement", symbolizer, node);
  934. }
  935. // add in optional Halo
  936. if(symbolizer.haloRadius != null ||
  937. symbolizer.haloColor != null ||
  938. symbolizer.haloOpacity != null) {
  939. this.writeNode("Halo", symbolizer, node);
  940. }
  941. // add in optional Fill
  942. if(symbolizer.fontColor != null ||
  943. symbolizer.fontOpacity != null) {
  944. this.writeNode("Fill", {
  945. fillColor: symbolizer.fontColor,
  946. fillOpacity: symbolizer.fontOpacity
  947. }, node);
  948. }
  949. return node;
  950. },
  951. "LabelPlacement": function(symbolizer) {
  952. var node = this.createElementNSPlus("sld:LabelPlacement");
  953. // PointPlacement and LinePlacement are choices, so don't output both
  954. if ((symbolizer.labelAnchorPointX != null ||
  955. symbolizer.labelAnchorPointY != null ||
  956. symbolizer.labelAlign != null ||
  957. symbolizer.labelXOffset != null ||
  958. symbolizer.labelYOffset != null ||
  959. symbolizer.labelRotation != null) &&
  960. symbolizer.labelPerpendicularOffset == null) {
  961. this.writeNode("PointPlacement", symbolizer, node);
  962. }
  963. if (symbolizer.labelPerpendicularOffset != null) {
  964. this.writeNode("LinePlacement", symbolizer, node);
  965. }
  966. return node;
  967. },
  968. "LinePlacement": function(symbolizer) {
  969. var node = this.createElementNSPlus("sld:LinePlacement");
  970. this.writeNode("PerpendicularOffset", symbolizer.labelPerpendicularOffset, node);
  971. return node;
  972. },
  973. "PerpendicularOffset": function(value) {
  974. return this.createElementNSPlus("sld:PerpendicularOffset", {
  975. value: value
  976. });
  977. },
  978. "PointPlacement": function(symbolizer) {
  979. var node = this.createElementNSPlus("sld:PointPlacement");
  980. if (symbolizer.labelAnchorPointX != null ||
  981. symbolizer.labelAnchorPointY != null ||
  982. symbolizer.labelAlign != null) {
  983. this.writeNode("AnchorPoint", symbolizer, node);
  984. }
  985. if (symbolizer.labelXOffset != null ||
  986. symbolizer.labelYOffset != null) {
  987. this.writeNode("Displacement", symbolizer, node);
  988. }
  989. if (symbolizer.labelRotation != null) {
  990. this.writeNode("Rotation", symbolizer.labelRotation, node);
  991. }
  992. return node;
  993. },
  994. "AnchorPoint": function(symbolizer) {
  995. var node = this.createElementNSPlus("sld:AnchorPoint");
  996. var x = symbolizer.labelAnchorPointX,
  997. y = symbolizer.labelAnchorPointY;
  998. if (x != null) {
  999. this.writeNode("AnchorPointX", x, node);
  1000. }
  1001. if (y != null) {
  1002. this.writeNode("AnchorPointY", y, node);
  1003. }
  1004. if (x == null && y == null) {
  1005. var xAlign = symbolizer.labelAlign.substr(0, 1),
  1006. yAlign = symbolizer.labelAlign.substr(1, 1);
  1007. if (xAlign === "l") {
  1008. x = 0;
  1009. } else if (xAlign === "c") {
  1010. x = 0.5;
  1011. } else if (xAlign === "r") {
  1012. x = 1;
  1013. }
  1014. if (yAlign === "b") {
  1015. y = 0;
  1016. } else if (yAlign === "m") {
  1017. y = 0.5;
  1018. } else if (yAlign === "t") {
  1019. y = 1;
  1020. }
  1021. this.writeNode("AnchorPointX", x, node);
  1022. this.writeNode("AnchorPointY", y, node);
  1023. }
  1024. return node;
  1025. },
  1026. "AnchorPointX": function(value) {
  1027. return this.createElementNSPlus("sld:AnchorPointX", {
  1028. value: value
  1029. });
  1030. },
  1031. "AnchorPointY": function(value) {
  1032. return this.createElementNSPlus("sld:AnchorPointY", {
  1033. value: value
  1034. });
  1035. },
  1036. "Displacement": function(symbolizer) {
  1037. var node = this.createElementNSPlus("sld:Displacement");
  1038. if (symbolizer.labelXOffset != null) {
  1039. this.writeNode("DisplacementX", symbolizer.labelXOffset, node);
  1040. }
  1041. if (symbolizer.labelYOffset != null) {
  1042. this.writeNode("DisplacementY", symbolizer.labelYOffset, node);
  1043. }
  1044. return node;
  1045. },
  1046. "DisplacementX": function(value) {
  1047. return this.createElementNSPlus("sld:DisplacementX", {
  1048. value: value
  1049. });
  1050. },
  1051. "DisplacementY": function(value) {
  1052. return this.createElementNSPlus("sld:DisplacementY", {
  1053. value: value
  1054. });
  1055. },
  1056. "Font": function(symbolizer) {
  1057. var node = this.createElementNSPlus("sld:Font");
  1058. // add in CssParameters
  1059. if(symbolizer.fontFamily) {
  1060. this.writeNode(
  1061. "CssParameter",
  1062. {symbolizer: symbolizer, key: "fontFamily"},
  1063. node
  1064. );
  1065. }
  1066. if(symbolizer.fontSize) {
  1067. this.writeNode(
  1068. "CssParameter",
  1069. {symbolizer: symbolizer, key: "fontSize"},
  1070. node
  1071. );
  1072. }
  1073. if(symbolizer.fontWeight) {
  1074. this.writeNode(
  1075. "CssParameter",
  1076. {symbolizer: symbolizer, key: "fontWeight"},
  1077. node
  1078. );
  1079. }
  1080. if(symbolizer.fontStyle) {
  1081. this.writeNode(
  1082. "CssParameter",
  1083. {symbolizer: symbolizer, key: "fontStyle"},
  1084. node
  1085. );
  1086. }
  1087. return node;
  1088. },
  1089. "Label": function(label) {
  1090. return this.writers.sld._OGCExpression.call(
  1091. this, "sld:Label", label
  1092. );
  1093. },
  1094. "Halo": function(symbolizer) {
  1095. var node = this.createElementNSPlus("sld:Halo");
  1096. if(symbolizer.haloRadius) {
  1097. this.writeNode("Radius", symbolizer.haloRadius, node);
  1098. }
  1099. if(symbolizer.haloColor || symbolizer.haloOpacity) {
  1100. this.writeNode("Fill", {
  1101. fillColor: symbolizer.haloColor,
  1102. fillOpacity: symbolizer.haloOpacity
  1103. }, node);
  1104. }
  1105. return node;
  1106. },
  1107. "Radius": function(value) {
  1108. return this.createElementNSPlus("sld:Radius", {
  1109. value: value
  1110. });
  1111. },
  1112. "RasterSymbolizer": function(symbolizer) {
  1113. var node = this.createElementNSPlus("sld:RasterSymbolizer");
  1114. if (symbolizer.geometry) {
  1115. this.writeNode("Geometry", symbolizer.geometry, node);
  1116. }
  1117. if (symbolizer.opacity) {
  1118. this.writeNode("Opacity", symbolizer.opacity, node);
  1119. }
  1120. if (symbolizer.colorMap) {
  1121. this.writeNode("ColorMap", symbolizer.colorMap, node);
  1122. }
  1123. return node;
  1124. },
  1125. "Geometry": function(geometry) {
  1126. var node = this.createElementNSPlus("sld:Geometry");
  1127. if (geometry.property) {
  1128. this.writeNode("ogc:PropertyName", geometry, node);
  1129. }
  1130. return node;
  1131. },
  1132. "ColorMap": function(colorMap) {
  1133. var node = this.createElementNSPlus("sld:ColorMap");
  1134. for (var i=0, len=colorMap.length; i<len; ++i) {
  1135. this.writeNode("ColorMapEntry", colorMap[i], node);
  1136. }
  1137. return node;
  1138. },
  1139. "ColorMapEntry": function(colorMapEntry) {
  1140. var node = this.createElementNSPlus("sld:ColorMapEntry");
  1141. var a = colorMapEntry;
  1142. node.setAttribute("color", a.color);
  1143. a.opacity !== undefined && node.setAttribute("opacity",
  1144. parseFloat(a.opacity));
  1145. a.quantity !== undefined && node.setAttribute("quantity",
  1146. parseFloat(a.quantity));
  1147. a.label !== undefined && node.setAttribute("label", a.label);
  1148. return node;
  1149. },
  1150. "PolygonSymbolizer": function(symbolizer) {
  1151. var node = this.createElementNSPlus("sld:PolygonSymbolizer");
  1152. if(symbolizer.fill !== false) {
  1153. this.writeNode("Fill", symbolizer, node);
  1154. }
  1155. if(symbolizer.stroke !== false) {
  1156. this.writeNode("Stroke", symbolizer, node);
  1157. }
  1158. return node;
  1159. },
  1160. "Fill": function(symbolizer) {
  1161. var node = this.createElementNSPlus("sld:Fill");
  1162. // GraphicFill here
  1163. // add in CssParameters
  1164. if(symbolizer.fillColor) {
  1165. this.writeNode(
  1166. "CssParameter",
  1167. {symbolizer: symbolizer, key: "fillColor"},
  1168. node
  1169. );
  1170. }
  1171. if(symbolizer.fillOpacity != null) {
  1172. this.writeNode(
  1173. "CssParameter",
  1174. {symbolizer: symbolizer, key: "fillOpacity"},
  1175. node
  1176. );
  1177. }
  1178. return node;
  1179. },
  1180. "PointSymbolizer": function(symbolizer) {
  1181. var node = this.createElementNSPlus("sld:PointSymbolizer");
  1182. this.writeNode("Graphic", symbolizer, node);
  1183. return node;
  1184. },
  1185. "Graphic": function(symbolizer) {
  1186. var node = this.createElementNSPlus("sld:Graphic");
  1187. if(symbolizer.externalGraphic != undefined) {
  1188. this.writeNode("ExternalGraphic", symbolizer, node);
  1189. } else {
  1190. this.writeNode("Mark", symbolizer, node);
  1191. }
  1192. if(symbolizer.graphicOpacity != undefined) {
  1193. this.writeNode("Opacity", symbolizer.graphicOpacity, node);
  1194. }
  1195. if(symbolizer.pointRadius != undefined) {
  1196. this.writeNode("Size", symbolizer.pointRadius * 2, node);
  1197. } else if (symbolizer.graphicWidth != undefined) {
  1198. this.writeNode("Size", symbolizer.graphicWidth, node);
  1199. }
  1200. if(symbolizer.rotation != undefined) {
  1201. this.writeNode("Rotation", symbolizer.rotation, node);
  1202. }
  1203. return node;
  1204. },
  1205. "ExternalGraphic": function(symbolizer) {
  1206. var node = this.createElementNSPlus("sld:ExternalGraphic");
  1207. this.writeNode(
  1208. "OnlineResource", symbolizer.externalGraphic, node
  1209. );
  1210. var format = symbolizer.graphicFormat ||
  1211. this.getGraphicFormat(symbolizer.externalGraphic);
  1212. this.writeNode("Format", format, node);
  1213. return node;
  1214. },
  1215. "Mark": function(symbolizer) {
  1216. var node = this.createElementNSPlus("sld:Mark");
  1217. if(symbolizer.graphicName) {
  1218. this.writeNode("WellKnownName", symbolizer.graphicName, node);
  1219. }
  1220. if (symbolizer.fill !== false) {
  1221. this.writeNode("Fill", symbolizer, node);
  1222. }
  1223. if (symbolizer.stroke !== false) {
  1224. this.writeNode("Stroke", symbolizer, node);
  1225. }
  1226. return node;
  1227. },
  1228. "WellKnownName": function(name) {
  1229. return this.createElementNSPlus("sld:WellKnownName", {
  1230. value: name
  1231. });
  1232. },
  1233. "Opacity": function(value) {
  1234. return this.createElementNSPlus("sld:Opacity", {
  1235. value: value
  1236. });
  1237. },
  1238. "Size": function(value) {
  1239. return this.writers.sld._OGCExpression.call(
  1240. this, "sld:Size", value
  1241. );
  1242. },
  1243. "Rotation": function(value) {
  1244. return this.createElementNSPlus("sld:Rotation", {
  1245. value: value
  1246. });
  1247. },
  1248. "OnlineResource": function(href) {
  1249. return this.createElementNSPlus("sld:OnlineResource", {
  1250. attributes: {
  1251. "xlink:type": "simple",
  1252. "xlink:href": href
  1253. }
  1254. });
  1255. },
  1256. "Format": function(format) {
  1257. return this.createElementNSPlus("sld:Format", {
  1258. value: format
  1259. });
  1260. }
  1261. }
  1262. }, OpenLayers.Format.Filter.v1_0_0.prototype.writers),
  1263. CLASS_NAME: "OpenLayers.Format.SLD.v1"
  1264. });