Batch merge for rc2 of 2.7. 'svn merge -r7967:HEAD from trunk (Closes #1733) (Closes #1489) (Closes #1639) (Closes #1718) (Closes #1723) (Closes #1732) (Closes #1616) (Closes #1722)

git-svn-id: http://svn.openlayers.org/branches/openlayers/2.7@8012 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
euzuro
2008-09-12 17:24:20 +00:00
parent a43e98762c
commit f7f338e265
51 changed files with 7219 additions and 90 deletions

View File

@@ -0,0 +1,525 @@
/* 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
*/
/**
* Eventually, this will require the OpenLayers.Format.GML. For now, since
* this parser can be included in a lib without the old GML parser, we
* declare the namespace if it doesn't exist.
*/
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
* {String} The local (without prefix) feature typeName.
*/
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: 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 - {String} Local (without prefix) feature typeName (required).
* featureNS - {String} Feature namespace (required).
* geometryName - {String} Geometry element name.
*/
initialize: function(options) {
OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
this.setNamespace("feature", options.featureNS);
},
/**
* 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);
},
"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.concatChildValues(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();
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 == 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);
var feature = new OpenLayers.Feature.Vector(
container.components[0], container.attributes
);
var fid = node.getAttribute("fid") ||
this.getAttributeNS(node, this.namespaces["gml"], "id");
if(fid) {
feature.fid = fid;
}
if(this.internalProjection && this.externalProjection &&
feature.geometry) {
feature.geometry.transform(
this.externalProjection, this.internalProjection
);
}
obj.features.push(feature);
},
"_geometry": function(node, obj) {
this.readChildNodes(node, obj);
},
"_attribute": function(node, obj) {
var local = node.localName || node.nodeName.split(":").pop();
var value = this.getChildValue(node);
obj.attributes[local] = value;
}
},
"wfs": {
"FeatureCollection": function(node, obj) {
this.readChildNodes(node, obj);
}
}
},
/**
* Method: write
*
* Parameters:
* features - {Array(<OpenLayers.Feature.Vector>) | OpenLayers.Feature.Vector}
* An array of features or a single feature.
*
* Returns:
* {String} Given an array of features, a doc with a gml:featureMembers
* element will be returned. Given a single feature, a doc with a
* gml:featureMember element will be returned.
*/
write: function(features) {
var name;
if(features instanceof Array) {
name = "featureMembers";
} else {
name = "featureMember";
}
var root = this.writeNode("gml:" + name, features);
this.setAttributeNS(
root, this.namespaces["xsi"],
"xsi:schemaLocation", this.schemaLocation
);
return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
},
/**
* Property: writers
* As a compliment to the readers property, this structure contains public
* writing functions grouped by namespace alias and named like the
* node names they produce.
*/
writers: {
"gml": {
"featureMember": function(feature) {
var node = this.createElementNSPlus("gml:featureMember");
this.writeNode("feature:_typeName", feature, node);
return node;
},
"MultiPoint": function(geometry) {
var node = this.createElementNSPlus("gml:MultiPoint");
for(var i=0; i<geometry.components.length; ++i) {
this.writeNode("pointMember", geometry.components[i], node);
}
return node;
},
"pointMember": function(geometry) {
var node = this.createElementNSPlus("gml:pointMember");
this.writeNode("Point", geometry, node);
return node;
},
"MultiLineString": function(geometry) {
var node = this.createElementNSPlus("gml:MultiLineString");
for(var i=0; i<geometry.components.length; ++i) {
this.writeNode("lineStringMember", geometry.components[i], node);
}
return node;
},
"lineStringMember": function(geometry) {
var node = this.createElementNSPlus("gml:lineStringMember");
this.writeNode("LineString", geometry, node);
return node;
},
"MultiPolygon": function(geometry) {
var node = this.createElementNSPlus("gml:MultiPolygon");
for(var i=0; i<geometry.components.length; ++i) {
this.writeNode(
"polygonMember", geometry.components[i], node
);
}
return node;
},
"polygonMember": function(geometry) {
var node = this.createElementNSPlus("gml:polygonMember");
this.writeNode("Polygon", geometry, node);
return node;
},
"GeometryCollection": function(geometry) {
var node = this.createElementNSPlus("gml:GeometryCollection");
for(var i=0, len=geometry.components.length; i<len; ++i) {
this.writeNode("geometryMember", geometry.components[i], node);
}
return node;
},
"geometryMember": function(geometry) {
var node = this.createElementNSPlus("gml:geometryMember");
var child = this.writeNode("feature:_geometry", geometry);
node.appendChild(child.firstChild);
return node;
}
},
"feature": {
"_typeName": function(feature) {
var node = this.createElementNSPlus("feature:" + this.featureType, {
attributes: {fid: feature.fid}
});
if(feature.geometry) {
this.writeNode("feature:_geometry", feature.geometry, node);
}
for(var name in feature.attributes) {
var value = feature.attributes[name];
if(value != null) {
this.writeNode(
"feature:_attribute",
{name: name, value: value}, node
)
}
}
return node;
},
"_geometry": function(geometry) {
if(this.externalProjection && this.internalProjection) {
geometry = geometry.clone().transform(
this.internalProjection, this.externalProjection
);
}
var node = this.createElementNSPlus(
"feature:" + this.geometryName
);
var type = this.geometryTypes[geometry.CLASS_NAME];
var child = this.writeNode("gml:" + type, geometry, node);
if(this.srsName) {
child.setAttribute("srsName", this.srsName);
}
return node;
},
"_attribute": function(obj) {
return this.createElementNSPlus("feature:" + obj.name, {
value: obj.value
});
}
},
"wfs": {
"FeatureCollection": function(features) {
/**
* This is only here because GML2 only describes abstract
* feature collections. Typically, you would not be using
* the GML format to write wfs elements. This just provides
* some way to write out lists of features. GML3 defines the
* featureMembers element, so that is used by default instead.
*/
var node = this.createElementNSPlus("wfs:FeatureCollection");
for(var i=0, len=features.length; i<len; ++i) {
this.writeNode("gml:featureMember", features[i], node);
}
return node;
}
}
},
/**
* Property: geometryTypes
* {Object} Maps OpenLayers geometry class names to GML element names.
*/
geometryTypes: {
"OpenLayers.Geometry.Point": "Point",
"OpenLayers.Geometry.MultiPoint": "MultiPoint",
"OpenLayers.Geometry.LineString": "LineString",
"OpenLayers.Geometry.MultiLineString": "MultiLineString",
"OpenLayers.Geometry.Polygon": "Polygon",
"OpenLayers.Geometry.MultiPolygon": "MultiPolygon",
"OpenLayers.Geometry.Collection": "GeometryCollection"
},
CLASS_NAME: "OpenLayers.Format.GML.Base"
});

