Changeset 6963


Ignore:
Timestamp:
Apr 18, 2008 2:21:31 AM (8 years ago)
Author:
tschaub
Message:

Pulling out read/write code in a way that is easier to extend. Round-tripping all attributes.

Location:
sandbox/topp/almanac/lib/OpenLayers/Format
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • sandbox/topp/almanac/lib/OpenLayers/Format/Atom.js

    r6962 r6963  
    7878    initialize: function(options) {
    7979        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
     80        this.gmlParser = new OpenLayers.Format.GMLSF({'xy': this.xy});
    8081        this.featureAttributes = OpenLayers.Util.applyDefaults(
    8182            this.featureAttributes || {},
     
    8485    },
    8586   
     87    /**
     88     * APIMethod: read
     89     * Return a list of features from an Atom feed or Atom entry doc
     90     
     91     * Parameters:
     92     * data - {Element}
     93     *
     94     * Returns:
     95     * {Array(<OpenLayers.Feature.Vector>)} An array of features.
     96     */
     97    read: function(doc) {
     98        if (typeof doc == "string") {
     99            doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]);
     100        }
     101       
     102        var obj = {features: []};
     103        this.readChildNodes(doc, obj);
     104       
     105        return obj.features;
     106    },
     107
    86108    /**
    87109     * Property: readers
     
    94116    readers: {
    95117        "atom": {
     118            "feed": function(node, obj) {
     119                this.readChildNodes(node, obj);
     120            },
     121            "entry": function(node, obj) {
     122                var feature = new OpenLayers.Feature.Vector(
     123                    null, OpenLayers.Util.extend({}, this.featureAttributes)
     124                );
     125                this.readChildNodes(node, feature);
     126       
     127                if(feature.geometry &&
     128                   this.internalProjection && this.externalProjection) {
     129                    feature.geometry.transform(
     130                        this.externalProjection,
     131                        this.internalProjection
     132                    );
     133                }
     134                obj.features.push(feature);
     135            },
    96136            "title": function(node, feature) {
    97137                feature.attributes.title = this.getChildValue(node);
     
    168208            "*": function(node, feature) {
    169209                var key = node.nodeName.split(":").pop();
    170                 feature.attribute[key] = this.getChildValue(node);
     210                feature.attributes[key] = this.getChildValue(node);
    171211            }
    172212        }
    173213    },
    174 
    175     /**
    176      * Method: readChildNodes
    177      */
    178     readChildNodes: function(node, obj) {
    179         var children = node.childNodes;
    180         var child, group, reader, prefix, local;
    181         for(var i=0; i<children.length; ++i) {
    182             child = children[i];
    183             if(child.nodeType == 1) {
    184                 prefix = this.getNamespacePrefix(child.namespaceURI);
    185                 local = child.nodeName.split(":").pop();
    186                 group = this.readers[prefix];
    187                 if(group) {
    188                     reader = group[local];
    189                     if(reader) {
    190                         reader.apply(this, [child, obj]);
    191                     } else {
    192                         if(group["*"]) {
    193                             reader.apply(this, [child, obj]);
    194                         }
    195                     }
    196                 }
    197             }
    198         }
    199     },
    200 
    201     /**
    202      * Method: createFeatureFromEntry
    203      * Return a feature from an Atom entry.
    204      *
    205      * Parameters:
    206      * entry - {DOMElement} An Atom entry node.
    207      *
    208      * Returns:
    209      * {<OpenLayers.Feature.Vector>} A feature representing the entry.
    210      */
    211     createFeatureFromEntry: function(entry) {
    212         var feature = new OpenLayers.Feature.Vector(
    213             null, OpenLayers.Util.extend({}, this.featureAttributes)
    214         );
    215         this.readChildNodes(entry, feature);
    216 
    217         if(feature.geometry && this.internalProjection && this.externalProjection) {
    218             feature.geometry.transform(
    219                 this.externalProjection,
    220                 this.internalProjection
    221             );
    222         }
    223      
    224         return feature;
    225     },       
    226    
    227     /**
    228      * APIMethod: read
    229      * Return a list of features from an Atom feed doc
    230      
    231      * Parameters:
    232      * data - {Element}
    233      *
    234      * Returns:
    235      * An Array of <OpenLayers.Feature.Vector>s
    236      */
    237     read: function(doc) {
    238         if (typeof doc == "string") {
    239             doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]);
    240         }
    241 
    242         var itemlist = null;
    243         itemlist = this.getElementsByTagNameNS(doc, '*', 'entry');
    244        
    245         var numItems = itemlist.length;
    246         var features = new Array(numItems);
    247         for(var i=0; i<numItems; i++) {
    248             features[i] = this.createFeatureFromEntry(itemlist[i]);
    249         }
    250         return features;
    251     },
    252    
    253214
    254215    /**
     
    262223        var atom;
    263224        if (features instanceof Array) {
    264             atom = this.createElementNSPlus("feed");
    265             for (var i=0; i < features.length; i++) {
    266                 atom.appendChild(this.createFeatureXML(features[i]));
    267             }
     225            atom = this.writeNode("feed", features);
    268226        } else {
    269             atom = this.createFeatureXML(features);
     227            atom = this.writeNode("entry", features);
    270228        }
    271229        return OpenLayers.Format.XML.prototype.write.apply(this, [atom]);
    272230    },
    273231   
     232    /**
     233     * Property: writers
     234     * As a compliment to the <readers> property, this structure contains public
     235     *     writing functions grouped by namespace alias and named like the
     236     *     node names they produce.
     237     */
     238    writers: {
     239        "atom": {
     240            "feed": function(features) {
     241                var node = this.createElementNSPlus("feed");
     242                for(var i=0; i<features.length; ++i) {
     243                    this.writeNode("entry", features[i], node);
     244                }
     245                return node;
     246            },
     247            "entry": function(feature) {
     248                var node = this.createElementNSPlus("entry");
     249                // write geometry
     250                if(feature.geometry) {
     251                    this.writeNode("georss:where", feature.geometry, node);
     252                }
     253                // write attributes
     254                var name;
     255                for(var key in feature.attributes) {
     256                    if(this.attributeMap[key]) {
     257                        this.writeNode(
     258                            this.attributeMap[key], feature.attributes[key], node
     259                        );
     260                    } else {
     261                        this.writeNode(
     262                            "ol:*", {name: key, value: feature.attributes[key]}, node
     263                        );
     264                    }
     265                }
     266                // write fid
     267                if(feature.fid) {
     268                    this.writeNode("id", feature.fid, node);
     269                }
     270                return node;
     271            },
     272            "title": function(value) {
     273                return this.createElementNSPlus("title", {value: value});
     274            },
     275            "summary": function(value) {
     276                return this.createElementNSPlus("summary", {value: value});
     277            },
     278            "content": function(value) {
     279                return this.createElementNSPlus("content", {value: value});
     280            },
     281            "link": function(href) {
     282                return this.createElementNSPlus("link", {
     283                    attributes: {href: href}
     284                });
     285            },
     286            "id": function(value) {
     287                return this.createElementNSPlus("id", {value: value});
     288            }
     289        },
     290        "georss": {
     291            "where": function(geometry) {
     292                var node = this.createElementNSPlus("georss:where");
     293                node.appendChild(this.gmlParser.buildGeometryNode(geometry));
     294                return node;
     295            }
     296        },
     297        "ol": {
     298            "*": function(obj) {
     299                return this.createElementNSPlus("ol:" + obj.name, {
     300                    value: obj.value
     301                });
     302            }
     303        }
     304    },
     305
    274306    /**
    275307     * Property: attributeMap
     
    280312        "description": "summary",
    281313        "content": "content",
    282         "link": "link",
    283     },
    284    
    285     /**
    286      * Method: getAttributeForElement
    287      */
    288     getAttributeForElement: function(name) {
    289         name = name.split(":").pop();
    290         var attr;
    291         for(var key in this.attributeMap) {
    292             if(this.attributeMap[key] == name) {
    293                 attr = key;
    294                 break;
    295             }
    296         }
    297         return attr;
    298     },
    299 
    300     /**
    301      * Method: createFeatureXML
    302      * Accept an <OpenLayers.Feature.Vector>, and build a geometry for it.
    303      *
    304      * Parameters:
    305      * feature - {<OpenLayers.Feature.Vector>}
    306      *
    307      * Returns:
    308      * {DOMElement}
    309      */
    310     createFeatureXML: function(feature) {
    311         var whereNode = this.createElementNSPlus("georss:where");
    312         var geometryNode = this.buildGeometryNode(feature.geometry);
    313         var featureNode = this.createElementNSPlus("entry");
    314         var name;
    315         for(var key in feature.attributes) {
    316             if(this.attributeMap[key]) {
    317                 name = this.attributeMap[key];
    318             } else {
    319                 name = "ol:" + key;
    320             }
    321             featureNode.appendChild(this.createElementNSPlus(name, {
    322                 value: feature.attributes[key]
    323             }));
    324         }
    325 
    326         whereNode.appendChild(geometryNode);
    327         featureNode.appendChild(whereNode);
    328         return featureNode;
    329     },   
    330    
    331     /**
    332      * Method: buildGeometryNode
    333      * builds a GeoRSS node with a given geometry
    334      *
    335      * Parameters:
    336      * geometry - {<OpenLayers.Geometry>}
    337      *
    338      * Returns:
    339      * {DOMElement} A gml node.
    340      */
    341     buildGeometryNode: function(geometry) {
    342         this.gmlParser = new OpenLayers.Format.GMLSF({'xy': this.xy});
    343         return this.gmlParser.buildGeometryNode(geometry);
    344     },
    345    
     314        "link": "link"
     315    },
     316
    346317    CLASS_NAME: "OpenLayers.Format.Atom"
    347318});     
  • sandbox/topp/almanac/lib/OpenLayers/Format/XML.js

    r6956 r6963  
    3131     */
    3232    defaultNamespace: null,
     33   
     34    /**
     35     * Property: readers
     36     * Contains public functions, grouped by namespace prefix, that will
     37     *     be applied when a namespaced node is found matching the function
     38     *     name.  The function will be applied in the scope of this parser
     39     *     with two arguments: the node being read and a context object passed
     40     *     from the parent.
     41     */
     42    readers: {},
     43   
     44    /**
     45     * Property: writers
     46     * As a compliment to the <readers> property, this structure contains public
     47     *     writing functions grouped by namespace alias and named like the
     48     *     node names they produce.
     49     */
     50    writers: {},
    3351
    3452    /**
     
    483501    },
    484502
     503    /**
     504     * Method: readChildNodes
     505     */
     506    readChildNodes: function(node, obj) {
     507        var children = node.childNodes;
     508        var child, group, reader, prefix, local;
     509        for(var i=0; i<children.length; ++i) {
     510            child = children[i];
     511            if(child.nodeType == 1) {
     512                prefix = this.getNamespacePrefix(child.namespaceURI);
     513                local = child.nodeName.split(":").pop();
     514                group = this.readers[prefix];
     515                if(group) {
     516                    reader = group[local];
     517                    if(reader) {
     518                        reader.apply(this, [child, obj]);
     519                    } else {
     520                        if(group["*"]) {
     521                            group["*"].apply(this, [child, obj]);
     522                        }
     523                    }
     524                }
     525            }
     526        }
     527    },
     528
     529    /**
     530     * Method: writeNode
     531     * Shorthand for applying one of the named writers and appending the
     532     *     results to a node.  If a qualified name is not provided for the
     533     *     second argument (and a local name is used instead), the namespace
     534     *     of the parent node will be assumed.
     535     *
     536     * Parameters:
     537     * name - {String} The name of a node to generate.  If a qualified name
     538     *     (e.g. "pre:Name") is used, the namespace prefix is assumed to be
     539     *     in the <writers> group.  If a local name is used (e.g. "Name") then
     540     *     the namespace of the parent is assumed.  If a local name is used
     541     *     and no parent is supplied, then the default namespace is assumed.
     542     * obj - {Object} Structure containing data for the writer.
     543     * parent - {DOMElement} Result will be appended to this node.  If no parent
     544     *     is supplied, the node will not be appended to anything.
     545     *
     546     * Returns:
     547     * {DOMElement} The child node.
     548     */
     549    writeNode: function(name, obj, parent) {
     550        var prefix, local;
     551        var split = name.indexOf(":");
     552        if(split > 0) {
     553            prefix = name.substring(0, split);
     554            local = name.substring(split + 1);
     555        } else {
     556            if(parent) {
     557                prefix = this.getNamespacePrefix(parent.namespaceURI);
     558            } else {
     559                prefix = this.defaultPrefix;
     560            }
     561            local = name;
     562        }
     563        try {
     564            var child = this.writers[prefix][local].apply(this, [obj]);
     565        } catch(err) {
     566            throw "Writing " + prefix + ":" + local + " failed - " + err;
     567        }
     568        if(parent) {
     569            parent.appendChild(child);
     570        }
     571        return child;
     572    },
     573
    485574    CLASS_NAME: "OpenLayers.Format.XML"
    486575
Note: See TracChangeset for help on using the changeset viewer.