diff --git a/lib/OpenLayers/Format/WMSGetFeatureInfo.js b/lib/OpenLayers/Format/WMSGetFeatureInfo.js new file mode 100644 index 0000000000..5dba8e325a --- /dev/null +++ b/lib/OpenLayers/Format/WMSGetFeatureInfo.js @@ -0,0 +1,686 @@ +/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD + * license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the + * full text of the license. */ + +/** + * @requires OpenLayers/Format/XML.js + */ + +/** + * Class: OpenLayers.Format.WMSGetFeatureInfo + * Class to read GetFeatureInfo responses from Web Mapping Services + * + * Inherits from: + * - + */ +OpenLayers.Format.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Format.XML, { + + /** + * APIProperty: layerIdentifier + * {String} All xml nodes containing this search criteria will populate an + * internal array of layer nodes. + */ + layerIdentifier: '_layer', + + /** + * APIProperty: featureIdentifier + * {String} All xml nodes containing this search criteria will populate an + * internal array of feature nodes for each layer node found. + */ + featureIdentifier: '_feature', + + /** + * Property: regExes + * Compiled regular expressions for manipulating strings. + */ + regExes: { + trimSpace: (/^\s*|\s*$/g), + removeSpace: (/\s*/g), + splitSpace: (/\s+/), + trimComma: (/\s*,\s*/g) + }, + + /** + * Constructor: OpenLayers.Format.WMSGetFeatureInfo + * Create a new parser for WMS GetFeatureInfo responses + * + * Parameters: + * options - {Object} An optional object whose properties will be set on + * this instance. + */ + initialize: function(options) { + OpenLayers.Format.XML.prototype.initialize.apply(this, arguments); + OpenLayers.Util.extend(this, options); + this.options = options; + }, + + /** + * APIMethod: read + * Read WMS GetFeatureInfo data from a string, and return an array of features + * + * Parameters: + * data - {String} or {DOMElement} data to read/parse. + * + * Returns: + * {Array()} An array of features. + */ + read: function(data) { + var result; + if(typeof data == "string") { + data = OpenLayers.Format.XML.prototype.read.apply(this, [data]); + } + var root = data.documentElement; + var scope = this; + var read = this["read_" + root.nodeName]; + if(read) { + result = read.call(this, root); + } else { + // fall-back to GML since this is a common output format for WMS + // GetFeatureInfo responses + result = new OpenLayers.Format.GML((this.options ? this.options : {})).read(data); + } + return result; + }, + + + /** + * Method: read_msGMLOutput + * Parse msGMLOutput nodes. + * + * Parameters: + * data - {DOMElement} + * + * Returns: + * {Array} + */ + read_msGMLOutput: function(data) { + var response = []; + var layerNodes, n; + layerNodes = this.getSiblingNodesByTagCriteria(data, + this.layerIdentifier); + if (layerNodes) { + n = layerNodes.length; + for (var i = 0; i < n; i++) { + var node = layerNodes[i]; + var layerName = node.nodeName; + if (node.prefix) { + layerName = layerName.split(':')[1]; + } + var layerName = layerName.replace(this.layerIdentifier, ''); + var featureNodes = this.getSiblingNodesByTagCriteria(node, + this.featureIdentifier); + if (featureNodes) { + for (var j = 0; j < featureNodes.length; j++) { + var featureNode = featureNodes[j]; + var geom = null; + var attributes = this.parseAttributes(featureNode); + var feature = new OpenLayers.Feature.Vector(geom, + attributes, null); + feature.type = layerName; + response.push(feature); + } + } + } + } + return response; + }, + + /** + * Method: read_FeatureInfoResponse + * Parse FeatureInfoResponse nodes. + * + * Parameters: + * data - {DOMElement} + * + * Returns: + * {Array} + */ + read_FeatureInfoResponse: function(data) { + var response = []; + var featureNodes = this.getElementsByTagNameNS(data, '*', + 'FIELDS'); + + for(var i=0, len=featureNodes.length;i 0 && tagName.indexOf(criteria) > -1) { + for (var i = 0; i < n; i++) { + child = children[i]; + if (child.nodeType == 1) { + nodes.push(child); + } + } + } + else { + for (var i = 0; i < n; i++) { + matchNodes = this.getSiblingNodesByTagCriteria( + children[i], criteria); + (nodes.length == 0) ? + nodes = matchNodes : nodes.push(matchNodes); + } + } + } + return nodes; + }, + + /** + * Method: parseAttributes + * + * Parameters: + * node - {} + * + * Returns: + * {Object} An attributes object. + * + * Notes: + * Assumes that attributes are direct child xml nodes of the passed node + * and contain only a single text node. + */ + parseAttributes: function(node){ + var attributes = {}; + if (node.nodeType == 1) { + var children = node.childNodes; + n = children.length + for (var i = 0; i < n; ++i) { + var child = children[i]; + if (child.nodeType == 1) { + var grandchildren = child.childNodes; + if (grandchildren.length == 1) { + var grandchild = grandchildren[0]; + if (grandchild.nodeType == 3 || + grandchild.nodeType == 4) { + var name = (child.prefix) ? + child.nodeName.split(":")[1] : child.nodeName; + var value = grandchild.nodeValue.replace( + this.regExes.trimSpace, ""); + attributes[name] = value; + } + } + } + } + } + return attributes; + }, + + CLASS_NAME: "OpenLayers.Format.WMSGetFeatureInfo" + +}); +/** + * @requires OpenLayers/Format/XML.js + **/ + +/** + * Class: OpenLayers.Format.WMSGetFeatureInfo + * Class to read GetFeatureInfo responses from Web Mapping Services + * + * Inherits from: + * - + */ +OpenLayers.Format.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Format.XML, { + + /** + * APIProperty: layerIdentifier + * {String} All xml nodes containing this search criteria will populate an + * internal array of layer nodes. + */ + layerIdentifier: '_layer', + + /** + * APIProperty: featureIdentifier + * {String} All xml nodes containing this search criteria will populate an + * internal array of feature nodes for each layer node found. + */ + featureIdentifier: '_feature', + + /** + * Property: regExes + * Compiled regular expressions for manipulating strings. + */ + regExes: { + trimSpace: (/^\s*|\s*$/g), + removeSpace: (/\s*/g), + splitSpace: (/\s+/), + trimComma: (/\s*,\s*/g) + }, + + /** + * Constructor: OpenLayers.Format.WMSGetFeatureInfo + * Create a new parser for WMS GetFeatureInfo responses + * + * Parameters: + * options - {Object} An optional object whose properties will be set on + * this instance. + */ + initialize: function(options) { + OpenLayers.Format.XML.prototype.initialize.apply(this, arguments); + OpenLayers.Util.extend(this, options); + this.options = options; + }, + + /** + * APIMethod: read + * Read WMS GetFeatureInfo data from a string, and return an array of features + * + * Parameters: + * data - {String} or {DOMElement} data to read/parse. + * + * Returns: + * {Array()} An array of features. + */ + read: function(data) { + var result; + if(typeof data == "string") { + data = OpenLayers.Format.XML.prototype.read.apply(this, [data]); + } + var root = data.documentElement; + var scope = this; + var read = this["read_" + root.nodeName]; + if(read) { + result = read.call(this, root); + } else { + // fall-back to GML since this is a common output format for WMS + // GetFeatureInfo responses + result = new OpenLayers.Format.GML((this.options ? this.options : {})).read(data); + } + return result; + }, + + read_msGMLOutput: function(data) { + var response = []; + var layerNodes, n; + layerNodes = this.getSiblingNodesByTagCriteria(data, + this.layerIdentifier); + if (layerNodes) { + n = layerNodes.length; + for (var i = 0; i < n; i++) { + var node = layerNodes[i]; + var layerName = node.nodeName; + if (node.prefix) { + layerName = layerName.split(':')[1]; + } + var layerName = layerName.replace(this.layerIdentifier, ''); + var featureNodes = this.getSiblingNodesByTagCriteria(node, + this.featureIdentifier); + if (featureNodes) { + for (var j = 0; j < featureNodes.length; j++) { + var featureNode = featureNodes[j]; + var geom = null; + var attributes = this.parseAttributes(featureNode); + var feature = new OpenLayers.Feature.Vector(geom, + attributes, null); + feature.type = layerName; + response.push(feature); + } + } + } + return response; + } + }, + + read_FeatureInfoResponse: function(data) { + var response = []; + var featureNodes = this.getElementsByTagNameNS(data, '*', + 'FIELDS'); + + for(var i=0;i 0 && tagName.indexOf(criteria) > -1) { + for (var i = 0; i < n; i++) { + child = children[i]; + if (child.nodeType == 1) { + nodes.push(child); + } + } + } + else { + for (var i = 0; i < n; i++) { + matchNodes = this.getSiblingNodesByTagCriteria( + children[i], criteria); + (nodes.length == 0) ? + nodes = matchNodes : nodes.push(matchNodes); + } + } + } + return nodes; + }, + + /** + * Method: parseAttributes + * + * Parameters: + * node - {} + * + * Returns: + * {Object} An attributes object. + * + * Notes: + * Assumes that attributes are direct child xml nodes of the passed node + * and contain only a single text node. + */ + parseAttributes: function(node){ + var attributes = {}; + if (node.nodeType == 1) { + var children = node.childNodes; + n = children.length + for (var i = 0; i < n; ++i) { + var child = children[i]; + if (child.nodeType == 1) { + var grandchildren = child.childNodes; + if (grandchildren.length == 1) { + var grandchild = grandchildren[0]; + if (grandchild.nodeType == 3 || + grandchild.nodeType == 4) { + var name = (child.prefix) ? + child.nodeName.split(":")[1] : child.nodeName; + var value = grandchild.nodeValue.replace( + this.regExes.trimSpace, ""); + attributes[name] = value; + } + } + } + } + } + return attributes; + }, + + CLASS_NAME: "OpenLayers.Format.WMSGetFeatureInfo" + +}); +/** + * @requires OpenLayers/Format/XML.js + **/ + +/** + * Class: OpenLayers.Format.WMSGetFeatureInfo + * Class to read GetFeatureInfo responses from Web Mapping Services + * + * Inherits from: + * - + */ +OpenLayers.Format.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Format.XML, { + + /** + * APIProperty: layerIdentifier + * {String} All xml nodes containing this search criteria will populate an + * internal array of layer nodes. + */ + layerIdentifier: '_layer', + + /** + * APIProperty: featureIdentifier + * {String} All xml nodes containing this search criteria will populate an + * internal array of feature nodes for each layer node found. + */ + featureIdentifier: '_feature', + + /** + * Property: regExes + * Compiled regular expressions for manipulating strings. + */ + regExes: { + trimSpace: (/^\s*|\s*$/g), + removeSpace: (/\s*/g), + splitSpace: (/\s+/), + trimComma: (/\s*,\s*/g) + }, + + /** + * Constructor: OpenLayers.Format.WMSGetFeatureInfo + * Create a new parser for WMS GetFeatureInfo responses + * + * Parameters: + * options - {Object} An optional object whose properties will be set on + * this instance. + */ + initialize: function(options) { + OpenLayers.Format.XML.prototype.initialize.apply(this, arguments); + OpenLayers.Util.extend(this, options); + this.options = options; + }, + + /** + * APIMethod: read + * Read WMS GetFeatureInfo data from a string, and return an array of features + * + * Parameters: + * data - {String} or {DOMElement} data to read/parse. + * + * Returns: + * {Array()} An array of features. + */ + read: function(data) { + var result; + if(typeof data == "string") { + data = OpenLayers.Format.XML.prototype.read.apply(this, [data]); + } + var root = data.documentElement; + var scope = this; + var read = this["read_" + root.nodeName]; + if(read) { + result = read.call(this, root); + } else { + // fall-back to GML since this is a common output format for WMS + // GetFeatureInfo responses + result = new OpenLayers.Format.GML((this.options ? this.options : {})).read(data); + } + return result; + }, + + read_msGMLOutput: function(data) { + var response = []; + var layerNodes, n; + layerNodes = this.getSiblingNodesByTagCriteria(data, + this.layerIdentifier); + if (layerNodes) { + n = layerNodes.length; + for (var i = 0; i < n; i++) { + var node = layerNodes[i]; + var layerName = node.nodeName; + if (node.prefix) { + layerName = layerName.split(':')[1]; + } + var layerName = layerName.replace(this.layerIdentifier, ''); + var featureNodes = this.getSiblingNodesByTagCriteria(node, + this.featureIdentifier); + if (featureNodes) { + for (var j = 0; j < featureNodes.length; j++) { + var featureNode = featureNodes[j]; + var geom = null; + var attributes = this.parseAttributes(featureNode); + var feature = new OpenLayers.Feature.Vector(geom, + attributes, null); + feature.type = layerName; + response.push(feature); + } + } + } + return response; + } + }, + + read_FeatureInfoResponse: function(data) { + var response = []; + var featureNodes = this.getElementsByTagNameNS(data, '*', + 'FIELDS'); + + for(var i=0;i 0 && tagName.indexOf(criteria) > -1) { + for (var i = 0; i < n; i++) { + child = children[i]; + if (child.nodeType == 1) { + nodes.push(child); + } + } + } + else { + for (var i = 0; i < n; i++) { + matchNodes = this.getSiblingNodesByTagCriteria( + children[i], criteria); + (nodes.length == 0) ? + nodes = matchNodes : nodes.push(matchNodes); + } + } + } + return nodes; + }, + + /** + * Method: parseAttributes + * + * Parameters: + * node - {} + * + * Returns: + * {Object} An attributes object. + * + * Notes: + * Assumes that attributes are direct child xml nodes of the passed node + * and contain only a single text node. + */ + parseAttributes: function(node){ + var attributes = {}; + if (node.nodeType == 1) { + var children = node.childNodes; + n = children.length + for (var i = 0; i < n; ++i) { + var child = children[i]; + if (child.nodeType == 1) { + var grandchildren = child.childNodes; + if (grandchildren.length == 1) { + var grandchild = grandchildren[0]; + if (grandchild.nodeType == 3 || + grandchild.nodeType == 4) { + var name = (child.prefix) ? + child.nodeName.split(":")[1] : child.nodeName; + var value = grandchild.nodeValue.replace( + this.regExes.trimSpace, ""); + attributes[name] = value; + } + } + } + } + } + return attributes; + }, + + CLASS_NAME: "OpenLayers.Format.WMSGetFeatureInfo" + +}); diff --git a/tests/Format/WMSGetFeatureInfo.html b/tests/Format/WMSGetFeatureInfo.html new file mode 100644 index 0000000000..0c1c02e1a6 --- /dev/null +++ b/tests/Format/WMSGetFeatureInfo.html @@ -0,0 +1,717 @@ + + + + + + + + + + + + + + + + + + + + + + + +