View File

@@ -0,0 +1,192 @@
/* 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/GML/Base.js
*/
/**
* Class: OpenLayers.Format.GML.v2
* Parses GML version 2.
*
* Inherits from:
* - <OpenLayers.Format.GML.Base>
*/
OpenLayers.Format.GML.v2 = OpenLayers.Class(OpenLayers.Format.GML.Base, {
/**
* Property: schemaLocation
* {String} Schema location for a particular minor version.
*/
schemaLocation: "http://www.opengis.net/gml http://schemas.opengis.net/gml/2.1.2/feature.xsd",
/**
* Constructor: OpenLayers.Format.GML.v2
* Create a parser for GML v2.
*
* Parameters:
* options - {Object} An optional object whose properties will be set on
* this instance.
*
* Valid options properties:
* featureType - {String} Local (without prefix) feature typeName (required).
* featureNS - {String} Feature namespace (required).
* geometryName - {String} Geometry element name.
*/
initialize: function(options) {
OpenLayers.Format.GML.Base.prototype.initialize.apply(this, [options]);
},
/**
* 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": OpenLayers.Util.applyDefaults({
"outerBoundaryIs": function(node, container) {
var obj = {};
this.readChildNodes(node, obj);
container.outer = obj.components[0];
},
"innerBoundaryIs": function(node, container) {
var obj = {};
this.readChildNodes(node, obj);
container.inner.push(obj.components[0]);
},
"Box": function(node, container) {
var obj = {};
this.readChildNodes(node, obj);
if(!container.components) {
container.components = [];
}
var min = obj.points[0];
var max = obj.points[1];
container.components.push(
new OpenLayers.Bounds(min.x, min.y, max.x, max.y)
);
}
}, OpenLayers.Format.GML.Base.prototype.readers["gml"]),
"feature": OpenLayers.Format.GML.Base.prototype.readers["feature"],
"wfs": OpenLayers.Format.GML.Base.prototype.readers["wfs"]
},
/**
* Method: write
*
* Parameters:
* features - {Array(<OpenLayers.Feature.Vector>) | OpenLayers.Feature.Vector}
* An array of features or a single feature.
*
* Returns:
* {String} Given an array of features, a doc with a gml:featureMembers
* element will be returned. Given a single feature, a doc with a
* gml:featureMember element will be returned.
*/
write: function(features) {
var name;
if(features instanceof Array) {
// GML2 only has abstract feature collections
// wfs provides a feature collection from a well-known schema
name = "wfs:FeatureCollection";
} else {
name = "gml:featureMember";
}
var root = this.writeNode(name, features);
this.setAttributeNS(
root, this.namespaces["xsi"],
"xsi:schemaLocation", this.schemaLocation
);
return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
},
/**
* Property: writers
* As a compliment to the readers property, this structure contains public
* writing functions grouped by namespace alias and named like the
* node names they produce.
*/
writers: {
"gml": OpenLayers.Util.applyDefaults({
"Point": function(geometry) {
var node = this.createElementNSPlus("gml:Point");
this.writeNode("coordinates", [geometry], node);
return node;
},
"coordinates": function(points) {
var numPoints = points.length;
var parts = new Array(numPoints);
var point;
for(var i=0; i<numPoints; ++i) {
point = points[i];
if(this.xy) {
parts[i] = point.x + "," + point.y;
} else {
parts[i] = point.y + "," + point.x;
}
if(point.z != undefined) { // allow null or undefined
parts[i] += "," + point.z;
}
}
return this.createElementNSPlus("gml:coordinates", {
attributes: {
decimal: ".", cs: ",", ts: " "
},
value: (numPoints == 1) ? parts[0] : parts.join(" ")
});
},
"LineString": function(geometry) {
var node = this.createElementNSPlus("gml:LineString");
this.writeNode("coordinates", geometry.components, node);
return node;
},
"Polygon": function(geometry) {
var node = this.createElementNSPlus("gml:Polygon");
this.writeNode("outerBoundaryIs", geometry.components[0], node);
for(var i=1; i<geometry.components.length; ++i) {
this.writeNode(
"innerBoundaryIs", geometry.components[i], node
);
}
return node;
},
"outerBoundaryIs": function(ring) {
var node = this.createElementNSPlus("gml:outerBoundaryIs");
this.writeNode("LinearRing", ring, node);
return node;
},
"innerBoundaryIs": function(ring) {
var node = this.createElementNSPlus("gml:innerBoundaryIs");
this.writeNode("LinearRing", ring, node);
return node;
},
"LinearRing": function(ring) {
var node = this.createElementNSPlus("gml:LinearRing");
this.writeNode("coordinates", ring.components, node);
return node;
},
"Box": function(bounds) {
var node = this.createElementNSPlus("gml:Box");
this.writeNode("coordinates", [
{x: bounds.left, y: bounds.bottom},
{x: bounds.right, y: bounds.top}
], node);
// srsName attribute is optional for gml:Box
if(this.srsName) {
node.setAttribute("srsName", this.srsName);
}
return node;
}
}, OpenLayers.Format.GML.Base.prototype.writers["gml"]),
"feature": OpenLayers.Format.GML.Base.prototype.writers["feature"],
"wfs": OpenLayers.Format.GML.Base.prototype.writers["wfs"]
},
CLASS_NAME: "OpenLayers.Format.GML.v2"
});

