Hi Tim, I just posted a patch on ticket #927. The patch suits the requirements: - KML extends XML - XML class methods are used for XML manipulation - tested on FF2/Linux and IE7 - KML.write() returns a string (using XML.write()) - GGE import of OL exported KML is working, and vice-versa
My 2 cents Cheers, Damien Tim Schaub wrote: > I've opened ticket #927 to track this. > > If anybody has a patch for KML, please attach it to that ticket. > Damien, I've referenced your email on the ticket. > > Since XML flavors should now all inherit from the XML format class, I'd > say that write will always return a string. > > Thanks for any contributions. > Tim > > > Damien Corpataux wrote: > >> Hello, >> >> As far as I can see, the advantages of doing so are obvious. Althought I >> didn't have time to apply these, here is a new version of the patch: >> - puts placemarks in a folder tag (for google earth import) >> - bugfix with geometry tags >> >> Is the question about write() return type (string or DOMDocuemt/DOMNode) >> still open? >> >> Cheers, >> Damien >> >> >> Patch: >> Index: /home/dcorpataux/workspace/openlayers/lib/OpenLayers/Format/KML.js >> =================================================================== >> --- >> /home/dcorpataux/workspace/openlayers/lib/OpenLayers/Format/KML.js >> (revision 3900) >> +++ >> /home/dcorpataux/workspace/openlayers/lib/OpenLayers/Format/KML.js >> (working copy) >> @@ -8,8 +8,8 @@ >> * @requires OpenLayers/Ajax.js >> * >> * Class: OpenLayers.Format.KML >> - * Read only KML. Largely Proof of Concept: does not support advanced >> Features, >> - * including Polygons. Create a new instance with the >> + * Read/write KML 2.0. Does not support advanced Features. >> + * Create a new instance with the >> * <OpenLayers.Format.KML> constructor. >> * >> * Inherits from: >> @@ -24,6 +24,24 @@ >> kmlns: "http://earth.google.com/kml/2.0", >> >> /** >> + * APIProperty: placemarksDesc >> + * Default description for a placemark >> + */ >> + placemarksDesc: "No description available", >> + >> + /** >> + * APIProperty: foldersName >> + * Default name for a folder >> + */ >> + foldersName: "OpenLayers export", >> + >> + /** >> + * APIProperty: foldersDesc >> + * Default description for a folder >> + */ >> + foldersDesc: "Exported on " + new Date(), >> + >> + /** >> * Constructor: OpenLayers.Format.KML >> * Create a new parser for KML >> * >> @@ -46,7 +64,7 @@ >> if (typeof data == "string") { >> data = OpenLayers.parseXMLString(data); >> } >> - var featureNodes = OpenLayers.Ajax.getElementsByTagNameNS(data, >> this.kmlns, "", "Placemark"); >> + var featureNodes = OpenLayers.Ajax.getElementsByTagNameNS(data, >> this.kmlns, "kml", "Placemark"); >> >> var features = []; >> >> @@ -100,6 +118,19 @@ >> // TBD Bounds only set for one of multiple geometries >> geom.extendBounds(p.bounds); >> } >> + >> + // match Polygon >> + } else if (OpenLayers.Ajax.getElementsByTagNameNS(xmlNode, >> + this.kmlns, "", "Polygon").length != 0) { >> + var polygon = OpenLayers.Ajax.getElementsByTagNameNS(xmlNode, >> + this.kmlns, "", "Polygon")[0]; >> + p = this.parseCoords(polygon); >> + if (p.points) { >> + var linearRing = new >> OpenLayers.Geometry.LinearRing(p.points); >> + geom = new OpenLayers.Geometry.Polygon(linearRing); >> + // TBD Bounds only set for one of multiple geometries >> + geom.extendBounds(p.bounds); >> + } >> } >> >> feature.geometry = geom; >> @@ -191,5 +222,171 @@ >> return p; >> }, >> >> + /** >> + * Method: write >> + * Accept Feature Collection, and return an XML Document. >> + * >> + * Parameters: >> + * features - An array of <OpenLayers.Feature.Vector> features. >> + * >> + * Returns: >> + * <DOMDocument> >> + */ >> + write: function(features) { >> + var kml = document.createElementNS(this.kmlns, "kml"); >> + var folder = this.createFolderXML(); >> + for (var i=0; i < features.length; i++) { >> + folder.appendChild(this.createPlacemarkXML(features[i])); >> + } >> + kml.appendChild(folder); >> + return kml; >> + }, >> + >> + /** >> + * Method: createFolderXML >> + * Creates and returns a KML Folder node with default name and >> description >> + * >> + * Returns: >> + * xmlNode - {<XMLNode>} >> + */ >> + createFolderXML: function() { >> + // Folder name >> + var folderName = document.createElementNS(this.kmlns, "name"); >> + var folderNameText = document.createTextNode(this.foldersName); >> + folderName.appendChild(folderNameText); >> + >> + // Folder description >> + var folderDesc = document.createElementNS(this.kmlns, >> "description"); >> + var folderDescText = document.createTextNode(this.foldersDesc); >> + folderDesc.appendChild(folderDescText); >> + >> + // Folder >> + var folder = document.createElementNS(this.kmlns, "Folder"); >> + folder.appendChild(folderName); >> + folder.appendChild(folderDesc); >> + >> + return folder; >> + }, >> + >> + /** >> + * Method: createPlacemarkXML >> + * Accept an OpenLayers.Feature.Vector, and create a KML Placemark node >> + * >> + * Parameters: >> + * feature - {<OpenLayers.Feature.Vector>} >> + * >> + * Returns: >> + * xmlNode - {<XMLNode>} >> + */ >> + createPlacemarkXML: function(feature) { >> + // Placemark name >> + var placemarkName = document.createElementNS(this.kmlns, "name"); >> + var placemarkNameText = document.createTextNode(feature.id); >> + placemarkName.appendChild(placemarkNameText); >> + >> + // Placemark description >> + var placemarkDesc = document.createElementNS(this.kmlns, >> "description"); >> + var placemarkDescText = >> document.createTextNode(this.placemarksDesc); >> + placemarkDesc.appendChild(placemarkDescText); >> + >> + // Placemark >> + var placemarkNode = document.createElementNS(this.kmlns, >> "Placemark"); >> + placemarkNode.appendChild(placemarkName); >> + placemarkNode.appendChild(placemarkDesc); >> + >> + // Geometry node (Point, LineString, etc. nodes) >> + var geometryNode = this.buildGeometryNode(feature.geometry); >> + placemarkNode.appendChild(geometryNode); >> + >> + return placemarkNode; >> + }, >> + >> + /** >> + * Method: buildGeometryNode >> + * Builds a KML geometry node with a given geometry >> + * >> + * Parameters: >> + * geometry - {<OpenLayers.Geometry>} >> + * >> + * Returns: >> + * xmlNode - {<XMLNode>} >> + */ >> + buildGeometryNode: function(geometry) { >> + // TBD test if geoserver can be given a Multi-geometry for a >> simple-geometry data store >> + // ie if multipolygon can be sent for a polygon feature type >> + var kml = ""; >> + // match MultiPolygon or Polygon >> + if (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPolygon" >> + || geometry.CLASS_NAME == "OpenLayers.Geometry.Polygon") { >> + kml = document.createElementNS(this.kmlns, 'Polygon'); >> + >> + var outerRing = document.createElementNS(this.kmlns, >> 'outerBoundaryIs'); >> + var linearRing = document.createElementNS(this.kmlns, >> 'LinearRing'); >> + >> + // TBD manage polygons with holes >> + >> linearRing.appendChild(this.buildCoordinatesNode(geometry.components[0])); >> + outerRing.appendChild(linearRing); >> + >> + kml.appendChild(outerRing); >> + } >> + // match MultiLineString or LineString >> + else if (geometry.CLASS_NAME == >> "OpenLayers.Geometry.MultiLineString" >> + || geometry.CLASS_NAME == >> "OpenLayers.Geometry.LineString") { >> + kml = document.createElementNS(this.kmlns, >> 'LineString'); >> + >> + kml.appendChild(this.buildCoordinatesNode(geometry)); >> + } >> + // match MultiPoint or Point >> + else if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point" || >> + geometry.CLASS_NAME == >> "OpenLayers.Geometry.MultiPoint") { >> + kml = document.createElementNS(this.kmlns, 'Point'); >> + >> + // FIXME: There should be only one Point node per >> Placemark node >> + var parts = ""; >> + if (geometry.CLASS_NAME == >> "OpenLayers.Geometry.MultiPoint") { >> + parts = geometry.components; >> + } else { >> + parts = [geometry]; >> + } >> + >> + for (var i = 0; i < parts.length; i++) { >> + kml.appendChild(this.buildCoordinatesNode(parts[i])); >> + } >> + } >> + return kml; >> + }, >> + /** >> + * Method: buildCoordinatesNode >> + * builds the KML coordinates node >> + * >> + * Parameters: >> + * geometry - {<OpenLayers.Geometry>} >> + * >> + * Returns: >> + * xmlNode - {<XMLNode>} >> + */ >> + buildCoordinatesNode: function(geometry) { >> + var coordinatesNode = document.createElementNS(this.kmlns, >> "coordinates"); >> + >> + var points = null; >> + if (geometry.components) { >> + points = geometry.components; >> + } >> + >> + var path = ""; >> + if (points) { >> + for (var i = 0; i < points.length; i++) { >> + path += points[i].x + "," + points[i].y + " "; >> + } >> + } else { >> + path += geometry.x + "," + geometry.y + " "; >> + } >> + >> + var txtNode = document.createTextNode(path); >> + coordinatesNode.appendChild(txtNode); >> + >> + return coordinatesNode; >> + }, >> + >> CLASS_NAME: "OpenLayers.Format.KML" >> }); >> >> >> Tim Schaub wrote: >> >>> Hi- >>> >>> So, we're mid-way through changing how XML flavors are read/written in >>> OpenLayers. >>> >>> I've checked a new XML format in to the trunk. This format has most of >>> the methods we need for reading/writing XML cross-browser. >>> >>> To parse other XML flavors, format classes should be created that >>> inherit from the XML format. >>> >>> For an (incomplete) example, see: >>> http://dev.openlayers.org/sandbox/tschaub/xml/lib/OpenLayers/Format/GML.js >>> >>> (The important part to notice in the above example is that the GML >>> format inherits from the XML format.) >>> >>> Instead of using OpenLayers.Ajax methods or document methods, DOM >>> creation and traversal should be done with OpenLayers.Format.XML >>> methods. I've created methods to reflect the W3C standard XML DOM >>> methods - wrapping the standard ones and accommodating for non-compliant >>> browsers. >>> >>> If you (or anyone) needs additional XML DOM methods, they should be >>> added to the XML format. The next addition (in my mind) is >>> setAttributeNS. Aside from that, you should be able to do efficient >>> parsing and dom creation with the XML format methods. >>> >>> Please make modifications to the KML format in the trunk. Create a >>> ticket and attach patches in Trac. I can offer review or other help as >>> needed. >>> >>> I don't have time to keep these sandboxes entirely clean right now - so >>> please forgive anything you find that is in a half-developed state. >>> >>> Tim >>> >>> PS - Eventually, I'll move the following example into the trunk. It >>> would be nice if we could demonstrate read/write capability for all >>> vector formats in this way: >>> http://dev.openlayers.org/sandbox/tschaub/xml/examples/vector-formats.html >>> >>> (note again that this reflects partially complete work - and you should >>> not be surprised to encounter errors or see changes at any time) >>> >>> >>> Damien Corpataux wrote: >>> >>> >>>> Hello, >>>> >>>> Here's what I did so far... Reading KML only work for KML 2.0 namespaces >>>> for write() uses OpenLayers.Ajax.getElementsByTagNameNS(), but I'm >>>> pretty sure it will work on future versions (2.1 parsing successful). >>>> Also, GML and KML write() returns a Dom Document rather than a string. >>>> Should one change the result type, breaking OpenLayers.Format interface, >>>> or parse it into a string using OpenLayers.XML.....? >>>> >>>> Cheers, >>>> Damien >>>> >>>> >>>> >> [patch stripped] >> >> -- >> Camptocamp SA >> Damien Corpataux >> PSE A >> CH-1015 Lausanne >> +41 21 619 10 22 (Direct) >> +41 21 619 10 10 (Centrale) >> +41 21 619 10 00 (Fax) >> P Please consider the environment >> Do you really need to print this email? >> !DSPAM:4033,46cd662e41812090977483! >> >> >> ------------------------------------------------------------------------ >> >> _______________________________________________ >> Dev mailing list >> Dev@openlayers.org >> http://openlayers.org/mailman/listinfo/dev >> >> >> !DSPAM:4033,46cd662e41812090977483! >> > > _______________________________________________ > Dev mailing list > Dev@openlayers.org > http://openlayers.org/mailman/listinfo/dev > -- Camptocamp SA Damien Corpataux PSE A CH-1015 Lausanne +41 21 619 10 22 (Direct) +41 21 619 10 10 (Centrale) +41 21 619 10 00 (Fax) P Please consider the environment Do you really need to print this email?
_______________________________________________ Dev mailing list Dev@openlayers.org http://openlayers.org/mailman/listinfo/dev