[OpenLayers-Dev] OpenLayers.Format.KML.write()

Tim Schaub tschaub at openplans.org
Wed Aug 15 11:13:51 EDT 2007


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
> 
> 
> --8<-------------------------------------------------------------------------------------
> 
> 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:
> @@ -100,6 +100,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;
> @@ -190,6 +203,136 @@
>          }
>          return p;
>      },
> +   
> +    /**
> +     * Accept Feature Collection, and return a string.
> +     *
> +     * @param {Array} List of features to serialize into a string.
> +     */
> +     write: function(features) {
> +        var kml = 
> document.createElementNS("http://earth.google.com/kml/2.0", "kml:kml"); 
> // 'kml:' NS to be removed?
> +        for (var i=0; i < features.length; i++) {
> +            kml.appendChild(this.createPlacemarkXML(features[i]));
> +        }
> +        return kml;
> +     },
> +
> +    /**
> +     * Accept an OpenLayers.Feature.Vector, and build a geometry for it.
> +     *
> +     * @param OpenLayers.Feature.Vector feature
> +     * @return DOMElement
> +     */
> +    createPlacemarkXML: function(feature) {
> +        // Placemark name
> +        var placemarkName = document.createElementNS(this.kmlns, "kml:" 
> + "name");
> +        var placemarkNameText = document.createTextNode(feature.id);
> +        placemarkName.appendChild(placemarkNameText);
> +
> +        // Placemark description
> +        var placemarkDesc = document.createElementNS(this.kmlns, "kml:" 
> + "description");
> +        var placemarkDescText = document.createTextNode("Not available");
> +        placemarkDesc.appendChild(placemarkDescText);
> +       
> +        // Placemark
> +        var placemarkNode = document.createElementNS(this.kmlns, "kml:" 
> + "Placemark");
> +        placemarkNode.appendChild(placemarkName);
> +        placemarkNode.appendChild(placemarkDesc);
> +
> +        // Geometry node (Point, LineString, etc. nodes)
> +        var geometryNode = this.buildGeometryNode(feature.geometry);
> +        placemarkNode.appendChild(geometryNode);       
> +       
> +        return placemarkNode;
> +    },   
> +
> +    /**
> +     * builds a KML geometry node with a given geometry
> +     *
> +     * @param {OpenLayers.Geometry} geometry
> +     */
> +    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, 'kml:Polygon');
> +               
> +                var polygon = document.createElementNS(this.kmlns, 
> 'kml:Polygon');
> +                var outerRing = document.createElementNS(this.kmlns, 
> 'kml:outerBoundaryIs');
> +                var linearRing = document.createElementNS(this.kmlns, 
> 'kml:LinearRing');
> +               
> +                // TBD manage polygons with holes
> +                
> linearRing.appendChild(this.buildCoordinatesNode(geometry.components[0]));
> +                outerRing.appendChild(linearRing);
> +                polygon.appendChild(outerRing);
> +               
> +                kml.appendChild(polygon);
> +            }
> +        // match MultiLineString or LineString
> +        else if (geometry.CLASS_NAME == 
> "OpenLayers.Geometry.MultiLineString"
> +                 || geometry.CLASS_NAME == 
> "OpenLayers.Geometry.LineString") {
> +                     kml = document.createElementNS(this.kmlns, 
> 'kml:LineString');
> +                    
> +                     var lineString = 
> document.createElementNS(this.kmlns, 'kml:LineString');
> +                    
> +                     
> lineString.appendChild(this.buildCoordinatesNode(geometry));
> +                    
> +                     kml.appendChild(lineString);
> +                 }
> +        // match MultiPoint or Point
> +        else if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point" ||
> +                  geometry.CLASS_NAME == 
> "OpenLayers.Geometry.MultiPoint") {                    
> +                kml = document.createElementNS(this.kmlns, 'kml: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++) {
> +                    var point = document.createElementNS(this.kmlns, 
> 'kml:Point');
> +                    point.appendChild(this.buildCoordinatesNode(parts[i]));
> +                    kml.appendChild(point);
> +               }    
> +        }
> +        return kml;        
> +    },
> +    
> +    /**
> +     * builds the coordinates XmlNode
> +     * <kml:coordinates>...</kml:coordinates>
> +     *
> +     * @param {OpenLayers.Geometry} geometry
> +     * @return {XmlNode} created xmlNode
> +     */
> +    buildCoordinatesNode: function(geometry) {
> +        var coordinatesNode = document.createElementNS(this.kmlns, 
> "kml: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"
>  });    
> 
> 
> 
> 
> Christopher Schmidt wrote:
>> On Tue, Aug 14, 2007 at 04:16:32PM +0200, Damien Corpataux wrote:
>>   
>>> Hello,
>>>
>>> I'd like to implement a bit of OpenLayers.Format.KML.write() method, and
>>> enhance OpenLayers.Format.KML.read() to enabl.e Polygon node parsing...
>>>
>>> Questions:
>>> 1/ Did you have any reason not to have implemented Polygon parsing at
>>> once with Point and LineString? I thought it could be because of the
>>> outerBoudaryIs node, which cannot be translated into OpenLayers.Geometry
>>> object...? Or was it just laziness? :-)
>>>     
>>
>> Just laziness.
>>
>>   
>>> 2/ How do you see the namespaces for KML? My view is that one can parse
>>> any KML as a 2.0, fetching Placemark nodes and digging into their
>>> geometries, since this seems not to change over versions. Do you think
>>> it's a good way of doing it?
>>>     
>>
>> I didn't know enough about KML at the time I wrote it to know if this
>> was true or not. I'd be happy to be better informed either way. 
>>
>> Regards,
>>   
> 
> 
> -- 
> 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,46c30f78118678362916074!
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Dev mailing list
> Dev at openlayers.org
> http://openlayers.org/mailman/listinfo/dev
> 
> 
> !DSPAM:4033,46c30f78118678362916074!




More information about the Dev mailing list