docs: function(doc) {
          if (typeof doc == "string") { 
              doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]);
          }
  
          var nodes = this.getNodes(doc);
          var ways = this.getWays(doc);
          
          // Geoms will contain at least ways.length entries.
          var feat_list = new Array(ways.length);
          
          for (var i = 0; i < ways.length; i++) {
              // We know the minimal of this one ahead of time. (Could be -1
              // due to areas/polygons)
              var point_list = new Array(ways[i].nodes.length);
              
              var poly = this.isWayArea(ways[i]) ? 1 : 0; 
              for (var j = 0; j < ways[i].nodes.length; j++) {
                 var node = nodes[ways[i].nodes[j]];
                 
                 var point = new OpenLayers.Geometry.Point(node.lon, node.lat);
                 
                 // Since OSM is topological, we stash the node ID internally. 
                 point.osm_id = parseInt(ways[i].nodes[j]);
                 point_list[j] = point;
                 
                 // We don't display nodes if they're used inside other 
                 // elements.
                 node.used = true; 
              }
              var geometry = null;
              if (poly) { 
                  geometry = new OpenLayers.Geometry.Polygon(
                      new OpenLayers.Geometry.LinearRing(point_list));
              } else {    
                  geometry = new OpenLayers.Geometry.LineString(point_list);
              }
              if (this.internalProjection && this.externalProjection) {
                  geometry.transform(this.externalProjection, 
                      this.internalProjection);
              }        
              var feat = new OpenLayers.Feature.Vector(geometry,
                  ways[i].tags);
              feat.osm_id = parseInt(ways[i].id);
              feat.fid = "way." + feat.osm_id;
              feat_list[i] = feat;
          } 
          for (var node_id in nodes) {
              var node = nodes[node_id];
              if (!node.used || this.checkTags) {
                  var tags = null;
                  
                  if (this.checkTags) {
                      var result = this.getTags(node.node, true);
                      if (node.used && !result[1]) {
                          continue;
                      }
                      tags = result[0];
                  } else { 
                      tags = this.getTags(node.node);
                  }    
                  
                  var feat = new OpenLayers.Feature.Vector(
                      new OpenLayers.Geometry.Point(node['lon'], node['lat']),
                      tags);
                  if (this.internalProjection && this.externalProjection) {
                      feat.geometry.transform(this.externalProjection, 
                          this.internalProjection);
                  }        
                  feat.osm_id = parseInt(node_id); 
                  feat.fid = "node." + feat.osm_id;
                  feat_list.push(feat);
              }   
              // Memory cleanup
              node.node = null;
          }        
          return feat_list;
      }