auto-configure featureType and featureNS. p=bartvde (closes #3367)
git-svn-id: http://svn.openlayers.org/trunk/openlayers@12110 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
@@ -101,6 +101,18 @@ OpenLayers.Format.GML.Base = OpenLayers.Class(OpenLayers.Format.XML, {
|
|||||||
* of featuretypes.
|
* of featuretypes.
|
||||||
*/
|
*/
|
||||||
singleFeatureType: null,
|
singleFeatureType: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property: autoConfig
|
||||||
|
* {Boolean} Indicates if the format was configured without a <featureNS>,
|
||||||
|
* but auto-configured <featureNS> and <featureType> during read.
|
||||||
|
* Subclasses making use of <featureType> auto-configuration should make
|
||||||
|
* the first call to the <readNode> method (usually in the read method)
|
||||||
|
* with true as 3rd argument, so the auto-configured featureType can be
|
||||||
|
* reset and the format can be reused for subsequent reads with data from
|
||||||
|
* different featureTypes. Set to false after read if you want to keep the
|
||||||
|
* auto-configured values.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Property: regExes
|
* Property: regExes
|
||||||
@@ -110,7 +122,8 @@ OpenLayers.Format.GML.Base = OpenLayers.Class(OpenLayers.Format.XML, {
|
|||||||
trimSpace: (/^\s*|\s*$/g),
|
trimSpace: (/^\s*|\s*$/g),
|
||||||
removeSpace: (/\s*/g),
|
removeSpace: (/\s*/g),
|
||||||
splitSpace: (/\s+/),
|
splitSpace: (/\s+/),
|
||||||
trimComma: (/\s*,\s*/g)
|
trimComma: (/\s*,\s*/g),
|
||||||
|
featureMember: (/^(.*:)?featureMembers?$/)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -125,9 +138,9 @@ OpenLayers.Format.GML.Base = OpenLayers.Class(OpenLayers.Format.XML, {
|
|||||||
*
|
*
|
||||||
* Valid options properties:
|
* Valid options properties:
|
||||||
* featureType - {Array(String) or String} Local (without prefix) feature
|
* featureType - {Array(String) or String} Local (without prefix) feature
|
||||||
* typeName(s) (required).
|
* typeName(s) (required for write).
|
||||||
* featureNS - {String} Feature namespace (required).
|
* featureNS - {String} Feature namespace (required for write).
|
||||||
* geometryName - {String} Geometry element name.
|
* geometryName - {String} Geometry element name (required for write).
|
||||||
*/
|
*/
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
|
OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
|
||||||
@@ -156,7 +169,7 @@ OpenLayers.Format.GML.Base = OpenLayers.Class(OpenLayers.Format.XML, {
|
|||||||
data = data.documentElement;
|
data = data.documentElement;
|
||||||
}
|
}
|
||||||
var features = [];
|
var features = [];
|
||||||
this.readNode(data, {features: features});
|
this.readNode(data, {features: features}, true);
|
||||||
if(features.length == 0) {
|
if(features.length == 0) {
|
||||||
// look for gml:featureMember elements
|
// look for gml:featureMember elements
|
||||||
var elements = this.getElementsByTagNameNS(
|
var elements = this.getElementsByTagNameNS(
|
||||||
@@ -164,7 +177,7 @@ OpenLayers.Format.GML.Base = OpenLayers.Class(OpenLayers.Format.XML, {
|
|||||||
);
|
);
|
||||||
if(elements.length) {
|
if(elements.length) {
|
||||||
for(var i=0, len=elements.length; i<len; ++i) {
|
for(var i=0, len=elements.length; i<len; ++i) {
|
||||||
this.readNode(elements[i], {features: features});
|
this.readNode(elements[i], {features: features}, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// look for gml:featureMembers elements (this is v3, but does no harm here)
|
// look for gml:featureMembers elements (this is v3, but does no harm here)
|
||||||
@@ -173,13 +186,50 @@ OpenLayers.Format.GML.Base = OpenLayers.Class(OpenLayers.Format.XML, {
|
|||||||
);
|
);
|
||||||
if(elements.length) {
|
if(elements.length) {
|
||||||
// there can be only one
|
// there can be only one
|
||||||
this.readNode(elements[0], {features: features});
|
this.readNode(elements[0], {features: features}, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return features;
|
return features;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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).
|
||||||
|
* first - {Boolean} Should be set to true for the first node read. This
|
||||||
|
* is usually the readNode call in the read method. Without this being
|
||||||
|
* set, auto-configured properties will stick on subsequent reads.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {Object} The input object, modified (or a new one if none was provided).
|
||||||
|
*/
|
||||||
|
readNode: function(node, obj, first) {
|
||||||
|
// on subsequent calls of format.read(), we want to reset auto-
|
||||||
|
// configured properties and auto-configure again.
|
||||||
|
if (first === true && this.autoConfig === true) {
|
||||||
|
this.featureType = null;
|
||||||
|
delete this.namespaceAlias[this.featureNS];
|
||||||
|
delete this.namespaces["feature"];
|
||||||
|
this.featureNS = null;
|
||||||
|
}
|
||||||
|
// featureType auto-configuration
|
||||||
|
if (!this.featureNS && (!(node.prefix in this.namespaces) &&
|
||||||
|
node.parentNode.namespaceURI == this.namespaces["gml"] &&
|
||||||
|
this.regExes.featureMember.test(node.parentNode.nodeName))) {
|
||||||
|
this.featureType = node.nodeName.split(":").pop();
|
||||||
|
this.setNamespace("feature", node.namespaceURI);
|
||||||
|
this.featureNS = node.namespaceURI;
|
||||||
|
this.autoConfig = true;
|
||||||
|
}
|
||||||
|
return OpenLayers.Format.XML.prototype.readNode.apply(this, arguments);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Property: readers
|
* Property: readers
|
||||||
* Contains public functions, grouped by namespace prefix, that will
|
* Contains public functions, grouped by namespace prefix, that will
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ OpenLayers.Format.WFST.v1 = OpenLayers.Class(OpenLayers.Format.XML, {
|
|||||||
}
|
}
|
||||||
var obj = {};
|
var obj = {};
|
||||||
if(data) {
|
if(data) {
|
||||||
this.readNode(data, obj);
|
this.readNode(data, obj, true);
|
||||||
}
|
}
|
||||||
if(obj.features && options.output === "features") {
|
if(obj.features && options.output === "features") {
|
||||||
obj = obj.features;
|
obj = obj.features;
|
||||||
|
|||||||
@@ -62,6 +62,29 @@ OpenLayers.Format.WFST.v1_0_0 = OpenLayers.Class(
|
|||||||
OpenLayers.Format.WFST.v1.prototype.initialize.apply(this, [options]);
|
OpenLayers.Format.WFST.v1.prototype.initialize.apply(this, [options]);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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).
|
||||||
|
* first - {Boolean} Should be set to true for the first node read. This
|
||||||
|
* is usually the readNode call in the read method. Without this being
|
||||||
|
* set, auto-configured properties will stick on subsequent reads.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {Object} The input object, modified (or a new one if none was provided).
|
||||||
|
*/
|
||||||
|
readNode: function(node, obj, first) {
|
||||||
|
// Not the superclass, only the mixin classes inherit from
|
||||||
|
// Format.GML.v2. We need this because we don't want to get readNode
|
||||||
|
// from the superclass's superclass, which is OpenLayers.Format.XML.
|
||||||
|
return OpenLayers.Format.GML.v2.prototype.readNode.apply(this, [node, obj]);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Property: readers
|
* Property: readers
|
||||||
* Contains public functions, grouped by namespace prefix, that will
|
* Contains public functions, grouped by namespace prefix, that will
|
||||||
|
|||||||
@@ -61,6 +61,29 @@ OpenLayers.Format.WFST.v1_1_0 = OpenLayers.Class(
|
|||||||
OpenLayers.Format.WFST.v1.prototype.initialize.apply(this, [options]);
|
OpenLayers.Format.WFST.v1.prototype.initialize.apply(this, [options]);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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).
|
||||||
|
* first - {Boolean} Should be set to true for the first node read. This
|
||||||
|
* is usually the readNode call in the read method. Without this being
|
||||||
|
* set, auto-configured properties will stick on subsequent reads.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* {Object} The input object, modified (or a new one if none was provided).
|
||||||
|
*/
|
||||||
|
readNode: function(node, obj, first) {
|
||||||
|
// Not the superclass, only the mixin classes inherit from
|
||||||
|
// Format.GML.v3. We need this because we don't want to get readNode
|
||||||
|
// from the superclass's superclass, which is OpenLayers.Format.XML.
|
||||||
|
return OpenLayers.Format.GML.v3.prototype.readNode.apply(this, [node, obj]);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Property: readers
|
* Property: readers
|
||||||
* Contains public functions, grouped by namespace prefix, that will
|
* Contains public functions, grouped by namespace prefix, that will
|
||||||
|
|||||||
@@ -116,17 +116,6 @@ OpenLayers.Protocol.WFS.v1 = OpenLayers.Class(OpenLayers.Protocol, {
|
|||||||
schema: this.schema
|
schema: this.schema
|
||||||
}, this.formatOptions));
|
}, this.formatOptions));
|
||||||
}
|
}
|
||||||
if(!this.featureNS && this.featurePrefix) {
|
|
||||||
// featureNS autodetection
|
|
||||||
var readNode = this.format.readNode;
|
|
||||||
this.format.readNode = function(node, obj) {
|
|
||||||
if(!this.featureNS && node.prefix == this.featurePrefix) {
|
|
||||||
this.featureNS = node.namespaceURI;
|
|
||||||
this.setNamespace("feature", this.featureNS);
|
|
||||||
}
|
|
||||||
return readNode.apply(this, arguments);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -177,6 +177,21 @@
|
|||||||
t.eq(attributes["LAND_KM"], "143986.61", "read LAND_KM");
|
t.eq(attributes["LAND_KM"], "143986.61", "read LAND_KM");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_read_autoconfig(t) {
|
||||||
|
t.plan(5);
|
||||||
|
var doc = readXML("v2/topp-states.xml");
|
||||||
|
var format = new OpenLayers.Format.GML.v2();
|
||||||
|
var features = format.read(doc.documentElement);
|
||||||
|
|
||||||
|
t.eq(features.length, 3, "read 3 features");
|
||||||
|
var feature = features[0];
|
||||||
|
t.eq(feature.fid, "states.1", "read fid");
|
||||||
|
t.eq(feature.geometry.CLASS_NAME, "OpenLayers.Geometry.MultiPolygon",
|
||||||
|
"read multipolygon geometry");
|
||||||
|
t.eq(format.featureType, "states", "featureType correctly auto-configured");
|
||||||
|
t.eq(format.featureNS, "http://www.openplans.org/topp", "featureNS correctly auto-configured");
|
||||||
|
}
|
||||||
|
|
||||||
function test_boundedBy(t) {
|
function test_boundedBy(t) {
|
||||||
t.plan(5);
|
t.plan(5);
|
||||||
|
|
||||||
@@ -248,6 +263,7 @@
|
|||||||
t.eq(bounds.right, 337568, "bounds right correct");
|
t.eq(bounds.right, 337568, "bounds right correct");
|
||||||
t.eq(bounds.top, 6885985, "bounds top correct");
|
t.eq(bounds.top, 6885985, "bounds top correct");
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -212,6 +212,26 @@
|
|||||||
t.eq(attributes["LAND_KM"], "143986.61", "read LAND_KM");
|
t.eq(attributes["LAND_KM"], "143986.61", "read LAND_KM");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_read_autoconfig(t) {
|
||||||
|
t.plan(7);
|
||||||
|
var doc = readXML("v3/topp-states-wfs.xml");
|
||||||
|
var format = new OpenLayers.Format.GML.v3();
|
||||||
|
var features = format.read(doc.documentElement);
|
||||||
|
|
||||||
|
t.eq(features.length, 3, "read 3 features");
|
||||||
|
var feature = features[0];
|
||||||
|
t.eq(feature.fid, "states.1", "read fid");
|
||||||
|
t.eq(feature.geometry.CLASS_NAME, "OpenLayers.Geometry.MultiPolygon",
|
||||||
|
"read multipolygon geometry");
|
||||||
|
t.eq(format.featureType, "states", "featureType correctly auto-configured");
|
||||||
|
t.eq(format.featureNS, "http://www.openplans.org/topp", "featureNS correctly auto-configured");
|
||||||
|
|
||||||
|
t.eq(format.autoConfig, true, "autoConfig set to true");
|
||||||
|
format.autoConfig = false;
|
||||||
|
format.read(doc.documentElement);
|
||||||
|
t.eq(format.autoConfig, false, "now that featureNS is set, the format does not auto-configure again");
|
||||||
|
}
|
||||||
|
|
||||||
function test_emptyAttribute(t) {
|
function test_emptyAttribute(t) {
|
||||||
t.plan(4);
|
t.plan(4);
|
||||||
var str =
|
var str =
|
||||||
|
|||||||
Reference in New Issue
Block a user