OpenLayers OpenLayers

Ticket #1366: atom.patch

File atom.patch, 20.8 kB (added by tschaub, 4 months ago)

adds an atom format

  • tests/Format/Atom.html

    old new  
     1<html>  
     2<head>  
     3    <script src="../../lib/OpenLayers.js"></script>  
     4    <script type="text/javascript"> 
     5 
     6    function test_initialize(t) { 
     7        t.plan(1); 
     8        var atom = new OpenLayers.Format.Atom(); 
     9        t.ok(atom instanceof OpenLayers.Format.Atom, "returns an instance"); 
     10    } 
     11     
     12    function test_read(t) { 
     13        t.plan(10); 
     14         
     15        var atom = new OpenLayers.Format.Atom(); 
     16        var features = atom.read(entry); 
     17        var point = features[0]; 
     18        t.ok(point instanceof OpenLayers.Feature.Vector, "entry read as feature"); 
     19        t.eq(point.fid, "OpenLayers.Feature.Vector_135", "id parsed"); 
     20 
     21        var attributes = point.attributes; 
     22        t.eq(attributes["foo"], "bar", "foo attribute read correctly"); 
     23        t.eq(attributes["foo2"], "bar2", "foo2 attribute read correctly"); 
     24        t.eq(attributes["link"], "http://example.com", "link parsed"); 
     25        t.eq(attributes["description"], "the description", "summary parsed"); 
     26        t.eq(attributes["content"], "the content", "content parsed"); 
     27         
     28        var geometry = point.geometry; 
     29        t.geom_eq(geometry, new OpenLayers.Geometry.Point(100, -5), "geometry parsed"); 
     30         
     31        features = atom.read(feed); 
     32        t.eq(features.length, 3, "three features in feed"); 
     33        t.ok(features[0].geometry instanceof OpenLayers.Geometry.Polygon, "first feature polygon"); 
     34         
     35    } 
     36     
     37    function test_write(t) { 
     38        t.plan(2); 
     39 
     40        var atom = new OpenLayers.Format.Atom(); 
     41         
     42        var str, feature, features; 
     43         
     44 
     45        features = atom.read(entry); 
     46        str = atom.write(features[0]); 
     47        t.xml_eq(str, entry, "entry round trip"); 
     48         
     49        features = atom.read(feed); 
     50        str = atom.write(features); 
     51        t.xml_eq(str, feed, "feed round trip"); 
     52         
     53    } 
     54     
     55    var entry = '<entry xmlns="http://www.w3.org/2005/Atom"><summary>the description</summary><content>the content</content><link href="http://example.com"/><category scheme="http://namespace.openlayers.org/atom#attributes" term="foo/bar"/><category scheme="http://namespace.openlayers.org/atom#attributes" term="foo2/bar2"/><georss:where xmlns:georss="http://www.georss.org/georss"><gml:Point xmlns:gml="http://www.opengis.net/gml"><gml:pos>-5 100</gml:pos></gml:Point></georss:where><id>OpenLayers.Feature.Vector_135</id></entry>'; 
     56     
     57    var feed = '<feed xmlns="http://www.w3.org/2005/Atom"><entry><georss:where xmlns:georss="http://www.georss.org/georss"><gml:Polygon xmlns:gml="http://www.opengis.net/gml"><gml:exterior><gml:LinearRing><gml:posList>26.3671875 -52.734375 3.8671875 -66.09375 -10.1953125 -31.640625 13.0078125 -28.828125 26.3671875 -52.734375</gml:posList></gml:LinearRing></gml:exterior></gml:Polygon></georss:where></entry><entry><summary>the description</summary><content>the content</content><link href="http://example.com"/><category scheme="http://namespace.openlayers.org/atom#attributes" term="foo/bar"/><category scheme="http://namespace.openlayers.org/atom#attributes" term="foo2/bar2"/><georss:where xmlns:georss="http://www.georss.org/georss"><gml:Point xmlns:gml="http://www.opengis.net/gml"><gml:pos>-5 100</gml:pos></gml:Point></georss:where><id>OpenLayers.Feature.Vector_135</id></entry><entry><georss:where xmlns:georss="http://www.georss.org/georss"><gml:LineString xmlns:gml="http://www.opengis.net/gml"><gml:posList>27.7734375 16.875 10.1953125 40.078125 -25.6640625 -6.328125 -40.4296875 40.078125</gml:posList></gml:LineString></georss:where></entry></feed>'; 
     58     
     59    </script>  
     60</head>  
     61<body>  
     62</body>  
     63</html>  
  • tests/list-tests.html

    old new  
    4040    <li>Filter/Logical.html</li> 
    4141    <li>Filter/Spatial.html</li> 
    4242    <li>Format.html</li> 
     43    <li>Format/Atom.html</li> 
    4344    <li>Format/GeoJSON.html</li> 
    4445    <li>Format/GeoRSS.html</li> 
    4546    <li>Format/GML.html</li> 
  • lib/OpenLayers/Format/Atom.js

    old new  
     1/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD 
     2 * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the 
     3 * full text of the license. */ 
     4 
     5/** 
     6 * @requires OpenLayers/Format/XML.js 
     7 * @requires OpenLayers/Format/GML/v3.js 
     8 */ 
     9 
     10/** 
     11 * Class: OpenLayers.Format.Atom 
     12 * Read/write Atom + GeoRSS parser. Create a new instance with the  
     13 *     <OpenLayers.Format.Atom> constructor. 
     14 * 
     15 * Inherits from: 
     16 *  - <OpenLayers.Format.XML> 
     17 */ 
     18OpenLayers.Format.Atom = OpenLayers.Class(OpenLayers.Format.XML, { 
     19     
     20    /** 
     21     * Property: namespaces 
     22     * {Object} Mapping of namespace aliases to namespace URIs. 
     23     */ 
     24    namespaces: { 
     25        atom: "http://www.w3.org/2005/Atom", 
     26        georss: "http://www.georss.org/georss", 
     27        gml: "http://www.opengis.net/gml" 
     28    }, 
     29     
     30    /** 
     31     * Property: defaultPrefix 
     32     * {String} The namespace alias to use for node names with no prefix. 
     33     *     Default is "atom". 
     34     */ 
     35    defaultPrefix: "atom", 
     36     
     37    /** 
     38     * Property: categoryScheme 
     39     * {String} An IRI that identifies a categorization scheme for parsing 
     40     *     of atom:category elements. Default is 
     41     *     http://namespace.openlayers.org/atom#attributes. 
     42     */ 
     43    categoryScheme: "http://namespace.openlayers.org/atom#attributes", 
     44     
     45    /** 
     46     * Property: writeOptions 
     47     * {Object} Optional configuration for <write>. 
     48     */ 
     49    writeOptions: null, 
     50     
     51    /** 
     52     * Property: writeCallback 
     53     * {Function} 
     54     */ 
     55    writeCallback: null, 
     56 
     57    /** 
     58     * Property: readOptions 
     59     * {Object} Optional configuration for <read>. 
     60     */ 
     61    readOptions: null, 
     62     
     63    /** 
     64     * Property: readCallback 
     65     * {Function} 
     66     */ 
     67    readCallback: null, 
     68 
     69    /** 
     70     * APIProperty: xy 
     71     * {Boolean} Order of the GML coordinate: true:(x,y) or false:(y,x) 
     72     *     For GeoRSS the default is (y,x), therefore: false 
     73     */  
     74    xy: false, 
     75     
     76    /** 
     77     * APIProperty: srsName 
     78     * {String} URI for spatial reference system.  This is optional for 
     79     *     single part geometries and mandatory for collections and multis. 
     80     *     If set, the srsName attribute will be written for all geometries. 
     81     *     Default is null. 
     82     */ 
     83    srsName: null, 
     84 
     85    /** 
     86     * Property: regExes 
     87     * Compiled regular expressions for manipulating strings. 
     88     */ 
     89    regExes: OpenLayers.Format.GML.Base.prototype.regExes, 
     90 
     91    /** 
     92     * Constructor: OpenLayers.Format.Atom 
     93     * Create a new parser for Atom. 
     94     * 
     95     * Parameters: 
     96     * options - {Object} An optional object whose properties will be set on 
     97     *     this instance. 
     98     */ 
     99    initialize: function(options) { 
     100        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]); 
     101        this.writeOptions = this.writeOptions || {}; 
     102        this.readOptions = this.readOptions || {}; 
     103    }, 
     104     
     105    /** 
     106     * APIMethod: read 
     107     * Return a list of features from an Atom feed or Atom entry doc. 
     108      
     109     * Parameters: 
     110     * data - {Element}  
     111     * options - {Object} Optional object for configuring the read. 
     112     * 
     113     * Supported options: 
     114     * callback - {Function} A function that will be called for each atom:entry 
     115     *     node prior to returning the feature representing that node.  The 
     116     *     callback will receive node and feature as arguments. 
     117     * 
     118     * Returns: 
     119     * {Array(<OpenLayers.Feature.Vector>)} An array of features. 
     120     */ 
     121    read: function(doc, options) { 
     122        options = options || {}; 
     123        this.readCallback = options.callback || this.readOptions.callback; 
     124        if (typeof doc == "string") {  
     125            doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]); 
     126        } 
     127         
     128        var obj = {features: []}; 
     129        this.readChildNodes(doc, obj); 
     130         
     131        return obj.features; 
     132    }, 
     133 
     134    /** 
     135     * Property: readers 
     136     * Contains public functions, grouped by namespace prefix, that will 
     137     *     be applied when a namespaced node is found matching the function 
     138     *     name.  The function will be applied in the scope of this parser 
     139     *     with two arguments: the node being read and a context object passed 
     140     *     from the parent. 
     141     */ 
     142    readers: { 
     143        "atom": { 
     144            "feed": function(node, obj) { 
     145                // only extracting entries out of feed for now 
     146                var entries = this.getElementsByTagNameNS( 
     147                    node, this.namespaces.atom, "entry" 
     148                ); 
     149                if(entries) { 
     150                    for(var i=0, len=entries.length; i<len; ++i) { 
     151                        this.readers.atom.entry.apply(this, [entries[i], obj]); 
     152                    } 
     153                } 
     154            }, 
     155            "entry": function(node, obj) { 
     156                var feature = new OpenLayers.Feature.Vector(); 
     157                this.readChildNodes(node, feature); 
     158         
     159                if(feature.geometry && 
     160                   this.internalProjection && this.externalProjection) { 
     161                    feature.geometry.transform( 
     162                        this.externalProjection, 
     163                        this.internalProjection 
     164                    ); 
     165                } 
     166                if(this.readCallback) { 
     167                    this.readCallback(node, feature); 
     168                } 
     169                obj.features.push(feature); 
     170            }, 
     171            "title": function(node, feature) { 
     172                feature.attributes.title = this.getChildValue(node); 
     173            }, 
     174            "summary": function(node, feature) { 
     175                feature.attributes.description = this.getChildValue(node); 
     176            }, 
     177            "content": function(node, feature) { 
     178                feature.attributes.content = this.getChildValue(node); 
     179            }, 
     180            "link": function(node, feature) { 
     181                feature.attributes.link = node.getAttribute("href"); 
     182            }, 
     183            "id": function(node, feature) { 
     184                feature.fid = this.getChildValue(node); 
     185            }, 
     186            "category": function(node, feature) { 
     187                /** 
     188                 * Only parses category with a scheme of 
     189                 * http://namespace.openlayers.org/atom#attributes 
     190                 * Assumes term values map to feature attributes. 
     191                 * 
     192                 * atom:category elements should look like 
     193                 * <category scheme=http://namespace.openlayers.org/atom#attributes" 
     194                 *           term="key/value"/> 
     195                 * 
     196                 * Where this would become feature.attributes[key] = value 
     197                 */ 
     198                if(node.getAttribute("scheme") == this.categoryScheme) { 
     199                    var pair = node.getAttribute("term").split("/"); 
     200                    feature.attributes[decodeURIComponent(pair[0])] = 
     201                        decodeURIComponent(pair[1]); 
     202                } 
     203            } 
     204        }, 
     205        "georss": { 
     206            "point": function(node, feature) { 
     207                if(!feature.geometry) { 
     208                    var location = OpenLayers.String.trim( 
     209                        this.getNodeValue(node).split(/\s+/) 
     210                    ); 
     211                    if(location.length !=2) { 
     212                        location = OpenLayers.String.trim( 
     213                            this.getNodeValue(node).split(/\s*,\s*/) 
     214                        ); 
     215                    } 
     216                    feature.geometry = new OpenLayers.Geometry.Point( 
     217                        parseFloat(location[1]), 
     218                        parseFloat(location[0]) 
     219                    ); 
     220                } 
     221            }, 
     222            "line": function(node, feature) { 
     223                if(!feature.geometry) { 
     224                    var coords = OpenLayers.String.trim( 
     225                        this.getChildValue(node).split(/\s+/) 
     226                    ); 
     227                    var components = []; 
     228                    for(var i=0, len=coords.length; i<len; i+=2) { 
     229                        components.push(new OpenLayers.Geometry.Point( 
     230                            parseFloat(coords[i+1]),  
     231                            parseFloat(coords[i]) 
     232                        )); 
     233                    } 
     234                    feature.geometry = new OpenLayers.Geometry.LineString(components); 
     235                } 
     236            }, 
     237            "polygon": function(node, feature) { 
     238                if(!feature.geometry) { 
     239                    var coords = OpenLayers.String.trim( 
     240                        this.getChildValue(node).split(/\s+/) 
     241                    ); 
     242                    var components = [];  
     243                    for(var i=0, len=coords.length; i<len; i+=2) { 
     244                        components.push(new OpenLayers.Geometry.Point( 
     245                            parseFloat(coords[i+1]),  
     246                            parseFloat(coords[i]) 
     247                        )); 
     248                    } 
     249                    feature.geometry = new OpenLayers.Geometry.Polygon( 
     250                        [new OpenLayers.Geometry.LinearRing(components)] 
     251                    ); 
     252                } 
     253            }, 
     254            "where": function(node, feature) { 
     255                if(!feature.geometry) { 
     256                    var obj = {components: []}; 
     257                    this.readChildNodes(node, obj); 
     258                    if(obj.components.length > 0) { 
     259                        feature.geometry = obj.components[0]; 
     260                    } 
     261                } 
     262            } 
     263        }, 
     264        "gml": OpenLayers.Format.GML.v3.prototype.readers["gml"] 
     265    }, 
     266 
     267    /** 
     268     * APIMethod: write 
     269     * Accept Feature Collection, and return a string.  
     270     *  
     271     * Parameters:  
     272     * features - {Array(<OpenLayers.Feature.Vector>)} List of features to 
     273     *     serialize into a string. 
     274     * options - {Object} Optional object for configuring the write. 
     275     * 
     276     * Supported options: 
     277     * callback - {Function} A function that will be called for each feature 
     278     *     prior to returning the node representing that feature.  The callback 
     279     *     will receive feature and node as arguments. 
     280     * 
     281     * Returns: 
     282     * {String} An Atom doc as string. 
     283     */ 
     284    write: function(features, options) { 
     285        options = options || {}; 
     286        this.writeCallback = options.callback || this.writeOptions.callback; 
     287        var atom; 
     288        if (features instanceof Array) { 
     289            atom = this.writeNode("feed", features); 
     290        } else { 
     291            atom = this.writeNode("entry", features); 
     292        } 
     293        return OpenLayers.Format.XML.prototype.write.apply(this, [atom]); 
     294    }, 
     295     
     296    /** 
     297     * Property: writers 
     298     * As a compliment to the <readers> property, this structure contains public 
     299     *     writing functions grouped by namespace alias and named like the 
     300     *     node names they produce. 
     301     */ 
     302    writers: { 
     303        "atom": { 
     304            "feed": function(features) { 
     305                var node = this.createElementNSPlus("feed"); 
     306                for(var i=0, len=features.length; i<len; ++i) { 
     307                    this.writeNode("entry", features[i], node); 
     308                } 
     309                return node; 
     310            }, 
     311            "entry": function(feature) { 
     312                var node = this.createElementNSPlus("entry"); 
     313                // write attributes 
     314                var value; 
     315                for(var key in feature.attributes) { 
     316                    var value = feature.attributes[key]; 
     317                    if(this.attributeMap[key]) { 
     318                        this.writeNode( 
     319                            this.attributeMap[key], value, node 
     320                        ); 
     321                    } else { 
     322                        this.writeNode( 
     323                            "category", 
     324                            { 
     325                                scheme: this.categoryScheme, 
     326                                term: encodeURIComponent(key) + "/"+ 
     327                                      encodeURIComponent(value) 
     328                            }, 
     329                            node 
     330                        ); 
     331                    } 
     332                } 
     333                // write geometry 
     334                if(feature.geometry) { 
     335                    this.writeNode("georss:where", feature.geometry, node); 
     336                } 
     337                // write fid 
     338                if(feature.fid) { 
     339                    this.writeNode("id", feature.fid, node); 
     340                } 
     341                if(this.writeCallback) { 
     342                    this.writeCallback(feature, node); 
     343                } 
     344                return node; 
     345            }, 
     346            "title": function(value) { 
     347                return this.createElementNSPlus("title", {value: value}); 
     348            }, 
     349            "summary": function(value) { 
     350                return this.createElementNSPlus("summary", {value: value}); 
     351            }, 
     352            "content": function(value) { 
     353                return this.createElementNSPlus("content", {value: value}); 
     354            }, 
     355            "link": function(href) { 
     356                return this.createElementNSPlus("link", { 
     357                    attributes: {href: href} 
     358                }); 
     359            }, 
     360            "id": function(value) { 
     361                return this.createElementNSPlus("id", {value: value}); 
     362            }, 
     363            "category": function(obj) { 
     364                return this.createElementNSPlus("category", { 
     365                    attributes: { 
     366                        scheme: obj.scheme, term: obj.term, label: obj.label 
     367                    } 
     368                }); 
     369            } 
     370        }, 
     371        "georss": { 
     372            "where": function(geometry) { 
     373                if(this.externalProjection && this.internalProjection) { 
     374                    geometry = geometry.clone().transform( 
     375                        this.internalProjection, this.externalProjection 
     376                    ); 
     377                } 
     378                var node = this.createElementNSPlus("georss:where"); 
     379                var type = this.geometryTypes[geometry.CLASS_NAME]; 
     380                this.writeNode("gml:" + type, geometry, node); 
     381                return node; 
     382            } 
     383        }, 
     384        "gml": OpenLayers.Format.GML.v3.prototype.writers["gml"] 
     385    }, 
     386     
     387    /** 
     388     * Property: geometryTypes 
     389     * {Object} Maps OpenLayers geometry class names to GML element names. 
     390     */ 
     391    geometryTypes: OpenLayers.Format.GML.Base.prototype.geometryTypes, 
     392 
     393    /** 
     394     * Property: attributeMap 
     395     * {Object} Maps feature attribute names to atom element names. 
     396     */ 
     397    attributeMap: { 
     398        "title": "title", 
     399        "description": "summary", 
     400        "content": "content", 
     401        "link": "link" 
     402    }, 
     403 
     404    CLASS_NAME: "OpenLayers.Format.Atom"  
     405});      
  • lib/OpenLayers.js

    old new  
    203203            "OpenLayers/Format.js", 
    204204            "OpenLayers/Format/XML.js", 
    205205            "OpenLayers/Format/GML.js", 
     206            "OpenLayers/Format/Atom.js", 
    206207            "OpenLayers/Format/KML.js", 
    207208            "OpenLayers/Format/GeoRSS.js", 
    208209            "OpenLayers/Format/WFS.js", 
  • examples/vector-formats.html

    old new  
    6363                geojson: new OpenLayers.Format.GeoJSON(in_options), 
    6464                georss: new OpenLayers.Format.GeoRSS(in_options), 
    6565                gml: new OpenLayers.Format.GML(in_options), 
     66                atom: new OpenLayers.Format.Atom(in_options), 
    6667                kml: new OpenLayers.Format.KML(in_options) 
    6768              },  
    6869              'out': { 
     
    7071                geojson: new OpenLayers.Format.GeoJSON(out_options), 
    7172                georss: new OpenLayers.Format.GeoRSS(out_options), 
    7273                gml: new OpenLayers.Format.GML(out_options), 
     74                atom: new OpenLayers.Format.Atom(out_options), 
    7375                kml: new OpenLayers.Format.KML(out_options) 
    7476              }  
    7577            }; 
     
    168170            <select name="formatType" id="formatType"> 
    169171                <option value="geojson" selected="selected">GeoJSON</option> 
    170172                <option value="kml">KML</option> 
     173                <option value="atom">Atom</option> 
    171174                <option value="georss">GeoRSS</option> 
    172175                <option value="gml">GML</option> 
    173176                <option value="wkt">Well-Known Text (WKT)</option>