View File

@@ -0,0 +1,287 @@
/* 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/GML/Base.js
*/
/**
* Class: OpenLayers.Format.GML.v3
* Parses GML version 3.
*
* Inherits from:
* - <OpenLayers.Format.GML.Base>
*/
OpenLayers.Format.GML.v3 = OpenLayers.Class(OpenLayers.Format.GML.Base, {
/**
* Property: schemaLocation
* {String} Schema location for a particular minor version. The writers
* conform with the Simple Features Profile for GML.
*/
schemaLocation: "http://www.opengis.net/gml http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsf.xsd",
/**
* Constructor: OpenLayers.Format.GML.v3
* Create a parser for GML v3.
*
* Parameters:
* options - {Object} An optional object whose properties will be set on
* this instance.
*
* Valid options properties:
* featureType - {String} Local (without prefix) feature typeName (required).
* featureNS - {String} Feature namespace (required).
* geometryName - {String} Geometry element name.
*/
initialize: function(options) {
OpenLayers.Format.GML.Base.prototype.initialize.apply(this, [options]);
},
/**
* 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": OpenLayers.Util.applyDefaults({
"featureMembers": function(node, obj) {
this.readChildNodes(node, obj);
},
"pos": function(node, obj) {
var str = this.getChildValue(node).replace(
this.regExes.trimSpace, ""
);
var coords = str.split(this.regExes.splitSpace);
var point;
if(this.xy) {
point = new OpenLayers.Geometry.Point(
coords[0], coords[1], coords[2]
);
} else {
point = new OpenLayers.Geometry.Point(
coords[1], coords[0], coords[2]
);
}
obj.points = [point];
},
"posList": function(node, obj) {
var str = this.concatChildValues(node).replace(
this.regExes.trimSpace, ""
);
var coords = str.split(this.regExes.splitSpace);
var dim = parseInt(node.getAttribute("dimension")) || 2;
var j, x, y, z;
var numPoints = coords.length / dim;
var points = new Array(numPoints);
for(var i=0, len=coords.length; i<len; i += dim) {
x = coords[i];
y = coords[i+1];
z = (dim == 2) ? undefined : coords[i+2];
if (this.xy) {
points[i/dim] = new OpenLayers.Geometry.Point(x, y, z);
} else {
points[i/dim] = new OpenLayers.Geometry.Point(y, x, z);
}
}
obj.points = points;
},
"exterior": function(node, container) {
var obj = {};
this.readChildNodes(node, obj);
container.outer = obj.components[0];
},
"interior": function(node, container) {
var obj = {};
this.readChildNodes(node, obj);
container.inner.push(obj.components[0]);
},
"MultiSurface": function(node, container) {
var obj = {components: []};
this.readChildNodes(node, obj);
if(obj.components.length > 0) {
container.components = [
new OpenLayers.Geometry.MultiPolygon(obj.components)
];
}
},
"surfaceMember": function(node, obj) {
this.readChildNodes(node, obj);
},
"surfaceMembers": function(node, obj) {
this.readChildNodes(node, obj);
},
"pointMembers": function(node, obj) {
this.readChildNodes(node, obj);
},
"lineStringMembers": function(node, obj) {
this.readChildNodes(node, obj);
},
"polygonMembers": function(node, obj) {
this.readChildNodes(node, obj);
},
"geometryMembers": function(node, obj) {
this.readChildNodes(node, obj);
},
"Envelope": function(node, container) {
var obj = {points: new Array(2)};
this.readChildNodes(node, obj);
if(!container.components) {
container.components = [];
}
var min = obj.points[0];
var max = obj.points[1];
container.components.push(
new OpenLayers.Bounds(min.x, min.y, max.x, max.y)
);
},
"lowerCorner": function(node, container) {
var obj = {};
this.readChildNodes(node, obj)
container.points[0] = obj.points[0];
},
"upperCorner": function(node, container) {
var obj = {};
this.readChildNodes(node, obj)
container.points[1] = obj.points[0];
}
}, OpenLayers.Format.GML.Base.prototype.readers["gml"]),
"feature": OpenLayers.Format.GML.Base.prototype.readers["feature"],
"wfs": OpenLayers.Format.GML.Base.prototype.readers["wfs"]
},
/**
* Method: write
*
* Parameters:
* features - {Array(<OpenLayers.Feature.Vector>) | OpenLayers.Feature.Vector}
* An array of features or a single feature.
*
* Returns:
* {String} Given an array of features, a doc with a gml:featureMembers
* element will be returned. Given a single feature, a doc with a
* gml:featureMember element will be returned.
*/
write: function(features) {
var name;
if(features instanceof Array) {
name = "featureMembers";
} else {
name = "featureMember";
}
var root = this.writeNode("gml:" + name, features);
this.setAttributeNS(
root, this.namespaces["xsi"],
"xsi:schemaLocation", this.schemaLocation
);
return OpenLayers.Format.XML.prototype.write.apply(this, [root]);
},
/**
* Property: writers
* As a compliment to the readers property, this structure contains public
* writing functions grouped by namespace alias and named like the
* node names they produce.
*/
writers: {
"gml": OpenLayers.Util.applyDefaults({
"featureMembers": function(features) {
var node = this.createElementNSPlus("gml:featureMembers");
for(var i=0, len=features.length; i<len; ++i) {
this.writeNode("feature:_typeName", features[i], node);
}
return node;
},
"Point": function(geometry) {
var node = this.createElementNSPlus("gml:Point");
this.writeNode("pos", geometry, node);
return node;
},
"pos": function(point) {
// only 2d for simple features profile
var pos = (this.xy) ?
(point.x + " " + point.y) : (point.y + " " + point.x);
return this.createElementNSPlus("gml:pos", {
value: pos
});
},
"LineString": function(geometry) {
var node = this.createElementNSPlus("gml:LineString");
this.writeNode("posList", geometry.components, node);
return node;
},
"posList": function(points) {
// only 2d for simple features profile
var len = points.length;
var parts = new Array(len);
var point;
for(var i=0; i<len; ++i) {
point = points[i];
if(this.xy) {
parts[i] = point.x + " " + point.y;
} else {
parts[i] = point.y + " " + point.x;
}
}
return this.createElementNSPlus("gml:posList", {
value: parts.join(" ")
});
},
"Polygon": function(geometry) {
var node = this.createElementNSPlus("gml:Polygon");
this.writeNode("exterior", geometry.components[0], node);
for(var i=1, len=geometry.components.length; i<len; ++i) {
this.writeNode(
"interior", geometry.components[i], node
);
}
return node;
},
"exterior": function(ring) {
var node = this.createElementNSPlus("gml:exterior");
this.writeNode("LinearRing", ring, node);
return node;
},
"interior": function(ring) {
var node = this.createElementNSPlus("gml:interior");
this.writeNode("LinearRing", ring, node);
return node;
},
"LinearRing": function(ring) {
var node = this.createElementNSPlus("gml:LinearRing");
this.writeNode("posList", ring.components, node);
return node;
},
"Envelope": function(bounds) {
var node = this.createElementNSPlus("gml:Envelope");
this.writeNode("lowerCorner", bounds, node);
this.writeNode("upperCorner", bounds, node);
// srsName attribute is required for gml:Envelope
if(this.srsName) {
node.setAttribute("srsName", this.srsName);
}
return node;
},
"lowerCorner": function(bounds) {
var node = this.createElementNSPlus("gml:lowerCorner");
this.writeNode("pos", {x: bounds.left, y: bounds.bottom}, node);
return node;
},
"upperCorner": function(bounds) {
var node = this.createElementNSPlus("gml:upperCorner");
this.writeNode("pos", {x: bounds.right, y: bounds.top}, node);
return node;
}
}, OpenLayers.Format.GML.Base.prototype.writers["gml"]),
"feature": OpenLayers.Format.GML.Base.prototype.writers["feature"],
"wfs": OpenLayers.Format.GML.Base.prototype.writers["wfs"]
},
CLASS_NAME: "OpenLayers.Format.GML.v3"
});

