Index: tests/Format/test_GeoRSS.html
===================================================================
--- tests/Format/test_GeoRSS.html	(revision 4288)
+++ tests/Format/test_GeoRSS.html	(working copy)
@@ -18,19 +18,34 @@
     function test_Format_GeoRSS_serializeline(t) { 
         t.plan(1);
 
-        if (OpenLayers.Util.getBrowserName() == "msie") {
-            //serialization currently not supported in IE
-            t.ok(true, "GeoRSS serialization not currently supported in IE");
-        } else {
-            var parser = new OpenLayers.Format.GeoRSS();
-            var point = new OpenLayers.Geometry.Point(-111.04, 45.68);  
-            var point2 = new OpenLayers.Geometry.Point(-112.04, 45.68); 
-            var l = new OpenLayers.Geometry.LineString([point, point2]);
-            var f = new OpenLayers.Feature.Vector(l);
-            var data = parser.write([f]);
-            t.eq(data.firstChild.childNodes[2].firstChild.nodeValue, '45.68 -111.04 45.68 -112.04 ', 'GeoRSS serializes a line correctly');
+        var parser = new OpenLayers.Format.GeoRSS();
+        var point = new OpenLayers.Geometry.Point(-111.04, 45.68);  
+        var point2 = new OpenLayers.Geometry.Point(-112.04, 45.68); 
+        var l = new OpenLayers.Geometry.LineString([point, point2]);
+        var f = new OpenLayers.Feature.Vector(l);
+        var data = parser.write([f]);
+        t.eq(data, '<rss xmlns="http://backend.userland.com/rss2"><item><title></title><description></description><georss:line xmlns:georss="http://www.georss.org/georss">45.68 -111.04 45.68 -112.04 </georss:line></item></rss>', 'GeoRSS serializes a line correctly');
+    }
+    function test_Format_GeoRSS_roundtrip(t) {
+        t.plan(input.length);
+        var parser = new OpenLayers.Format.GeoRSS();
+        for(var i=0; i < input.length; i++) {
+            var feed = shell_start+input[i]+shell_end;
+            var data = parser.read(feed);
+            var out = parser.write(data);
+            t.eq(out, output[i], "Output gave expected value");
         }
     }
+             
+    var shell_start = '<feed xmlns="http://www.w3.org/2005/Atom" \n              xmlns:georss="http://www.georss.org/georss">\n              <title>scribble</title>\n              <id>http://featureserver.org/featureserver.cgi/scribble?format=atom</id>\n              <author><name>FeatureServer</name></author>\n';             
+    var shell_end = '</feed>'; 
+    var input = ['<entry><id>http://featureserver.org/featureserver.cgi/scribble/562.atom</id><link href="http://featureserver.org/featureserver.cgi/scribble/562.atom"/><title>Feature 2</title><content type="html">&lt;b&gt;strokeColor&lt;/b&gt;: red&lt;br /&gt;&lt;b&gt;title&lt;/b&gt;: Feature 2&lt;br /&gt;&lt;b&gt;author&lt;/b&gt;: Your Name Here</content><georss:polygon>-5.9765625 -131.484375 -58.0078125 -112.5 -50.2734375 -32.34375 52.3828125 -114.609375 -35.5078125 -167.34375 -57.3046875 -146.953125 -34.1015625 -139.921875 -5.9765625 -131.484375</georss:polygon></entry>',
+    '<entry><id>http://featureserver.org/featureserver.cgi/scribble/796.atom</id><link href="http://featureserver.org/featureserver.cgi/scribble/796.atom"/><title>Feature 2</title><content type="html">&lt;b&gt;strokeColor&lt;/b&gt;: 00ccff&lt;br /&gt;&lt;b&gt;title&lt;/b&gt;: Feature 2&lt;br /&gt;&lt;b&gt;author&lt;/b&gt;: Your Name Here</content><georss:point>75.5859375 15.46875</georss:point></entry>',
+    '<entry><id>http://featureserver.org/featureserver.cgi/scribble/794.atom</id><link href="http://featureserver.org/featureserver.cgi/scribble/794.atom"/><title>Feature 5</title><content type="html">&lt;b&gt;strokeColor&lt;/b&gt;: red&lt;br /&gt;&lt;b&gt;title&lt;/b&gt;: Feature 5&lt;br /&gt;&lt;b&gt;author&lt;/b&gt;: Your Name Here</content><georss:line>28.828125 32.6953125 49.921875 34.8046875 39.375 58.0078125 39.375 58.0078125 40.078125 58.0078125 41.484375 58.0078125 43.59375 58.0078125 45.703125 58.7109375 47.8125 58.7109375 49.21875 58.7109375 51.328125 59.4140625 52.03125 59.4140625 54.140625 60.8203125 56.25 61.5234375 56.25 62.2265625 57.65625 62.2265625 57.65625 62.9296875 58.359375 63.6328125 58.359375 65.0390625 58.359375 65.7421875 59.0625 66.4453125 59.0625 67.1484375 59.0625 68.5546875 59.765625 69.9609375 59.765625 72.0703125 59.765625 73.4765625 59.765625 76.2890625 59.765625 78.3984375 59.765625 79.8046875 59.765625 81.9140625 59.765625 83.3203125 59.0625 84.7265625 59.0625 86.8359375 58.359375 87.5390625 58.359375 88.2421875 56.953125 89.6484375 56.25 91.0546875 54.84375 93.8671875 52.03125 96.6796875 51.328125 98.7890625 50.625 100.1953125 49.21875 102.3046875 48.515625 103.7109375 47.8125 104.4140625 47.109375 105.8203125 46.40625 106.5234375 46.40625 107.9296875 45.703125 109.3359375 45 110.7421875 43.59375 112.8515625 43.59375 114.2578125 43.59375 114.9609375 42.890625 117.0703125 42.890625 117.7734375 42.1875 118.4765625 42.1875 119.1796875 42.1875 119.8828125</georss:line></entry>' 
+    ];
+    var output= ['<rss xmlns="http://backend.userland.com/rss2"><item><title>Feature 2</title><description>&lt;b&gt;strokeColor&lt;/b&gt;: red&lt;br /&gt;&lt;b&gt;title&lt;/b&gt;: Feature 2&lt;br /&gt;&lt;b&gt;author&lt;/b&gt;: Your Name Here</description><link>http://featureserver.org/featureserver.cgi/scribble/562.atom</link><georss:polygon xmlns:georss="http://www.georss.org/georss">-5.9765625 -131.484375 -58.0078125 -112.5 -50.2734375 -32.34375 52.3828125 -114.609375 -35.5078125 -167.34375 -57.3046875 -146.953125 -34.1015625 -139.921875 -5.9765625 -131.484375 </georss:polygon></item></rss>',
+   '<rss xmlns="http://backend.userland.com/rss2"><item><title>Feature 2</title><description>&lt;b&gt;strokeColor&lt;/b&gt;: 00ccff&lt;br /&gt;&lt;b&gt;title&lt;/b&gt;: Feature 2&lt;br /&gt;&lt;b&gt;author&lt;/b&gt;: Your Name Here</description><link>http://featureserver.org/featureserver.cgi/scribble/796.atom</link><georss:point xmlns:georss="http://www.georss.org/georss">75.5859375 15.46875 </georss:point></item></rss>',
+   '<rss xmlns="http://backend.userland.com/rss2"><item><title>Feature 5</title><description>&lt;b&gt;strokeColor&lt;/b&gt;: red&lt;br /&gt;&lt;b&gt;title&lt;/b&gt;: Feature 5&lt;br /&gt;&lt;b&gt;author&lt;/b&gt;: Your Name Here</description><link>http://featureserver.org/featureserver.cgi/scribble/794.atom</link><georss:line xmlns:georss="http://www.georss.org/georss">28.828125 32.6953125 49.921875 34.8046875 39.375 58.0078125 39.375 58.0078125 40.078125 58.0078125 41.484375 58.0078125 43.59375 58.0078125 45.703125 58.7109375 47.8125 58.7109375 49.21875 58.7109375 51.328125 59.4140625 52.03125 59.4140625 54.140625 60.8203125 56.25 61.5234375 56.25 62.2265625 57.65625 62.2265625 57.65625 62.9296875 58.359375 63.6328125 58.359375 65.0390625 58.359375 65.7421875 59.0625 66.4453125 59.0625 67.1484375 59.0625 68.5546875 59.765625 69.9609375 59.765625 72.0703125 59.765625 73.4765625 59.765625 76.2890625 59.765625 78.3984375 59.765625 79.8046875 59.765625 81.9140625 59.765625 83.3203125 59.0625 84.7265625 59.0625 86.8359375 58.359375 87.5390625 58.359375 88.2421875 56.953125 89.6484375 56.25 91.0546875 54.84375 93.8671875 52.03125 96.6796875 51.328125 98.7890625 50.625 100.1953125 49.21875 102.3046875 48.515625 103.7109375 47.8125 104.4140625 47.109375 105.8203125 46.40625 106.5234375 46.40625 107.9296875 45.703125 109.3359375 45 110.7421875 43.59375 112.8515625 43.59375 114.2578125 43.59375 114.9609375 42.890625 117.0703125 42.890625 117.7734375 42.1875 118.4765625 42.1875 119.1796875 42.1875 119.8828125 </georss:line></item></rss>'];
 
     </script> 
 </head> 
Index: lib/OpenLayers/Format/GeoRSS.js
===================================================================
--- lib/OpenLayers/Format/GeoRSS.js	(revision 4288)
+++ lib/OpenLayers/Format/GeoRSS.js	(working copy)
@@ -4,6 +4,7 @@
 
 /**
  * @requires OpenLayers/Format.js
+ * @requires OpenLayers/Format/XML.js
  *
  * Class: OpenLayers.Format.GeoRSS
  * Write-only GeoRSS. Create a new instance with the 
@@ -12,7 +13,7 @@
  * Inherits from:
  *  - <OpenLayers.Format>
  */
-OpenLayers.Format.GeoRSS = OpenLayers.Class(OpenLayers.Format, {
+OpenLayers.Format.GeoRSS = OpenLayers.Class(OpenLayers.Format.XML, {
     
     /**
      * APIProperty: rssns
@@ -42,24 +43,170 @@
      *                    this instance.
      */
     initialize: function(options) {
-        OpenLayers.Format.prototype.initialize.apply(this, [options]);
+        OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
     },
+    
+    /**
+     * Method: createGeometryFromItem
+     * Return an {<OpenLayers.Geometry>} from an XML dom GeoRSS Item.
+     */
+    createGeometryFromItem: function(item) {
+        var point = this.getElementsByTagNameNS(item,
+                                                      this.georssns,
+                                                      "point");
+        var lat = OpenLayers.Util.getNodes(item, 'geo:lat');
+        var lon = OpenLayers.Util.getNodes(item, 'geo:long');
+        
+        var line = this.getElementsByTagNameNS(item,
+                                                this.georssns,
+                                                "line");
+        var polygon = this.getElementsByTagNameNS(item,
+                                                this.georssns,
+                                                "polygon");
+        
+        if (point.length > 0 || (lat.length > 0 && lon.length > 0)) {
+            if (point.length > 0) {
+                var location = point[0].firstChild.nodeValue.trim().split(/\s+/);
+                
+                if (location.length !=2) {
+                    var location = point[0].firstChild.nodeValue.trim().split(/\s*,\s*/);
+                }
+            } else {
+                var location = [parseFloat(lat[0].firstChild.nodeValue), parseFloat(lon[0].firstChild.nodeValue)];
+            }    
+            var geometry = new OpenLayers.Geometry.Point(parseFloat(location[1]),
+                                                     parseFloat(location[0]));
+        } else if (line.length > 0) {
+            var coords = line[0].firstChild.nodeValue.trim().split(/\s+/);
+            var components = []; 
+            for (var i=0; i < coords.length; i+=2) {
+                var point = new OpenLayers.Geometry.Point(parseFloat(coords[i+1]), parseFloat(coords[i]));
+                components.push(point);
+            }
+            geometry = new OpenLayers.Geometry.LineString(components);
+        } else if (polygon.length > 0) { 
+            var coords = polygon[0].firstChild.nodeValue.trim().split(/\s+/);
+            var components = []; 
+            for (var i=0; i < coords.length; i+=2) {
+                var point = new OpenLayers.Geometry.Point(parseFloat(coords[i+1]), parseFloat(coords[i]));
+                components.push(point);
+            }
+            geometry = new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(components)]);
+        }
+        return geometry;                                             
+    },        
 
     /**
+     * Method: createGeometryFromItem
+     * Return an {<OpenLayers.Feature.Vector>} from an XML dom GeoRSS Item.
+     */
+    createFeatureFromItem: function(item) {
+            var geometry = this.createGeometryFromItem(item);
+            /* Provide defaults for title and description */
+            var title = "Untitled";
+            try {
+                title = OpenLayers.Util.getNodes(item, 
+                        "title")[0].firstChild.nodeValue;
+            }
+            catch (e) { title="Untitled"; }
+           
+            /* First try RSS descriptions, then Atom summaries */
+            var descr_nodes = this.getElementsByTagNameNS(item,
+                                                          "*",
+                                                          "description");
+            if (descr_nodes.length == 0) {
+                descr_nodes = this.getElementsByTagNameNS(item,
+                                                          "*",
+                                                          "content");
+            }
+            var description = "No description.";
+            try {
+              description = descr_nodes[0].firstChild.nodeValue;
+            }
+            catch (e) { description="No description."; }
+
+            /* If no link URL is found in the first child node, try the
+               href attribute */
+            var link = null;
+            var edit_link = null;
+            try {
+                var link = OpenLayers.Util.getNodes(item, "link")[0].firstChild.nodeValue;
+            }
+            catch (e) {
+                var link_list = OpenLayers.Util.getNodes(item, "link");
+                for (var i = 0; i < link_list.length; i++) {
+                    var this_link = link_list[i];
+                    link = this_link.getAttribute("href");
+                }    
+            }
+            var id = null;
+            try {
+                id = OpenLayers.Util.getNodes(item, "id")[0].firstChild.nodeValue;
+            } catch (e) {
+            }
+            
+            var data = {
+                "title": title,
+                "description": description,
+                "link": link
+            };
+            var feature = new OpenLayers.Feature.Vector(geometry, data);
+            feature.fid = id;
+            return feature;
+    },        
+    
+    /**
+     * APIMethod: read
+     * Return a list of features from a GeoRSS doc
+     
+     * Parameters:
+     * data - {Element} 
+     *
+     * Returns:
+     * An Array of <OpenLayers.Feature.Vector>s
+     */
+    read: function(doc) {
+        if (typeof doc == "string") { 
+            doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]);
+        }
+
+        /* Try RSS items first, then Atom entries */
+        var itemlist = null;
+        itemlist = this.getElementsByTagNameNS(doc, '*', 'item');
+        if (itemlist.length == 0) {
+            itemlist = this.getElementsByTagNameNS(doc, '*', 'entry');
+        }
+        
+        var features = [];
+        for(var i=0; i<itemlist.length; i++) {
+            // this is horrendous - please change this
+            var item = itemlist[i];
+            features.push(this.createFeatureFromItem(item));
+        }
+        return features;
+    },
+    
+
+    /**
      * APIMethod: write
      * Accept Feature Collection, and return a string. 
      * 
      * Parameters: 
      * features - Array({<OpenLayers.Feature.Vector>}) List of features to serialize into a string.
      */
-     write: function(features) {
-        var featureCollection = document.createElementNS(this.rssns, "rss");
-        for (var i=0; i < features.length; i++) {
-            featureCollection.appendChild(this.createFeatureXML(features[i]));
+    write: function(features) {
+        var georss;
+        if(features instanceof Array) {
+            georss = this.createElementNS(this.rssns, "rss");
+            for(var i=0; i < features.length; i++) {
+                georss.appendChild(this.createFeatureXML(features[i]));
+            }
+        } else {
+            georss = this.createFeatureXML(features);
         }
-        return featureCollection;
+        return OpenLayers.Format.XML.prototype.write.apply(this, [georss]);
      },
-    
+
     /**
      * Method: createFeatureXML
      * Accept an <OpenLayers.Feature.Vector>, and build a geometry for it.
@@ -72,20 +219,26 @@
      */
     createFeatureXML: function(feature) {
         var geometryNode = this.buildGeometryNode(feature.geometry);
-        var featureNode = document.createElementNS(this.rssns, "item");
-        var titleNode = document.createElementNS(this.rssns, "title");
-        titleNode.appendChild(document.createTextNode(feature.attributes.title ? feature.attributes.title : ""));
-        var descNode = document.createElementNS(this.rssns, "description");
-        descNode.appendChild(document.createTextNode(feature.attributes.description ? feature.attributes.description : ""));
+        var featureNode = this.createElementNS(this.rssns, "item");
+        var titleNode = this.createElementNS(this.rssns, "title");
+        titleNode.appendChild(this.createTextNode(feature.attributes.title ? feature.attributes.title : ""));
+        var descNode = this.createElementNS(this.rssns, "description");
+        descNode.appendChild(this.createTextNode(feature.attributes.description ? feature.attributes.description : ""));
         featureNode.appendChild(titleNode);
         featureNode.appendChild(descNode);
+        if (feature.attributes.link) {
+            var linkNode = this.createElementNS(this.rssns, "link");
+            linkNode.appendChild(this.createTextNode(feature.attributes.link));
+            featureNode.appendChild(linkNode);
+        }    
         for(var attr in feature.attributes) {
-            var attrText = document.createTextNode(feature.attributes[attr]); 
+            if (attr == "link" || attr == "title" || attr == "description") { continue; } 
+            var attrText = this.createTextNode(feature.attributes[attr]); 
             var nodename = attr;
             if (attr.search(":") != -1) {
                 nodename = attr.split(":")[1];
             }    
-            var attrContainer = document.createElementNS(this.featureNS, "feature:"+nodename);
+            var attrContainer = this.createElementNS(this.featureNS, "feature:"+nodename);
             attrContainer.appendChild(attrText);
             featureNode.appendChild(attrContainer);
         }    
@@ -104,22 +257,22 @@
         var gml = "";
         // match MultiPolygon or Polygon
         if (geometry.CLASS_NAME == "OpenLayers.Geometry.Polygon") {
-                gml = document.createElementNS(this.georssns, 'georss:polygon');
-                
-                gml.appendChild(this.buildCoordinatesNode(geometry.components[0]));
-            }
+            gml = this.createElementNS(this.georssns, 'georss:polygon');
+            
+            gml.appendChild(this.buildCoordinatesNode(geometry.components[0]));
+        }
         // match MultiLineString or LineString
         else if (geometry.CLASS_NAME == "OpenLayers.Geometry.LineString") {
-                     gml = document.createElementNS(this.georssns, 'georss:line');
-                     
-                     gml.appendChild(this.buildCoordinatesNode(geometry));
-                 }
+            gml = this.createElementNS(this.georssns, 'georss:line');
+            
+            gml.appendChild(this.buildCoordinatesNode(geometry));
+        }
         // match MultiPoint or Point
         else if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
-                gml = document.createElementNS(this.georssns, 'georss:point');
-                gml.appendChild(this.buildCoordinatesNode(geometry));
+            gml = this.createElementNS(this.georssns, 'georss:point');
+            gml.appendChild(this.buildCoordinatesNode(geometry));
         } else {    
-          alert("Couldn't parse " + geometry.CLASS_NAME);
+            alert("Couldn't parse " + geometry.CLASS_NAME);
         }  
         return gml;         
     },
@@ -145,7 +298,7 @@
         } else {
            path += geometry.y + " " + geometry.x + " ";
         }
-        return document.createTextNode(path);
+        return this.createTextNode(path);
     },
 
     CLASS_NAME: "OpenLayers.Format.GeoRSS" 
