Files
openlayers/lib/OpenLayers/Format/KML.js
crschmidt 3948913bfc Merge all changes from the naturaldocs sandbox. This brings all the work that
has been done in the NaturalDocs branch back to trunk. Thanks to everyone who
helped out in making this happen. (I could list people, but the list would
be long, and I'm already mentally on vacation.)


git-svn-id: http://svn.openlayers.org/trunk/openlayers@3545 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
2007-06-29 15:59:20 +00:00

187 lines
6.0 KiB
JavaScript

/* Copyright (c) 2006 MetaCarta, Inc., published under a modified BSD license.
* See http://svn.openlayers.org/trunk/openlayers/repository-license.txt
* for the full text of the license. */
/**
* @requires OpenLayers/Format.js
* @requires OpenLayers/Feature/Vector.js
* @requires OpenLayers/Ajax.js
*
* Class: OpenLayers.Format.KML
* Read only KML. Largely Proof of Concept: does not support advanced Features,
* including Polygons.
*
* Inherits from:
* - <OpenLayers.Format>
*/
OpenLayers.Format.KML = OpenLayers.Class.create();
OpenLayers.Format.KML.prototype =
OpenLayers.Class.inherit( OpenLayers.Format, {
/**
* APIProperty: kmlns
* KML Namespace to use. Defaults to 2.0 namespace.
*/
kmlns: "http://earth.google.com/kml/2.0",
/**
* APIMethod: read
* Read data from a string, and return a list of features.
*
* Parameters:
* data - {string} or {XMLNode>} data to read/parse.
*/
read: function(data) {
if (typeof data == "string") {
data = OpenLayers.parseXMLString(data);
}
var featureNodes = OpenLayers.Ajax.getElementsByTagNameNS(data, this.kmlns, "", "Placemark");
var features = [];
// Process all the featureMembers
for (var i = 0; i < featureNodes.length; i++) {
var feature = this.parseFeature(featureNodes[i]);
if (feature) {
features.push(feature);
}
}
return features;
},
/**
* Method: parseFeature
* This function is the core of the KML parsing code in OpenLayers.
* It creates the geometries that are then attached to the returned
* feature, and calls parseAttributes() to get attribute data out.
*
* Parameters:
* xmlNode - {<DOMElement>}
*/
parseFeature: function(xmlNode) {
var geom;
var p; // [points,bounds]
var feature = new OpenLayers.Feature.Vector();
// match Point
if (OpenLayers.Ajax.getElementsByTagNameNS(xmlNode,
this.kmlns, "", "Point").length != 0) {
var point = OpenLayers.Ajax.getElementsByTagNameNS(xmlNode,
this.kmlns, "", "Point")[0];
p = this.parseCoords(point);
if (p.points) {
geom = p.points[0];
// TBD Bounds only set for one of multiple geometries
geom.extendBounds(p.bounds);
}
// match LineString
} else if (OpenLayers.Ajax.getElementsByTagNameNS(xmlNode,
this.kmlns, "", "LineString").length != 0) {
var linestring = OpenLayers.Ajax.getElementsByTagNameNS(xmlNode,
this.kmlns, "", "LineString")[0];
p = this.parseCoords(linestring);
if (p.points) {
geom = new OpenLayers.Geometry.LineString(p.points);
// TBD Bounds only set for one of multiple geometries
geom.extendBounds(p.bounds);
}
}
feature.geometry = geom;
feature.attributes = this.parseAttributes(xmlNode);
return feature;
},
/**
* Method: parseAttributes
* recursive function parse the attributes of a KML node.
* Searches for any child nodes which aren't geometries,
* and gets their value.
*
* Parameters:
* xmlNode - {<DOMElement>}
*/
parseAttributes: function(xmlNode) {
var nodes = xmlNode.childNodes;
var attributes = {};
for(var i = 0; i < nodes.length; i++) {
var name = nodes[i].nodeName;
var value = OpenLayers.Util.getXmlNodeValue(nodes[i]);
// Ignore Geometry attributes
// match ".//gml:pos|.//gml:posList|.//gml:coordinates"
if((name.search(":pos")!=-1)
||(name.search(":posList")!=-1)
||(name.search(":coordinates")!=-1)){
continue;
}
// Check for a leaf node
if((nodes[i].childNodes.length == 1 && nodes[i].childNodes[0].nodeName == "#text")
|| (nodes[i].childNodes.length == 0 && nodes[i].nodeName!="#text")) {
attributes[name] = value;
}
OpenLayers.Util.extend(attributes, this.parseAttributes(nodes[i]))
}
return attributes;
},
/**
* Method: parseCoords
* Extract Geographic coordinates from an XML node.
*
* Parameters:
* xmlNode - {<XMLNode>}
*
* Returns:
* An array of <OpenLayers.Geometry.Point> points.
*/
parseCoords: function(xmlNode) {
var p = [];
p.points = [];
// TBD: Need to handle an array of coordNodes not just coordNodes[0]
var coordNodes = OpenLayers.Ajax.getElementsByTagNameNS(xmlNode, this.kmlns, "", "coordinates")[0];
var coordString = OpenLayers.Util.getXmlNodeValue(coordNodes);
var firstCoord = coordString.split(" ");
while (firstCoord[0] == "")
firstCoord.shift();
var dim = firstCoord[0].split(",").length;
// Extract an array of Numbers from CoordString
var nums = (coordString) ? coordString.split(/[, \n\t]+/) : [];
// Remove elements caused by leading and trailing white space
while (nums[0] == "")
nums.shift();
while (nums[nums.length-1] == "")
nums.pop();
for(i = 0; i < nums.length; i = i + dim) {
x = parseFloat(nums[i]);
y = parseFloat(nums[i+1]);
p.points.push(new OpenLayers.Geometry.Point(x, y));
if (!p.bounds) {
p.bounds = new OpenLayers.Bounds(x, y, x, y);
} else {
p.bounds.extend(x, y);
}
}
return p;
},
/** @final @type String */
CLASS_NAME: "OpenLayers.Format.KML"
});