View File

@@ -19,6 +19,46 @@
*/
OpenLayers.Format.XML = OpenLayers.Class(OpenLayers.Format, {
/**
* Property: namespaces
* {Object} Mapping of namespace aliases to namespace URIs. Properties
* of this object should not be set individually. Read-only. All
* XML subclasses should have their own namespaces object. Use
* <setNamespace> to add or set a namespace alias after construction.
*/
namespaces: null,
/**
* Property: namespaceAlias
* {Object} Mapping of namespace URI to namespace alias. This object
* is read-only. Use <setNamespace> to add or set a namespace alias.
*/
namespaceAlias: null,
/**
* Property: defaultPrefix
* {String} The default namespace alias for creating element nodes.
*/
defaultPrefix: null,
/**
* 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: {},
/**
* Property: writers
* As a compliment to the <readers> property, this structure contains public
* writing functions grouped by namespace alias and named like the
* node names they produce.
*/
writers: {},
/**
* Property: xmldom
* {XMLDom} If this browser uses ActiveX, this will be set to a XMLDOM
@@ -44,6 +84,34 @@ OpenLayers.Format.XML = OpenLayers.Class(OpenLayers.Format, {
this.xmldom = new ActiveXObject("Microsoft.XMLDOM");
}
OpenLayers.Format.prototype.initialize.apply(this, [options]);
// clone the namespace object and set all namespace aliases
this.namespaces = OpenLayers.Util.extend({}, this.namespaces);
this.namespaceAlias = {};
for(var alias in this.namespaces) {
this.namespaceAlias[this.namespaces[alias]] = alias;
}
},
/**
* APIMethod: destroy
* Clean up.
*/
destroy: function() {
this.xmldom = null;
OpenLayers.Format.prototype.destroy.apply(this, arguments);
},
/**
* Method: setNamespace
* Set a namespace alias and URI for the format.
*
* Parameters:
* alias - {String} The namespace alias (prefix).
* uri - {String} The namespace URI.
*/
setNamespace: function(alias, uri) {
this.namespaces[alias] = uri;
this.namespaceAlias[uri] = alias;
},
/**
@@ -289,11 +357,12 @@ OpenLayers.Format.XML = OpenLayers.Class(OpenLayers.Format, {
* {String} The value of the first child of the given node.
*/
getChildValue: function(node, def) {
var value;
if (node && node.firstChild && node.firstChild.nodeValue) {
value = node.firstChild.nodeValue;
} else {
value = (def != undefined) ? def : "";
var value = def || "";
if(node) {
var child = node.firstChild;
if(child) {
value = child.nodeValue || value;
}
}
return value;
},
@@ -384,6 +453,172 @@ OpenLayers.Format.XML = OpenLayers.Class(OpenLayers.Format, {
}
},
/**
* Method: createElementNSPlus
* Shorthand for creating namespaced elements with optional attributes and
* child text nodes.
*
* Parameters:
* name - {String} The qualified node name.
* options - {Object} Optional object for node configuration.
*
* Valid options:
* uri - {String} Optional namespace uri for the element - supply a prefix
* instead if the namespace uri is a property of the format's namespace
* object.
* attributes - {Object} Optional attributes to be set using the
* <setAttributes> method.
* value - {String} Optional text to be appended as a text node.
*
* Returns:
* {Element} An element node.
*/
createElementNSPlus: function(name, options) {
options = options || {};
var loc = name.indexOf(":");
// order of prefix preference
// 1. in the uri option
// 2. in the prefix option
// 3. in the qualified name
// 4. from the defaultPrefix
var uri = options.uri || this.namespaces[options.prefix];
if(!uri) {
loc = name.indexOf(":");
uri = this.namespaces[name.substring(0, loc)];
}
if(!uri) {
uri = this.namespaces[this.defaultPrefix];
}
var node = this.createElementNS(uri, name);
if(options.attributes) {
this.setAttributes(node, options.attributes);
}
if(options.value) {
node.appendChild(this.createTextNode(options.value));
}
return node;
},
/**
* Method: setAttributes
* Set multiple attributes given key value pairs from an object.
*
* Parameters:
* node - {Element} An element node.
* obj - {Object || Array} An object whose properties represent attribute
* names and values represent attribute values. If an attribute name
* is a qualified name ("prefix:local"), the prefix will be looked up
* in the parsers {namespaces} object. If the prefix is found,
* setAttributeNS will be used instead of setAttribute.
*/
setAttributes: function(node, obj) {
var value, loc, alias, uri;
for(var name in obj) {
if(obj[name] != null && obj[name].toString) {
value = obj[name].toString();
// check for qualified attribute name ("prefix:local")
uri = this.namespaces[name.substring(0, name.indexOf(":"))] || null;
this.setAttributeNS(node, uri, name, value);
}
}
},
/**
* Method: readNode
* Shorthand for applying one of the named readers given the node
* namespace and local name. Readers take two args (node, obj) and
* generally extend or modify the second.
*
* Parameters:
* node - {DOMElement} The node to be read (required).
* obj - {Object} The object to be modified (optional).
*
* Returns:
* {Object} The input object, modified (or a new one if none was provided).
*/
readNode: function(node, obj) {
if(!obj) {
obj = {};
}
var group = this.readers[this.namespaceAlias[node.namespaceURI]];
if(group) {
var local = node.localName || node.nodeName.split(":").pop();
var reader = group[local] || group["*"];
if(reader) {
reader.apply(this, [node, obj]);
}
}
return obj;
},
/**
* Method: readChildNodes
* Shorthand for applying the named readers to all children of a node.
* For each child of type 1 (element), <readSelf> is called.
*
* Parameters:
* node - {DOMElement} The node to be read (required).
* obj - {Object} The object to be modified (optional).
*
* Returns:
* {Object} The input object, modified.
*/
readChildNodes: function(node, obj) {
if(!obj) {
obj = {};
}
var children = node.childNodes;
var child;
for(var i=0, len=children.length; i<len; ++i) {
child = children[i];
if(child.nodeType == 1) {
this.readNode(child, obj);
}
}
return obj;
},
/**
* Method: writeNode
* Shorthand for applying one of the named writers and appending the
* results to a node. If a qualified name is not provided for the
* second argument (and a local name is used instead), the namespace
* of the parent node will be assumed.
*
* Parameters:
* name - {String} The name of a node to generate. If a qualified name
* (e.g. "pre:Name") is used, the namespace prefix is assumed to be
* in the <writers> group. If a local name is used (e.g. "Name") then
* the namespace of the parent is assumed. If a local name is used
* and no parent is supplied, then the default namespace is assumed.
* obj - {Object} Structure containing data for the writer.
* parent - {DOMElement} Result will be appended to this node. If no parent
* is supplied, the node will not be appended to anything.
*
* Returns:
* {DOMElement} The child node.
*/
writeNode: function(name, obj, parent) {
var prefix, local;
var split = name.indexOf(":");
if(split > 0) {
prefix = name.substring(0, split);
local = name.substring(split + 1);
} else {
if(parent) {
prefix = this.namespaceAlias[parent.namespaceURI];
} else {
prefix = this.defaultPrefix;
}
local = name;
}
var child = this.writers[prefix][local].apply(this, [obj]);
if(parent) {
parent.appendChild(child);
}
return child;
},
CLASS_NAME: "OpenLayers.Format.XML"
});