1 /* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
2 * license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
3 * full text of the license. */
6 * @requires OpenLayers/Format/WMC.js
7 * @requires OpenLayers/Format/XML.js
11 * Class: OpenLayers.Format.WMC.v1
12 * Superclass for WMC version 1 parsers.
15 * - <OpenLayers.Format.XML>
17 OpenLayers.Format.WMC.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
20 * Property: namespaces
21 * {Object} Mapping of namespace aliases to namespace URIs.
24 ol: "http://openlayers.org/context",
25 wmc: "http://www.opengis.net/context",
26 sld: "http://www.opengis.net/sld",
27 xlink: "http://www.w3.org/1999/xlink",
28 xsi: "http://www.w3.org/2001/XMLSchema-instance"
32 * Property: schemaLocation
33 * {String} Schema location for a particular minor version.
38 * Method: getNamespacePrefix
39 * Get the namespace prefix for a given uri from the <namespaces> object.
42 * {String} A namespace prefix or null if none found.
44 getNamespacePrefix: function(uri) {
47 prefix = this.namespaces[this.defaultPrefix];
49 for(prefix in this.namespaces) {
50 if(this.namespaces[prefix] == uri) {
59 * Property: defaultPrefix
64 * Property: rootPrefix
65 * {String} Prefix on the root node that maps to the context namespace URI.
70 * Property: defaultStyleName
71 * {String} Style name used if layer has no style param. Default is "".
76 * Property: defaultStyleTitle
77 * {String} Default style title. Default is "Default".
79 defaultStyleTitle: "Default",
82 * Constructor: OpenLayers.Format.WMC.v1
83 * Instances of this class are not created directly. Use the
84 * <OpenLayers.Format.WMC> constructor instead.
87 * options - {Object} An optional object whose properties will be set on
90 initialize: function(options) {
91 OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
96 * Read capabilities data from a string, and return a list of layers.
99 * data - {String} or {DOMElement} data to read/parse.
102 * {Array} List of named layers.
104 read: function(data) {
105 if(typeof data == "string") {
106 data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
108 var root = data.documentElement;
109 this.rootPrefix = root.prefix;
111 version: root.getAttribute("version")
113 this.runChildNodes(context, root);
118 * Method: runChildNodes
120 runChildNodes: function(obj, node) {
121 var children = node.childNodes;
122 var childNode, processor, prefix, local;
123 for(var i=0, len=children.length; i<len; ++i) {
124 childNode = children[i];
125 if(childNode.nodeType == 1) {
126 prefix = this.getNamespacePrefix(childNode.namespaceURI);
127 local = childNode.nodeName.split(":").pop();
128 processor = this["read_" + prefix + "_" + local];
130 processor.apply(this, [obj, childNode]);
137 * Method: read_wmc_General
139 read_wmc_General: function(context, node) {
140 this.runChildNodes(context, node);
144 * Method: read_wmc_BoundingBox
146 read_wmc_BoundingBox: function(context, node) {
147 context.projection = node.getAttribute("SRS");
148 context.bounds = new OpenLayers.Bounds(
149 parseFloat(node.getAttribute("minx")),
150 parseFloat(node.getAttribute("miny")),
151 parseFloat(node.getAttribute("maxx")),
152 parseFloat(node.getAttribute("maxy"))
157 * Method: read_wmc_LayerList
159 read_wmc_LayerList: function(context, node) {
161 this.runChildNodes(context, node);
165 * Method: read_wmc_Layer
167 read_wmc_Layer: function(context, node) {
169 params: this.layerParams || {},
171 visibility: (node.getAttribute("hidden") != "1"),
172 queryable: (node.getAttribute("queryable") == "1")
178 this.runChildNodes(layerInfo, node);
179 // set properties common to multiple objects on layer options/params
180 layerInfo.params.layers = layerInfo.name;
181 layerInfo.options.maxExtent = layerInfo.maxExtent;
183 var layer = this.getLayerFromInfo(layerInfo);
184 context.layers.push(layer);
188 * Method: getLayerFromInfo
189 * Create a WMS layer from a layerInfo object.
192 * layerInfo - {Object} An object representing a WMS layer.
195 * {<OpenLayers.Layer.WMS>} A WMS layer.
197 getLayerFromInfo: function(layerInfo) {
198 var options = layerInfo.options;
199 if (this.layerOptions) {
200 OpenLayers.Util.applyDefaults(options, this.layerOptions);
202 var layer = new OpenLayers.Layer.WMS(
212 * Method: read_wmc_Extension
214 read_wmc_Extension: function(obj, node) {
215 this.runChildNodes(obj, node);
219 * Method: read_ol_units
221 read_ol_units: function(layerInfo, node) {
222 layerInfo.options.units = this.getChildValue(node);
226 * Method: read_ol_maxExtent
228 read_ol_maxExtent: function(obj, node) {
229 var bounds = new OpenLayers.Bounds(
230 node.getAttribute("minx"), node.getAttribute("miny"),
231 node.getAttribute("maxx"), node.getAttribute("maxy")
233 obj.maxExtent = bounds;
237 * Method: read_ol_transparent
239 read_ol_transparent: function(layerInfo, node) {
240 layerInfo.params.transparent = this.getChildValue(node);
244 * Method: read_ol_numZoomLevels
246 read_ol_numZoomLevels: function(layerInfo, node) {
247 layerInfo.options.numZoomLevels = parseInt(this.getChildValue(node));
251 * Method: read_ol_opacity
253 read_ol_opacity: function(layerInfo, node) {
254 layerInfo.options.opacity = parseFloat(this.getChildValue(node));
258 * Method: read_ol_singleTile
260 read_ol_singleTile: function(layerInfo, node) {
261 layerInfo.options.singleTile = (this.getChildValue(node) == "true");
265 * Method: read_ol_isBaseLayer
267 read_ol_isBaseLayer: function(layerInfo, node) {
268 layerInfo.options.isBaseLayer = (this.getChildValue(node) == "true");
272 * Method: read_ol_displayInLayerSwitcher
274 read_ol_displayInLayerSwitcher: function(layerInfo, node) {
275 layerInfo.options.displayInLayerSwitcher =
276 (this.getChildValue(node) == "true");
280 * Method: read_wmc_Server
282 read_wmc_Server: function(layerInfo, node) {
283 layerInfo.params.version = node.getAttribute("version");
284 this.runChildNodes(layerInfo, node);
288 * Method: read_wmc_FormatList
290 read_wmc_FormatList: function(layerInfo, node) {
291 this.runChildNodes(layerInfo, node);
295 * Method: read_wmc_Format
297 read_wmc_Format: function(layerInfo, node) {
298 var format = this.getChildValue(node);
299 layerInfo.formats.push(format);
300 if(node.getAttribute("current") == "1") {
301 layerInfo.params.format = format;
306 * Method: read_wmc_StyleList
308 read_wmc_StyleList: function(layerInfo, node) {
309 this.runChildNodes(layerInfo, node);
313 * Method: read_wmc_Style
315 read_wmc_Style: function(layerInfo, node) {
317 this.runChildNodes(style, node);
318 if(node.getAttribute("current") == "1") {
319 // three style types to consider
323 // running child nodes always gets name, optionally gets href or body
325 layerInfo.params.sld = style.href;
326 } else if(style.body) {
327 layerInfo.params.sld_body = style.body;
329 layerInfo.params.styles = style.name;
332 layerInfo.styles.push(style);
336 * Method: read_wmc_SLD
338 read_wmc_SLD: function(style, node) {
339 this.runChildNodes(style, node);
340 // style either comes back with an href or a body property
344 * Method: read_sld_StyledLayerDescriptor
346 read_sld_StyledLayerDescriptor: function(sld, node) {
347 var xml = OpenLayers.Format.XML.prototype.write.apply(this, [node]);
352 * Method: read_wmc_OnlineResource
354 read_wmc_OnlineResource: function(obj, node) {
355 obj.href = this.getAttributeNS(
356 node, this.namespaces.xlink, "href"
361 * Method: read_wmc_Name
363 read_wmc_Name: function(obj, node) {
364 var name = this.getChildValue(node);
371 * Method: read_wmc_Title
373 read_wmc_Title: function(obj, node) {
374 var title = this.getChildValue(node);
381 * Method: read_wmc_MetadataURL
383 read_wmc_MetadataURL: function(layerInfo, node) {
384 var metadataURL = {};
385 var links = node.getElementsByTagName("OnlineResource");
386 if(links.length > 0) {
387 this.read_wmc_OnlineResource(metadataURL, links[0]);
389 layerInfo.options.metadataURL = metadataURL.href;
394 * Method: read_wmc_Abstract
396 read_wmc_Abstract: function(obj, node) {
397 var abst = this.getChildValue(node);
399 obj["abstract"] = abst;
404 * Method: read_wmc_LatLonBoundingBox
406 read_wmc_LatLonBoundingBox: function(layer, node) {
408 parseFloat(node.getAttribute("minx")),
409 parseFloat(node.getAttribute("miny")),
410 parseFloat(node.getAttribute("maxx")),
411 parseFloat(node.getAttribute("maxy"))
416 * Method: read_wmc_LegendURL
418 read_wmc_LegendURL: function(style, node) {
420 width: node.getAttribute('width'),
421 height: node.getAttribute('height')
423 var links = node.getElementsByTagName("OnlineResource");
424 if(links.length > 0) {
425 this.read_wmc_OnlineResource(legend, links[0]);
427 style.legend = legend;
434 * context - {Object} An object representing the map context.
435 * options - {Object} Optional object.
438 * {String} A WMC document string.
440 write: function(context, options) {
441 var root = this.createElementDefaultNS("ViewContext");
442 this.setAttributes(root, {
443 version: this.VERSION,
444 id: (options && typeof options.id == "string") ?
446 OpenLayers.Util.createUniqueID("OpenLayers_Context_")
449 // add schemaLocation attribute
451 root, this.namespaces.xsi,
452 "xsi:schemaLocation", this.schemaLocation
455 // required General element
456 root.appendChild(this.write_wmc_General(context));
458 // required LayerList element
459 root.appendChild(this.write_wmc_LayerList(context));
461 return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
465 * Method: createElementDefaultNS
466 * Shorthand for createElementNS with namespace from <defaultPrefix>.
467 * Can optionally be used to set attributes and a text child value.
470 * name - {String} The qualified node name.
471 * childValue - {String} Optional value for text child node.
472 * attributes - {Object} Optional object representing attributes.
475 * {Element} An element node.
477 createElementDefaultNS: function(name, childValue, attributes) {
478 var node = this.createElementNS(
479 this.namespaces[this.defaultPrefix],
483 node.appendChild(this.createTextNode(childValue));
486 this.setAttributes(node, attributes);
492 * Method: setAttributes
493 * Set multiple attributes given key value pairs from an object.
496 * node - {Element} An element node.
497 * obj - {Object} An object whose properties represent attribute names and
498 * values represent attribute values.
500 setAttributes: function(node, obj) {
502 for(var name in obj) {
503 value = obj[name].toString();
504 if(value.match(/[A-Z]/)) {
505 // safari lowercases attributes with setAttribute
506 this.setAttributeNS(node, null, name, value);
508 node.setAttribute(name, value);
514 * Method: write_wmc_General
515 * Create a General node given an context object.
518 * context - {Object} Context object.
521 * {Element} A WMC General element node.
523 write_wmc_General: function(context) {
524 var node = this.createElementDefaultNS("General");
526 // optional Window element
528 node.appendChild(this.createElementDefaultNS(
531 width: context.size.w,
532 height: context.size.h
537 // required BoundingBox element
538 var bounds = context.bounds;
539 node.appendChild(this.createElementDefaultNS(
542 minx: bounds.left.toPrecision(10),
543 miny: bounds.bottom.toPrecision(10),
544 maxx: bounds.right.toPrecision(10),
545 maxy: bounds.top.toPrecision(10),
546 SRS: context.projection
550 // required Title element
551 node.appendChild(this.createElementDefaultNS(
552 "Title", context.title
555 // OpenLayers specific map properties
556 node.appendChild(this.write_ol_MapExtension(context));
562 * Method: write_ol_MapExtension
564 write_ol_MapExtension: function(context) {
565 var node = this.createElementDefaultNS("Extension");
567 var bounds = context.maxExtent;
569 var maxExtent = this.createElementNS(
570 this.namespaces.ol, "ol:maxExtent"
572 this.setAttributes(maxExtent, {
573 minx: bounds.left.toPrecision(10),
574 miny: bounds.bottom.toPrecision(10),
575 maxx: bounds.right.toPrecision(10),
576 maxy: bounds.top.toPrecision(10)
578 node.appendChild(maxExtent);
585 * Method: write_wmc_LayerList
586 * Create a LayerList node given an context object.
589 * context - {Object} Context object.
592 * {Element} A WMC LayerList element node.
594 write_wmc_LayerList: function(context) {
595 var list = this.createElementDefaultNS("LayerList");
598 for(var i=0, len=context.layers.length; i<len; ++i) {
599 layer = context.layers[i];
600 if(layer instanceof OpenLayers.Layer.WMS) {
601 list.appendChild(this.write_wmc_Layer(layer));
609 * Method: write_wmc_Layer
610 * Create a Layer node given a layer object.
613 * layer - {<OpenLayers.Layer.WMS>} Layer object.
616 * {Element} A WMC Layer element node.
618 write_wmc_Layer: function(layer) {
619 var node = this.createElementDefaultNS(
621 queryable: layer.queryable ? "1" : "0",
622 hidden: layer.visibility ? "0" : "1"
626 // required Server element
627 node.appendChild(this.write_wmc_Server(layer));
629 // required Name element
630 node.appendChild(this.createElementDefaultNS(
631 "Name", layer.params["LAYERS"]
634 // required Title element
635 node.appendChild(this.createElementDefaultNS(
639 // optional MetadataURL element
640 if (layer.metadataURL) {
641 node.appendChild(this.write_wmc_MetadataURL(layer));
644 // optional FormatList element
645 node.appendChild(this.write_wmc_FormatList(layer));
647 // optional StyleList element
648 node.appendChild(this.write_wmc_StyleList(layer));
650 // OpenLayers specific properties go in an Extension element
651 node.appendChild(this.write_wmc_LayerExtension(layer));
657 * Method: write_wmc_LayerExtension
658 * Add OpenLayers specific layer parameters to an Extension element.
661 * layer - {<OpenLayers.Layer.WMS>} A WMS layer.
664 * {Element} A WMC Extension element (for a layer).
666 write_wmc_LayerExtension: function(layer) {
667 var node = this.createElementDefaultNS("Extension");
669 var bounds = layer.maxExtent;
670 var maxExtent = this.createElementNS(
671 this.namespaces.ol, "ol:maxExtent"
673 this.setAttributes(maxExtent, {
674 minx: bounds.left.toPrecision(10),
675 miny: bounds.bottom.toPrecision(10),
676 maxx: bounds.right.toPrecision(10),
677 maxy: bounds.top.toPrecision(10)
679 node.appendChild(maxExtent);
681 var param = layer.params["TRANSPARENT"];
683 var trans = this.createElementNS(
684 this.namespaces.ol, "ol:transparent"
686 trans.appendChild(this.createTextNode(param));
687 node.appendChild(trans);
691 "numZoomLevels", "units", "isBaseLayer",
692 "opacity", "displayInLayerSwitcher", "singleTile"
695 for(var i=0, len=properties.length; i<len; ++i) {
696 child = this.createOLPropertyNode(layer, properties[i]);
698 node.appendChild(child);
706 * Method: createOLPropertyNode
707 * Create a node representing an OpenLayers property. If the property is
708 * null or undefined, null will be returned.
711 * object - {Object} An object.
712 * prop - {String} A property.
715 * {Element} A property node.
717 createOLPropertyNode: function(obj, prop) {
719 if(obj[prop] != null) {
720 node = this.createElementNS(this.namespaces.ol, "ol:" + prop);
721 node.appendChild(this.createTextNode(obj[prop].toString()));
727 * Method: write_wmc_Server
728 * Create a Server node given a layer object.
731 * layer - {<OpenLayers.Layer.WMS>} Layer object.
734 * {Element} A WMC Server element node.
736 write_wmc_Server: function(layer) {
737 var node = this.createElementDefaultNS("Server");
738 this.setAttributes(node, {
740 version: layer.params["VERSION"]
743 // required OnlineResource element
744 node.appendChild(this.write_wmc_OnlineResource(layer.url));
750 * Method: write_wmc_MetadataURL
751 * Create a MetadataURL node given a layer object.
754 * layer - {<OpenLayers.Layer.WMS>} Layer object.
757 * {Element} A WMC metadataURL element node.
759 write_wmc_MetadataURL: function(layer) {
760 var node = this.createElementDefaultNS("MetadataURL");
762 // required OnlineResource element
763 node.appendChild(this.write_wmc_OnlineResource(layer.metadataURL));
769 * Method: write_wmc_FormatList
770 * Create a FormatList node given a layer.
773 * layer - {<OpenLayers.Layer.WMS>} Layer object.
776 * {Element} A WMC FormatList element node.
778 write_wmc_FormatList: function(layer) {
779 var node = this.createElementDefaultNS("FormatList");
780 node.appendChild(this.createElementDefaultNS(
781 "Format", layer.params["FORMAT"], {current: "1"}
788 * Method: write_wmc_StyleList
789 * Create a StyleList node given a layer.
792 * layer - {<OpenLayers.Layer.WMS>} Layer object.
795 * {Element} A WMC StyleList element node.
797 write_wmc_StyleList: function(layer) {
798 var node = this.createElementDefaultNS("StyleList");
799 var style = this.createElementDefaultNS(
800 "Style", null, {current: "1"}
803 // Style can come from one of three places (prioritized as below):
804 // 1) an SLD parameter
805 // 2) and SLD_BODY parameter
806 // 3) the STYLES parameter
808 if(layer.params["SLD"]) {
809 // create link from SLD parameter
810 var sld = this.createElementDefaultNS("SLD");
811 var link = this.write_wmc_OnlineResource(layer.params["SLD"]);
812 sld.appendChild(link);
813 style.appendChild(sld);
814 } else if(layer.params["SLD_BODY"]) {
815 // include sld fragment from SLD_BODY parameter
816 var sld = this.createElementDefaultNS("SLD");
817 var body = layer.params["SLD_BODY"];
818 // read in body as xml doc - assume proper namespace declarations
819 var doc = OpenLayers.Format.XML.prototype.read.apply(this, [body]);
820 // append to StyledLayerDescriptor node
821 var imported = doc.documentElement;
822 if(sld.ownerDocument && sld.ownerDocument.importNode) {
823 imported = sld.ownerDocument.importNode(imported, true);
825 sld.appendChild(imported);
826 style.appendChild(sld);
828 // use name(s) from STYLES parameter
829 var name = layer.params["STYLES"] ?
830 layer.params["STYLES"] : this.defaultStyleName;
832 style.appendChild(this.createElementDefaultNS("Name", name));
833 style.appendChild(this.createElementDefaultNS(
834 "Title", this.defaultStyleTitle
837 node.appendChild(style);
842 * Method: write_wmc_OnlineResource
843 * Create an OnlineResource node given a URL.
846 * href - {String} URL for the resource.
849 * {Element} A WMC OnlineResource element node.
851 write_wmc_OnlineResource: function(href) {
852 var node = this.createElementDefaultNS("OnlineResource");
853 this.setAttributeNS(node, this.namespaces.xlink, "xlink:type", "simple");
854 this.setAttributeNS(node, this.namespaces.xlink, "xlink:href", href);
858 CLASS_NAME: "OpenLayers.Format.WMC.v1"