|
/* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for |
|
* full list of contributors). 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 |
|
* @requires OpenLayers/Format/GML.js |
|
*/ |
|
|
|
/** |
|
* Though required in the full build, if the GML format is excluded, we set |
|
* the namespace here. |
|
*/ |
|
if(!OpenLayers.Format.GML) { |
|
OpenLayers.Format.GML = {}; |
|
} |
|
|
|
/** |
|
* Class: OpenLayers.Format.GML.Base |
|
* Superclass for GML parsers. |
|
* |
|
* Inherits from: |
|
* - <OpenLayers.Format.XML> |
|
*/ |
|
OpenLayers.Format.GML.Base = OpenLayers.Class(OpenLayers.Format.XML, { |
|
|
|
/** |
|
* Property: namespaces |
|
* {Object} Mapping of namespace aliases to namespace URIs. |
|
*/ |
|
namespaces: { |
|
gml: "http://www.opengis.net/gml", |
|
xlink: "http://www.w3.org/1999/xlink", |
|
xsi: "http://www.w3.org/2001/XMLSchema-instance", |
|
wfs: "http://www.opengis.net/wfs" // this is a convenience for reading wfs:FeatureCollection |
|
}, |
|
|
|
/** |
|
* Property: defaultPrefix |
|
*/ |
|
defaultPrefix: "gml", |
|
|
|
/** |
|
* Property: schemaLocation |
|
* {String} Schema location for a particular minor version. |
|
*/ |
|
schemaLocation: null, |
|
|
|
/** |
|
* APIProperty: featureType |
|
* {Array(String) or String} The local (without prefix) feature typeName(s). |
|
*/ |
|
featureType: null, |
|
|
|
/** |
|
* APIProperty: featureNS |
|
* {String} The feature namespace. Must be set in the options at |
|
* construction. |
|
*/ |
|
featureNS: null, |
|
|
|
/** |
|
* APIProperty: geometry |
|
* {String} Name of geometry element. Defaults to "geometry". |
|
*/ |
|
geometryName: "geometry", |
|
|
|
/** |
|
* APIProperty: extractAttributes |
|
* {Boolean} Extract attributes from GML. Default is true. |
|
*/ |
|
extractAttributes: true, |
|
|
|
/** |
|
* APIProperty: srsName |
|
* {String} URI for spatial reference system. This is optional for |
|
* single part geometries and mandatory for collections and multis. |
|
* If set, the srsName attribute will be written for all geometries. |
|
* Default is null. |
|
*/ |
|
srsName: null, |
|
|
|
/** |
|
* APIProperty: xy |
|
* {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x) |
|
* Changing is not recommended, a new Format should be instantiated. |
|
*/ |
|
xy: true, |
|
|
|
/** |
|
* Property: geometryTypes |
|
* {Object} Maps OpenLayers geometry class names to GML element names. |
|
* Use <setGeometryTypes> before accessing this property. |
|
*/ |
|
geometryTypes: null, |
|
|
|
/** |
|
* Property: singleFeatureType |
|
* {Boolean} True if there is only 1 featureType, and not an array |
|
* of featuretypes. |
|
*/ |
|
singleFeatureType: null, |
|
|
|
/** |
|
* 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.GML.Base |
|
* Instances of this class are not created directly. Use the |
|
* <OpenLayers.Format.GML.v2> or <OpenLayers.Format.GML.v3> constructor |
|
* instead. |
|
* |
|
* Parameters: |
|
* options - {Object} An optional object whose properties will be set on |
|
* this instance. |
|
* |
|
* Valid options properties: |
|
* featureType - {Array(String) or String} Local (without prefix) feature |
|
* typeName(s) (required). |
|
* featureNS - {String} Feature namespace (required). |
|
* geometryName - {String} Geometry element name. |
|
*/ |
|
initialize: function(options) { |
|
OpenLayers.Format.XML.prototype.initialize.apply(this, [options]); |
|
this.setGeometryTypes(); |
|
if(options && options.featureNS) { |
|
this.setNamespace("feature", options.featureNS); |
|
} |
|
this.singleFeatureType = !options || (typeof options.featureType === "string"); |
|
}, |
|
|
|
/** |
|
* Method: read |
|
* |
|
* Parameters: |
|
* data - {DOMElement} A gml:featureMember element, a gml:featureMembers |
|
* element, or an element containing either of the above at any level. |
|
* |
|
* Returns: |
|
* {Array(<OpenLayers.Feature.Vector>)} An array of features. |
|
*/ |
|
read: function(data) { |
|
if(typeof data == "string") { |
|
data = OpenLayers.Format.XML.prototype.read.apply(this, [data]); |
|
} |
|
if(data && data.nodeType == 9) { |
|
data = data.documentElement; |
|
} |
|
var features = []; |
|
this.readNode(data, {features: features}); |
|
if(features.length == 0) { |
|
// look for gml:featureMember elements |
|
var elements = this.getElementsByTagNameNS( |
|
data, this.namespaces.gml, "featureMember" |
|
); |
|
if(elements.length) { |
|
for(var i=0, len=elements.length; i<len; ++i) { |
|
this.readNode(elements[i], {features: features}); |
|
} |
|
} else { |
|
// look for gml:featureMembers elements (this is v3, but does no harm here) |
|
var elements = this.getElementsByTagNameNS( |
|
data, this.namespaces.gml, "featureMembers" |
|
); |
|
if(elements.length) { |
|
// there can be only one |
|
this.readNode(elements[0], {features: features}); |
|
} |
|
} |
|
} |
|
return features; |
|
}, |
|
|
|
/** |
|
* Property: readers |
|
* Contains public functions, grouped by namespace prefix, that will |
|
* be applied when a namespaced node is found matching the function |
|
* name. The function will be applied in the scope of this parser |
|
* with two arguments: the node being read and a context object passed |
|
* from the parent. |
|
*/ |
|
readers: { |
|
"gml": { |
|
"featureMember": function(node, obj) { |
|
this.readChildNodes(node, obj); |
|
}, |
|
"featureMembers": function(node, obj) { |
|
this.readChildNodes(node, obj); |
|
}, |
|
"name": function(node, obj) { |
|
obj.name = this.getChildValue(node); |
|
}, |
|
"boundedBy": function(node, obj) { |
|
var container = {}; |
|
this.readChildNodes(node, container); |
|
if(container.components && container.components.length > 0) { |
|
obj.bounds = container.components[0]; |
|
} |
|
}, |
|
"Point": function(node, container) { |
|
var obj = {points: []}; |
|
this.readChildNodes(node, obj); |
|
if(!container.components) { |
|
container.components = []; |
|
} |
|
container.components.push(obj.points[0]); |
|
}, |
|
"coordinates": function(node, obj) { |
|
var str = this.getChildValue(node).replace( |
|
this.regExes.trimSpace, "" |
|
); |
|
str = str.replace(this.regExes.trimComma, ","); |
|
var pointList = str.split(this.regExes.splitSpace); |
|
var coords; |
|
var numPoints = pointList.length; |
|
var points = new Array(numPoints); |
|
for(var i=0; i<numPoints; ++i) { |
|
coords = pointList[i].split(","); |
|
if (this.xy) { |
|
points[i] = new OpenLayers.Geometry.Point( |
|
coords[0], coords[1], coords[2] |
|
); |
|
} else { |
|
points[i] = new OpenLayers.Geometry.Point( |
|
coords[1], coords[0], coords[2] |
|
); |
|
} |
|
} |
|
obj.points = points; |
|
}, |
|
"coord": function(node, obj) { |
|
var coord = {}; |
|
this.readChildNodes(node, coord); |
|
if(!obj.points) { |
|
obj.points = []; |
|
} |
|
obj.points.push(new OpenLayers.Geometry.Point( |
|
coord.x, coord.y, coord.z |
|
)); |
|
}, |
|
"X": function(node, coord) { |
|
coord.x = this.getChildValue(node); |
|
}, |
|
"Y": function(node, coord) { |
|
coord.y = this.getChildValue(node); |
|
}, |
|
"Z": function(node, coord) { |
|
coord.z = this.getChildValue(node); |
|
}, |
|
"MultiPoint": function(node, container) { |
|
var obj = {components: []}; |
|
this.readChildNodes(node, obj); |
|
container.components = [ |
|
new OpenLayers.Geometry.MultiPoint(obj.components) |
|
]; |
|
}, |
|
"pointMember": function(node, obj) { |
|
this.readChildNodes(node, obj); |
|
}, |
|
"LineString": function(node, container) { |
|
var obj = {}; |
|
this.readChildNodes(node, obj); |
|
if(!container.components) { |
|
container.components = []; |
|
} |
|
container.components.push( |
|
new OpenLayers.Geometry.LineString(obj.points) |
|
); |
|
}, |
|
"MultiLineString": function(node, container) { |
|
var obj = {components: []}; |
|
this.readChildNodes(node, obj); |
|
container.components = [ |
|
new OpenLayers.Geometry.MultiLineString(obj.components) |
|
]; |
|
}, |
|
"lineStringMember": function(node, obj) { |
|
this.readChildNodes(node, obj); |
|
}, |
|
"Polygon": function(node, container) { |
|
var obj = {outer: null, inner: []}; |
|
this.readChildNodes(node, obj); |
|
obj.inner.unshift(obj.outer); |
|
if(!container.components) { |
|
container.components = []; |
|
} |
|
container.components.push( |
|
new OpenLayers.Geometry.Polygon(obj.inner) |
|
); |
|
}, |
|
"LinearRing": function(node, obj) { |
|
var container = {}; |
|
this.readChildNodes(node, container); |
|
obj.components = [new OpenLayers.Geometry.LinearRing( |
|
container.points |
|
)]; |
|
}, |
|
"MultiPolygon": function(node, container) { |
|
var obj = {components: []}; |
|
this.readChildNodes(node, obj); |
|
container.components = [ |
|
new OpenLayers.Geometry.MultiPolygon(obj.components) |
|
]; |
|
}, |
|
"polygonMember": function(node, obj) { |
|
this.readChildNodes(node, obj); |
|
}, |
|
"GeometryCollection": function(node, container) { |
|
var obj = {components: []}; |
|
this.readChildNodes(node, obj); |
|
container.components = [ |
|
new OpenLayers.Geometry.Collection(obj.components) |
|
]; |
|
}, |
|
"geometryMember": function(node, obj) { |
|
this.readChildNodes(node, obj); |
|
} |
|
}, |
|
"feature": { |
|
"*": function(node, obj) { |
|
// The node can either be named like the featureType, or it |
|
// can be a child of the feature:featureType. Children can be |
|
// geometry or attributes. |
|
var name; |
|
var local = node.localName || node.nodeName.split(":").pop(); |
|
// Since an attribute can have the same name as the feature type |
|
// we only want to read the node as a feature if the parent |
|
// node can have feature nodes as children. In this case, the |
|
// obj.features property is set. |
|
if (obj.features) { |
|
if (!this.singleFeatureType && |
|
(OpenLayers.Util.indexOf(this.featureType, local) !== -1)) { |
|
name = "_typeName"; |
|
} else if(local === this.featureType) { |
|
name = "_typeName"; |
|
} |
|
} else { |
|
// Assume attribute elements have one child node and that the child |
|
// is a text node. Otherwise assume it is a geometry node. |
|
if(node.childNodes.length == 0 || |
|
(node.childNodes.length == 1 && node.firstChild.nodeType == 3)) { |
|
if(this.extractAttributes) { |
|
name = "_attribute"; |
|
} |
|
} else { |
|
name = "_geometry"; |
|
} |
|
} |
|
if(name) { |
|
this.readers.feature[name].apply(this, [node, obj]); |
|
} |
|
}, |
|
"_typeName": function(node, obj) { |
|
var container = {components: [], attributes: {}}; |
|
this.readChildNodes(node, container); |
|