diff options
Diffstat (limited to 'misc/openlayers/lib/OpenLayers/Format/GeoRSS.js')
-rw-r--r-- | misc/openlayers/lib/OpenLayers/Format/GeoRSS.js | 409 |
1 files changed, 409 insertions, 0 deletions
diff --git a/misc/openlayers/lib/OpenLayers/Format/GeoRSS.js b/misc/openlayers/lib/OpenLayers/Format/GeoRSS.js new file mode 100644 index 0000000..cbbb4d8 --- /dev/null +++ b/misc/openlayers/lib/OpenLayers/Format/GeoRSS.js @@ -0,0 +1,409 @@ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for + * full list of contributors). Published under the 2-clause BSD license. + * See license.txt in the OpenLayers distribution or repository for the + * full text of the license. */ + +/** + * @requires OpenLayers/Format/XML.js + * @requires OpenLayers/Feature/Vector.js + * @requires OpenLayers/Geometry/Point.js + * @requires OpenLayers/Geometry/LineString.js + * @requires OpenLayers/Geometry/Polygon.js + */ + +/** + * Class: OpenLayers.Format.GeoRSS + * Read/write GeoRSS parser. Create a new instance with the + * <OpenLayers.Format.GeoRSS> constructor. + * + * Inherits from: + * - <OpenLayers.Format.XML> + */ +OpenLayers.Format.GeoRSS = OpenLayers.Class(OpenLayers.Format.XML, { + + /** + * APIProperty: rssns + * {String} RSS namespace to use. Defaults to + * "http://backend.userland.com/rss2" + */ + rssns: "http://backend.userland.com/rss2", + + /** + * APIProperty: featurens + * {String} Feature Attributes namespace. Defaults to + * "http://mapserver.gis.umn.edu/mapserver" + */ + featureNS: "http://mapserver.gis.umn.edu/mapserver", + + /** + * APIProperty: georssns + * {String} GeoRSS namespace to use. Defaults to + * "http://www.georss.org/georss" + */ + georssns: "http://www.georss.org/georss", + + /** + * APIProperty: geons + * {String} W3C Geo namespace to use. Defaults to + * "http://www.w3.org/2003/01/geo/wgs84_pos#" + */ + geons: "http://www.w3.org/2003/01/geo/wgs84_pos#", + + /** + * APIProperty: featureTitle + * {String} Default title for features. Defaults to "Untitled" + */ + featureTitle: "Untitled", + + /** + * APIProperty: featureDescription + * {String} Default description for features. Defaults to "No Description" + */ + featureDescription: "No Description", + + /** + * Property: gmlParse + * {Object} GML Format object for parsing features + * Non-API and only created if necessary + */ + gmlParser: null, + + /** + * APIProperty: xy + * {Boolean} Order of the GML coordinate: true:(x,y) or false:(y,x) + * For GeoRSS the default is (y,x), therefore: false + */ + xy: false, + + /** + * Constructor: OpenLayers.Format.GeoRSS + * Create a new parser for GeoRSS. + * + * Parameters: + * options - {Object} An optional object whose properties will be set on + * this instance. + */ + + /** + * Method: createGeometryFromItem + * Return a geometry from a GeoRSS Item. + * + * Parameters: + * item - {DOMElement} A GeoRSS item node. + * + * Returns: + * {<OpenLayers.Geometry>} A geometry representing the node. + */ + createGeometryFromItem: function(item) { + var point = this.getElementsByTagNameNS(item, this.georssns, "point"); + var lat = this.getElementsByTagNameNS(item, this.geons, 'lat'); + var lon = this.getElementsByTagNameNS(item, this.geons, 'long'); + + var line = this.getElementsByTagNameNS(item, + this.georssns, + "line"); + var polygon = this.getElementsByTagNameNS(item, + this.georssns, + "polygon"); + var where = this.getElementsByTagNameNS(item, + this.georssns, + "where"); + var box = this.getElementsByTagNameNS(item, + this.georssns, + "box"); + + if (point.length > 0 || (lat.length > 0 && lon.length > 0)) { + var location; + if (point.length > 0) { + location = OpenLayers.String.trim( + point[0].firstChild.nodeValue).split(/\s+/); + if (location.length !=2) { + location = OpenLayers.String.trim( + point[0].firstChild.nodeValue).split(/\s*,\s*/); + } + } else { + location = [parseFloat(lat[0].firstChild.nodeValue), + parseFloat(lon[0].firstChild.nodeValue)]; + } + + var geometry = new OpenLayers.Geometry.Point(location[1], location[0]); + + } else if (line.length > 0) { + var coords = OpenLayers.String.trim(this.getChildValue(line[0])).split(/\s+/); + var components = []; + var point; + for (var i=0, len=coords.length; i<len; i+=2) { + point = new OpenLayers.Geometry.Point(coords[i+1], coords[i]); + components.push(point); + } + geometry = new OpenLayers.Geometry.LineString(components); + } else if (polygon.length > 0) { + var coords = OpenLayers.String.trim(this.getChildValue(polygon[0])).split(/\s+/); + var components = []; + var point; + for (var i=0, len=coords.length; i<len; i+=2) { + point = new OpenLayers.Geometry.Point(coords[i+1], coords[i]); + components.push(point); + } + geometry = new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(components)]); + } else if (where.length > 0) { + if (!this.gmlParser) { + this.gmlParser = new OpenLayers.Format.GML({'xy': this.xy}); + } + var feature = this.gmlParser.parseFeature(where[0]); + geometry = feature.geometry; + } else if (box.length > 0) { + var coords = OpenLayers.String.trim(box[0].firstChild.nodeValue).split(/\s+/); + var components = []; + var point; + if (coords.length > 3) { + point = new OpenLayers.Geometry.Point(coords[1], coords[0]); + components.push(point); + point = new OpenLayers.Geometry.Point(coords[1], coords[2]); + components.push(point); + point = new OpenLayers.Geometry.Point(coords[3], coords[2]); + components.push(point); + point = new OpenLayers.Geometry.Point(coords[3], coords[0]); + components.push(point); + point = new OpenLayers.Geometry.Point(coords[1], coords[0]); + components.push(point); + } + geometry = new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(components)]); + } + + if (geometry && this.internalProjection && this.externalProjection) { + geometry.transform(this.externalProjection, + this.internalProjection); + } + + return geometry; + }, + + /** + * Method: createFeatureFromItem + * Return a feature from a GeoRSS Item. + * + * Parameters: + * item - {DOMElement} A GeoRSS item node. + * + * Returns: + * {<OpenLayers.Feature.Vector>} A feature representing the item. + */ + createFeatureFromItem: function(item) { + var geometry = this.createGeometryFromItem(item); + + /* Provide defaults for title and description */ + var title = this._getChildValue(item, "*", "title", this.featureTitle); + + /* First try RSS descriptions, then Atom summaries */ + var description = this._getChildValue( + item, "*", "description", + this._getChildValue(item, "*", "content", + this._getChildValue(item, "*", "summary", this.featureDescription))); + + /* If no link URL is found in the first child node, try the + href attribute */ + var link = this._getChildValue(item, "*", "link"); + if(!link) { + try { + link = this.getElementsByTagNameNS(item, "*", "link")[0].getAttribute("href"); + } catch(e) { + link = null; + } + } + + var id = this._getChildValue(item, "*", "id", null); + + var data = { + "title": title, + "description": description, + "link": link + }; + var feature = new OpenLayers.Feature.Vector(geometry, data); + feature.fid = id; + return feature; + }, + + /** + * Method: _getChildValue + * + * Parameters: + * node - {DOMElement} + * nsuri - {String} Child node namespace uri ("*" for any). + * name - {String} Child node name. + * def - {String} Optional string default to return if no child found. + * + * Returns: + * {String} The value of the first child with the given tag name. Returns + * default value or empty string if none found. + */ + _getChildValue: function(node, nsuri, name, def) { + var value; + var eles = this.getElementsByTagNameNS(node, nsuri, name); + if(eles && eles[0] && eles[0].firstChild + && eles[0].firstChild.nodeValue) { + value = this.getChildValue(eles[0]); + } else { + value = (def == undefined) ? "" : def; + } + return value; + }, + + /** + * APIMethod: read + * Return a list of features from a GeoRSS doc + * + * Parameters: + * doc - {Element} + * + * Returns: + * {Array(<OpenLayers.Feature.Vector>)} + */ + read: function(doc) { + if (typeof doc == "string") { + doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]); + } + + /* Try RSS items first, then Atom entries */ + var itemlist = null; + itemlist = this.getElementsByTagNameNS(doc, '*', 'item'); + if (itemlist.length == 0) { + itemlist = this.getElementsByTagNameNS(doc, '*', 'entry'); + } + + var numItems = itemlist.length; + var features = new Array(numItems); + for(var i=0; i<numItems; i++) { + features[i] = this.createFeatureFromItem(itemlist[i]); + } + return features; + }, + + + /** + * APIMethod: write + * Accept Feature Collection, and return a string. + * + * Parameters: + * features - {Array(<OpenLayers.Feature.Vector>)} List of features to serialize into a string. + */ + write: function(features) { + var georss; + if(OpenLayers.Util.isArray(features)) { + georss = this.createElementNS(this.rssns, "rss"); + for(var i=0, len=features.length; i<len; i++) { + georss.appendChild(this.createFeatureXML(features[i])); + } + } else { + georss = this.createFeatureXML(features); + } + return OpenLayers.Format.XML.prototype.write.apply(this, [georss]); + }, + + /** + * Method: createFeatureXML + * Accept an <OpenLayers.Feature.Vector>, and build a geometry for it. + * + * Parameters: + * feature - {<OpenLayers.Feature.Vector>} + * + * Returns: + * {DOMElement} + */ + createFeatureXML: function(feature) { + var geometryNode = this.buildGeometryNode(feature.geometry); + var featureNode = this.createElementNS(this.rssns, "item"); + var titleNode = this.createElementNS(this.rssns, "title"); + titleNode.appendChild(this.createTextNode(feature.attributes.title ? feature.attributes.title : "")); + var descNode = this.createElementNS(this.rssns, "description"); + descNode.appendChild(this.createTextNode(feature.attributes.description ? feature.attributes.description : "")); + featureNode.appendChild(titleNode); + featureNode.appendChild(descNode); + if (feature.attributes.link) { + var linkNode = this.createElementNS(this.rssns, "link"); + linkNode.appendChild(this.createTextNode(feature.attributes.link)); + featureNode.appendChild(linkNode); + } + for(var attr in feature.attributes) { + if (attr == "link" || attr == "title" || attr == "description") { continue; } + var attrText = this.createTextNode(feature.attributes[attr]); + var nodename = attr; + if (attr.search(":") != -1) { + nodename = attr.split(":")[1]; + } + var attrContainer = this.createElementNS(this.featureNS, "feature:"+nodename); + attrContainer.appendChild(attrText); + featureNode.appendChild(attrContainer); + } + featureNode.appendChild(geometryNode); + return featureNode; + }, + + /** + * Method: buildGeometryNode + * builds a GeoRSS node with a given geometry + * + * Parameters: + * geometry - {<OpenLayers.Geometry>} + * + * Returns: + * {DOMElement} A gml node. + */ + buildGeometryNode: function(geometry) { + if (this.internalProjection && this.externalProjection) { + geometry = geometry.clone(); + geometry.transform(this.internalProjection, + this.externalProjection); + } + var node; + // match Polygon + if (geometry.CLASS_NAME == "OpenLayers.Geometry.Polygon") { + node = this.createElementNS(this.georssns, 'georss:polygon'); + + node.appendChild(this.buildCoordinatesNode(geometry.components[0])); + } + // match LineString + else if (geometry.CLASS_NAME == "OpenLayers.Geometry.LineString") { + node = this.createElementNS(this.georssns, 'georss:line'); + + node.appendChild(this.buildCoordinatesNode(geometry)); + } + // match Point + else if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { + node = this.createElementNS(this.georssns, 'georss:point'); + node.appendChild(this.buildCoordinatesNode(geometry)); + } else { + throw "Couldn't parse " + geometry.CLASS_NAME; + } + return node; + }, + + /** + * Method: buildCoordinatesNode + * + * Parameters: + * geometry - {<OpenLayers.Geometry>} + */ + buildCoordinatesNode: function(geometry) { + var points = null; + + if (geometry.components) { + points = geometry.components; + } + + var path; + if (points) { + var numPoints = points.length; + var parts = new Array(numPoints); + for (var i = 0; i < numPoints; i++) { + parts[i] = points[i].y + " " + points[i].x; + } + path = parts.join(" "); + } else { + path = geometry.y + " " + geometry.x; + } + return this.createTextNode(path); + }, + + CLASS_NAME: "OpenLayers.Format.GeoRSS" +}); |