docs: function(node) {
          // only accept one geometry per feature - look for highest "order"
          var order = ["MultiPolygon", "Polygon",
                       "MultiLineString", "LineString",
                       "MultiPoint", "Point", "Envelope"];
          // FIXME: In case we parse a feature with no geometry, but boundedBy an Envelope,
          // this code creates a geometry derived from the Envelope. This is not correct.
          var type, nodeList, geometry, parser;
          for(var i=0; i<order.length; ++i) {
              type = order[i];
              nodeList = this.getElementsByTagNameNS(node, this.gmlns, type);
              if(nodeList.length > 0) {
                  // only deal with first geometry of this type
                  parser = this.parseGeometry[type.toLowerCase()];
                  if(parser) {
                      geometry = parser.apply(this, [nodeList[0]]);
                      if (this.internalProjection && this.externalProjection) {
                          geometry.transform(this.externalProjection, 
                                             this.internalProjection); 
                      }                       
                  } else {
                      throw new TypeError("Unsupported geometry type: " + type);
                  }
                  // stop looking for different geometry types
                  break;
              }
          }
  
          var bounds;
          var boxNodes = this.getElementsByTagNameNS(node, this.gmlns, "Box");
          for(i=0; i<boxNodes.length; ++i) {
              var boxNode = boxNodes[i];
              var box = this.parseGeometry["box"].apply(this, [boxNode]);
              var parentNode = boxNode.parentNode;
              var parentName = parentNode.localName ||
                               parentNode.nodeName.split(":").pop();
              if(parentName === "boundedBy") {
                  bounds = box;
              } else {
                  geometry = box.toGeometry();
              }
          }
          
          // construct feature (optionally with attributes)
          var attributes;
          if(this.extractAttributes) {
              attributes = this.parseAttributes(node);
          }
          var feature = new OpenLayers.Feature.Vector(geometry, attributes);
          feature.bounds = bounds;
          
          feature.gml = {
              featureType: node.firstChild.nodeName.split(":")[1],
              featureNS: node.firstChild.namespaceURI,
              featureNSPrefix: node.firstChild.prefix
          };
                  
          // assign fid - this can come from a "fid" or "id" attribute
          var childNode = node.firstChild;
          var fid;
          while(childNode) {
              if(childNode.nodeType == 1) {
                  fid = childNode.getAttribute("fid") ||
                        childNode.getAttribute("id");
                  if(fid) {
                      break;
                  }
              }
              childNode = childNode.nextSibling;
          }
          feature.fid = fid;
          return feature;
      }