diff --git libcloud/common/aws.py libcloud/common/aws.py
index 20b7269..206caef 100644
--- libcloud/common/aws.py
+++ libcloud/common/aws.py
@@ -13,18 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from xml.etree import ElementTree as ET
+from libcloud.common.base import XmlResponse
 
-from libcloud.common.base import Response
-from libcloud.common.types import MalformedResponseError
-
-class AWSBaseResponse(Response):
-    def parse_body(self):
-        if not self.body:
-            return None
-
-        try:
-          body = ET.XML(self.body)
-        except:
-          raise MalformedResponseError("Failed to parse XML", body=self.body)
-        return body
+class AWSBaseResponse(XmlResponse): pass
diff --git libcloud/common/base.py libcloud/common/base.py
index 70c577e..e6a4ff0 100644
--- libcloud/common/base.py
+++ libcloud/common/base.py
@@ -18,11 +18,17 @@ import urllib
 import StringIO
 import ssl
 
+from xml.etree import ElementTree as ET
 from pipes import quote as pquote
 import urlparse
 
+try:
+    import simplejson as json
+except:
+    import json
+
 import libcloud
-from libcloud.common.types import LibcloudError
+from libcloud.common.types import LibcloudError, MalformedResponseError
 
 from libcloud.httplib_ssl import LibcloudHTTPSConnection
 from httplib import HTTPConnection as LibcloudHTTPConnection
@@ -39,9 +45,10 @@ class Response(object):
     headers = {}
     error = None
     connection = None
+    parse_zero_length_body = False
 
     def __init__(self, response, connection):
-        self.body = response.read()
+        self.body = response.read().strip()
         self.status = response.status
         self.headers = dict(response.getheaders())
         self.error = response.reason
@@ -83,6 +90,46 @@ class Response(object):
         """
         return self.status == httplib.OK or self.status == httplib.CREATED
 
+
+class JsonResponse(Response):
+    """
+    A Base JSON Response class to derive from.
+    """
+    def parse_body(self):
+        if len(self.body) == 0 and not self.parse_zero_length_body:
+            return self.body
+
+        try:
+            body = json.loads(self.body)
+        except:
+            raise MalformedResponseError(
+                "Failed to parse JSON",
+                body=self.body,
+                driver=self.connection.driver)
+        return body
+
+    parse_error = parse_body
+
+
+class XmlResponse(Response):
+    """
+    A Base XML Response class to derive from.
+    """
+    def parse_body(self):
+        if len(self.body) == 0 and not self.parse_zero_length_body:
+            return self.body
+
+        try:
+          body = ET.XML(self.body)
+        except:
+          raise MalformedResponseError("Failed to parse XML",
+                                       body=self.body,
+                                       driver=self.connection.driver)
+        return body
+
+    parse_error = parse_body
+
+
 class RawResponse(Response):
 
     def __init__(self, connection):
diff --git libcloud/common/cloudstack.py libcloud/common/cloudstack.py
index f3690dd..c732b68 100644
--- libcloud/common/cloudstack.py
+++ libcloud/common/cloudstack.py
@@ -19,26 +19,10 @@ import hmac
 import time
 import urllib
 
-try:
-    import simplejson as json
-except:
-    import json
-
-from libcloud.common.base import ConnectionUserAndKey, Response
+from libcloud.common.base import ConnectionUserAndKey, JsonResponse
 from libcloud.common.types import MalformedResponseError
 
-class CloudStackResponse(Response):
-    def parse_body(self):
-        try:
-            body = json.loads(self.body)
-        except:
-            raise MalformedResponseError(
-                "Failed to parse JSON",
-                body=self.body,
-                driver=self.connection.driver)
-        return body
-
-    parse_error = parse_body
+class CloudStackResponse(JsonResponse): pass
 
 class CloudStackConnection(ConnectionUserAndKey):
     responseCls = CloudStackResponse
diff --git libcloud/common/gogrid.py libcloud/common/gogrid.py
index 5cc6fc7..38c07e5 100644
--- libcloud/common/gogrid.py
+++ libcloud/common/gogrid.py
@@ -16,14 +16,9 @@
 import hashlib
 import time
 
-try:
-    import simplejson as json
-except ImportError:
-    import json
-
 from libcloud.common.types import InvalidCredsError, LibcloudError
 from libcloud.common.types import MalformedResponseError
-from libcloud.common.base import ConnectionUserAndKey, Response
+from libcloud.common.base import ConnectionUserAndKey, JsonResponse
 from libcloud.compute.base import NodeLocation
 
 HOST = 'api.gogrid.com'
@@ -36,7 +31,7 @@ __all__ = ["GoGridResponse",
         "BaseGoGridDriver",
 ]
 
-class GoGridResponse(Response):
+class GoGridResponse(JsonResponse):
 
     def __init__(self, *args, **kwargs):
        self.driver = BaseGoGridDriver
@@ -50,19 +45,14 @@ class GoGridResponse(Response):
         if not self.body:
             return None
         try:
-            return json.loads(self.body)['status'] == 'success'
+            return self.parse_body()['status'] == 'success'
         except ValueError:
             raise MalformedResponseError('Malformed reply',
                     body=self.body, driver=self.driver)
 
-    def parse_body(self):
-        if not self.body:
-            return None
-        return json.loads(self.body)
-
     def parse_error(self):
         try:
-            return json.loads(self.body)["list"][0]['message']
+            return self.parse_body()["list"][0]["message"]
         except (ValueError, KeyError):
             return None
 
diff --git libcloud/common/linode.py libcloud/common/linode.py
index c4151fa..eeb9eae 100644
--- libcloud/common/linode.py
+++ libcloud/common/linode.py
@@ -13,13 +13,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-try:
-    import simplejson as json
-except ImportError:
-    import json
-
-from libcloud.common.base import ConnectionKey, Response
-from libcloud.common.types import InvalidCredsError, MalformedResponseError
+from libcloud.common.base import ConnectionKey, JsonResponse
+from libcloud.common.types import InvalidCredsError
 
 __all__ = [
     'API_HOST',
@@ -65,7 +60,7 @@ class LinodeException(Exception):
         return "<LinodeException code %u '%s'>" % (self.code, self.message)
 
 
-class LinodeResponse(Response):
+class LinodeResponse(JsonResponse):
     """Linode API response
 
     Wraps the HTTP response returned by the Linode API, which should be JSON in
@@ -106,10 +101,7 @@ class LinodeResponse(Response):
         None and errorarray will indicate an invalid JSON exception.
 
         @return: C{list} of objects and C{list} of errors"""
-        try:
-            js = json.loads(self.body)
-        except:
-            raise MalformedResponseError("Failed to parse JSON", body=self.body)
+        js = super(LinodeResponse, self).parse_body()
 
         try:
             if isinstance(js, dict):
diff --git libcloud/compute/drivers/bluebox.py libcloud/compute/drivers/bluebox.py
index f64d3a2..21b7fcd 100644
--- libcloud/compute/drivers/bluebox.py
+++ libcloud/compute/drivers/bluebox.py
@@ -26,14 +26,10 @@ import copy
 import urllib
 import base64
 
-try:
-    import simplejson as json
-except ImportError:
-    import json
-
-from libcloud.common.base import Response, ConnectionUserAndKey
+from libcloud.common.base import JsonResponse, ConnectionUserAndKey
 from libcloud.compute.providers import Provider
 from libcloud.compute.types import NodeState, InvalidCredsError
+from libcloud.common.types import MalformedResponseError
 from libcloud.compute.base import Node, NodeDriver
 from libcloud.compute.base import NodeSize, NodeImage, NodeLocation
 from libcloud.compute.base import NodeAuthPassword, NodeAuthSSHKey
@@ -83,14 +79,7 @@ NODE_STATE_MAP = { 'queued': NodeState.PENDING,
                    'error': NodeState.TERMINATED,
                    'unknown': NodeState.UNKNOWN }
 
-class BlueboxResponse(Response):
-    def parse_body(self):
-        try:
-            js = json.loads(self.body)
-            return js
-        except ValueError:
-            return self.body
-
+class BlueboxResponse(JsonResponse):
     def parse_error(self):
         if int(self.status) == 401:
             if not self.body:
diff --git libcloud/compute/drivers/brightbox.py libcloud/compute/drivers/brightbox.py
index 08c7545..bbc300b 100644
--- libcloud/compute/drivers/brightbox.py
+++ libcloud/compute/drivers/brightbox.py
@@ -18,7 +18,7 @@ Brightbox Driver
 import httplib
 import base64
 
-from libcloud.common.base import ConnectionUserAndKey, Response
+from libcloud.common.base import ConnectionUserAndKey, JsonResponse
 from libcloud.compute.types import Provider, NodeState, InvalidCredsError
 from libcloud.compute.base import NodeDriver
 from libcloud.compute.base import Node, NodeImage, NodeSize, NodeLocation
@@ -31,18 +31,18 @@ except ImportError:
 API_VERSION = '1.0'
 
 
-class BrightboxResponse(Response):
+class BrightboxResponse(JsonResponse):
     def success(self):
         return self.status >= 200 and self.status < 400
 
     def parse_body(self):
-        if self.headers['content-type'].split('; ')[0] == 'application/json' and len(self.body) > 0:
-            return json.loads(self.body)
+        if self.headers['content-type'].split('; ')[0] == 'application/json':
+            return super(BrightboxResponse, self).parse_body()
         else:
             return self.body
 
     def parse_error(self):
-        return json.loads(self.body)['error']
+        return super(BrightboxResponse, self).parse_body()['error']
 
 
 class BrightboxConnection(ConnectionUserAndKey):
diff --git libcloud/compute/drivers/dreamhost.py libcloud/compute/drivers/dreamhost.py
index 51b982c..f1a73b4 100644
--- libcloud/compute/drivers/dreamhost.py
+++ libcloud/compute/drivers/dreamhost.py
@@ -16,14 +16,9 @@
 DreamHost Driver
 """
 
-try:
-    import simplejson as json
-except ImportError:
-    import json
-
 import copy
 
-from libcloud.common.base import ConnectionKey, Response
+from libcloud.common.base import ConnectionKey, JsonResponse
 from libcloud.common.types import InvalidCredsError
 from libcloud.compute.base import Node, NodeDriver, NodeSize
 from libcloud.compute.base import NodeImage
@@ -81,13 +76,13 @@ class DreamhostAPIException(Exception):
         return "<DreamhostException '%s'>" % (self.args[0])
 
 
-class DreamhostResponse(Response):
+class DreamhostResponse(JsonResponse):
     """
     Response class for DreamHost PS
     """
 
     def parse_body(self):
-        resp = json.loads(self.body)
+        resp = super(DreamhostResponse, self).parse_body()
         if resp['result'] != 'success':
             raise Exception(self._api_parse_error(resp))
         return resp['data']
diff --git libcloud/compute/drivers/elasticstack.py libcloud/compute/drivers/elasticstack.py
index 07a6cd9..f48a16b 100644
--- libcloud/compute/drivers/elasticstack.py
+++ libcloud/compute/drivers/elasticstack.py
@@ -28,8 +28,8 @@ try:
 except ImportError:
     import json
 
-from libcloud.common.base import ConnectionUserAndKey, Response
-from libcloud.common.types import InvalidCredsError, MalformedResponseError
+from libcloud.common.base import ConnectionUserAndKey, JsonResponse
+from libcloud.common.types import InvalidCredsError
 from libcloud.compute.types import NodeState
 from libcloud.compute.base import NodeDriver, NodeSize, Node
 from libcloud.compute.base import NodeImage
@@ -111,26 +111,13 @@ class ElasticStackException(Exception):
         return "<ElasticStackException '%s'>" % (self.args[0])
 
 
-class ElasticStackResponse(Response):
+class ElasticStackResponse(JsonResponse):
     def success(self):
         if self.status == 401:
             raise InvalidCredsError()
 
         return self.status >= 200 and self.status <= 299
 
-    def parse_body(self):
-        if not self.body:
-            return self.body
-
-        try:
-            data = json.loads(self.body)
-        except:
-            raise MalformedResponseError('Failed to parse JSON',
-                                         body=self.body,
-                                         driver=ElasticStackBaseNodeDriver)
-
-        return data
-
     def parse_error(self):
         error_header = self.headers.get('x-elastic-error', '')
         return 'X-Elastic-Error: %s (%s)' % (error_header, self.body.strip())
diff --git libcloud/compute/drivers/ibm_sbc.py libcloud/compute/drivers/ibm_sbc.py
index 99e309d..df9a907 100644
--- libcloud/compute/drivers/ibm_sbc.py
+++ libcloud/compute/drivers/ibm_sbc.py
@@ -17,25 +17,18 @@ Driver for the IBM Developer Cloud.
 """
 import base64, urllib
 
-from libcloud.common.base import Response, ConnectionUserAndKey
+from libcloud.common.base import XmlResponse, ConnectionUserAndKey
 from libcloud.common.types import InvalidCredsError
 from libcloud.compute.types import NodeState, Provider
 from libcloud.compute.base import NodeDriver, Node, NodeImage, NodeSize, NodeLocation, NodeAuthSSHKey
 
-from xml.etree import ElementTree as ET
-
 HOST = 'www-147.ibm.com'
 REST_BASE = '/computecloud/enterprise/api/rest/20100331'
 
-class IBMResponse(Response):
+class IBMResponse(XmlResponse):
     def success(self):
         return int(self.status) == 200
 
-    def parse_body(self):
-        if not self.body:
-            return None
-        return ET.XML(self.body)
-
     def parse_error(self):
         if int(self.status) == 401:
             if not self.body:
diff --git libcloud/compute/drivers/opennebula.py libcloud/compute/drivers/opennebula.py
index 7263f8a..d3b3c38 100644
--- libcloud/compute/drivers/opennebula.py
+++ libcloud/compute/drivers/opennebula.py
@@ -30,11 +30,10 @@ import hashlib
 import httplib
 
 from libcloud.compute.base import NodeState, NodeDriver, Node, NodeLocation
-from libcloud.common.base import ConnectionUserAndKey, Response
+from libcloud.common.base import ConnectionUserAndKey, XmlResponse
 from libcloud.compute.base import NodeImage, NodeSize
 from libcloud.common.types import InvalidCredsError
 from libcloud.compute.providers import Provider
-from libcloud.common.base import Response
 
 API_HOST = ''
 API_PORT = (4567, 443)
@@ -42,7 +41,7 @@ API_SECURE = True
 DEFAULT_API_VERSION = '3.0'
 
 
-class OpenNebulaResponse(Response):
+class OpenNebulaResponse(XmlResponse):
     """
     Response class for the OpenNebula driver.
     """
@@ -51,11 +50,6 @@ class OpenNebulaResponse(Response):
         i = int(self.status)
         return i >= 200 and i <= 299
 
-    def parse_body(self):
-        if not self.body:
-            return None
-        return ET.XML(self.body)
-
     def parse_error(self):
         if int(self.status) == httplib.UNAUTHORIZED:
             raise InvalidCredsError(self.body)
diff --git libcloud/compute/drivers/opsource.py libcloud/compute/drivers/opsource.py
index 00dc83a..71d3e77 100644
--- libcloud/compute/drivers/opsource.py
+++ libcloud/compute/drivers/opsource.py
@@ -22,8 +22,7 @@ import httplib
 from libcloud.compute.base import NodeDriver, Node, NodeAuthPassword
 from libcloud.compute.base import NodeSize, NodeImage, NodeLocation
 from libcloud.common.types import LibcloudError, InvalidCredsError
-from libcloud.common.base import ConnectionUserAndKey, Response
-from libcloud.common.types import MalformedResponseError
+from libcloud.common.base import ConnectionUserAndKey, XmlResponse
 from libcloud.utils import fixxpath, findtext, findall
 from libcloud.compute.types import NodeState, Provider
 
@@ -88,18 +87,7 @@ IPPLAN_NS = NAMESPACE_BASE + "/ipplan"
 WHITELABEL_NS = NAMESPACE_BASE + "/whitelabel"
 
 
-class OpsourceResponse(Response):
-
-    def parse_body(self):
-        try:
-            body = ET.XML(self.body)
-        except:
-            raise MalformedResponseError(
-                'Failed to parse XML',
-                body=self.body,
-                driver=OpsourceNodeDriver)
-
-        return body
+class OpsourceResponse(XmlResponse):
 
     def parse_error(self):
         if self.status == httplib.UNAUTHORIZED:
@@ -107,13 +95,7 @@ class OpsourceResponse(Response):
         elif self.status == httplib.FORBIDDEN:
             raise InvalidCredsError(self.body)
 
-        try:
-            body = ET.XML(self.body)
-        except:
-            raise MalformedResponseError(
-                'Failed to parse XML',
-                body=self.body,
-                driver=OpsourceNodeDriver)
+        body = self.parse_body()
 
         if self.status == httplib.BAD_REQUEST:
             code = findtext(body, 'resultCode', SERVER_NS)
diff --git libcloud/compute/drivers/rimuhosting.py libcloud/compute/drivers/rimuhosting.py
index 82c0640..ecf1766 100644
--- libcloud/compute/drivers/rimuhosting.py
+++ libcloud/compute/drivers/rimuhosting.py
@@ -20,7 +20,7 @@ try:
 except ImportError:
     import json
 
-from libcloud.common.base import ConnectionKey, Response
+from libcloud.common.base import ConnectionKey, JsonResponse
 from libcloud.common.types import InvalidCredsError
 from libcloud.compute.types import Provider, NodeState
 from libcloud.compute.base import NodeDriver, NodeSize, Node, NodeLocation
@@ -40,7 +40,7 @@ class RimuHostingException(Exception):
     def __repr__(self):
         return "<RimuHostingException '%s'>" % (self.args[0])
 
-class RimuHostingResponse(Response):
+class RimuHostingResponse(JsonResponse):
     def __init__(self, response, connection):
         self.body = response.read()
         self.status = response.status
@@ -55,17 +55,15 @@ class RimuHostingResponse(Response):
         if self.status == 403:
             raise InvalidCredsError()
         return True
+
     def parse_body(self):
         try:
-            js = json.loads(self.body)
+            js = super(RimuHostingResponse, self).parse_body()
             if js[js.keys()[0]]['response_type'] == "ERROR":
                 raise RimuHostingException(
                     js[js.keys()[0]]['human_readable_message']
                 )
             return js[js.keys()[0]]
-        except ValueError:
-            raise RimuHostingException('Could not parse body: %s'
-                                       % (self.body))
         except KeyError:
             raise RimuHostingException('Could not parse body: %s'
                                        % (self.body))
diff --git libcloud/compute/drivers/slicehost.py libcloud/compute/drivers/slicehost.py
index 49c15ff..d23ae5e 100644
--- libcloud/compute/drivers/slicehost.py
+++ libcloud/compute/drivers/slicehost.py
@@ -21,40 +21,17 @@ import socket
 from xml.etree import ElementTree as ET
 from xml.parsers.expat import ExpatError
 
-from libcloud.common.base import ConnectionKey, Response
-from libcloud.compute.types import (
-    NodeState, Provider, InvalidCredsError, MalformedResponseError)
+from libcloud.common.base import ConnectionKey, XmlResponse
+from libcloud.compute.types import NodeState, Provider, InvalidCredsError
 from libcloud.compute.base import NodeSize, NodeDriver, NodeImage, NodeLocation
 from libcloud.compute.base import Node, is_private_subnet
 
-class SlicehostResponse(Response):
-
-    def parse_body(self):
-        # length of 1 can't be valid XML, but on destroy node,
-        # slicehost returns a 1 byte response with a "Content-Type:
-        # application/xml" header. booya.
-        if not self.body or len(self.body) <= 1:
-            return None
-        try:
-            body = ET.XML(self.body)
-        except:
-            raise MalformedResponseError(
-                "Failed to parse XML",
-                body=self.body,
-                driver=SlicehostNodeDriver)
-        return body
-
+class SlicehostResponse(XmlResponse):
     def parse_error(self):
         if self.status == 401:
             raise InvalidCredsError(self.body)
 
-        try:
-            body = ET.XML(self.body)
-        except:
-            raise MalformedResponseError(
-                "Failed to parse XML",
-                body=self.body,
-                driver=SlicehostNodeDriver)
+        body = super(SlicehostResponse, self).parse_body()
         try:
             return "; ".join([ err.text
                                for err in
diff --git libcloud/compute/drivers/vcloud.py libcloud/compute/drivers/vcloud.py
index eaa880b..47eb848 100644
--- libcloud/compute/drivers/vcloud.py
+++ libcloud/compute/drivers/vcloud.py
@@ -23,7 +23,7 @@ from urlparse import urlparse
 from xml.etree import ElementTree as ET
 from xml.parsers.expat import ExpatError
 
-from libcloud.common.base import Response, ConnectionUserAndKey
+from libcloud.common.base import XmlResponse, ConnectionUserAndKey
 from libcloud.common.types import InvalidCredsError
 from libcloud.compute.providers import Provider
 from libcloud.compute.types import NodeState
@@ -198,18 +198,7 @@ class InstantiateVAppXML(object):
             {'href': self.net_href}
         )
 
-class VCloudResponse(Response):
-
-    def parse_body(self):
-        if not self.body:
-            return None
-        try:
-            return ET.XML(self.body)
-        except ExpatError, e:
-            raise Exception("%s: %s" % (e, self.parse_error()))
-
-    def parse_error(self):
-        return self.error
+class VCloudResponse(XmlResponse):
 
     def success(self):
         return self.status in (httplib.OK, httplib.CREATED,
diff --git libcloud/compute/drivers/voxel.py libcloud/compute/drivers/voxel.py
index 42499f8..390d818 100644
--- libcloud/compute/drivers/voxel.py
+++ libcloud/compute/drivers/voxel.py
@@ -19,9 +19,7 @@ Voxel VoxCloud driver
 import datetime
 import hashlib
 
-from xml.etree import ElementTree as ET
-
-from libcloud.common.base import Response, ConnectionUserAndKey
+from libcloud.common.base import XmlResponse, ConnectionUserAndKey
 from libcloud.common.types import InvalidCredsError
 from libcloud.compute.providers import Provider
 from libcloud.compute.types import NodeState
@@ -30,7 +28,7 @@ from libcloud.compute.base import NodeSize, NodeImage, NodeLocation
 
 VOXEL_API_HOST = "api.voxel.net"
 
-class VoxelResponse(Response):
+class VoxelResponse(XmlResponse):
 
     def __init__(self, response, connection):
         self.parsed = None
@@ -41,7 +39,7 @@ class VoxelResponse(Response):
         if not self.body:
             return None
         if not self.parsed:
-            self.parsed = ET.XML(self.body)
+            self.parsed = super(VoxelResponse, self).parse_body()
         return self.parsed
 
     def parse_error(self):
@@ -49,7 +47,7 @@ class VoxelResponse(Response):
         if not self.body:
             return None
         if not self.parsed:
-            self.parsed = ET.XML(self.body)
+            self.parsed = super(VoxelResponse, self).parse_body()
         for err in self.parsed.findall('err'):
             code = err.get('code')
             err_list.append("(%s) %s" % (code, err.get('msg')))
@@ -64,7 +62,7 @@ class VoxelResponse(Response):
 
     def success(self):
         if not self.parsed:
-            self.parsed = ET.XML(self.body)
+            self.parsed = super(VoxelResponse, self).parse_body()
         stat = self.parsed.get('stat')
         if stat != "ok":
             return False
diff --git libcloud/compute/drivers/vpsnet.py libcloud/compute/drivers/vpsnet.py
index 181a62a..c223dbb 100644
--- libcloud/compute/drivers/vpsnet.py
+++ libcloud/compute/drivers/vpsnet.py
@@ -22,8 +22,8 @@ try:
 except ImportError:
     import json
 
-from libcloud.common.base import ConnectionUserAndKey, Response
-from libcloud.common.types import InvalidCredsError
+from libcloud.common.base import ConnectionUserAndKey, JsonResponse
+from libcloud.common.types import InvalidCredsError, MalformedResponseError
 from libcloud.compute.providers import Provider
 from libcloud.compute.types import NodeState
 from libcloud.compute.base import Node, NodeDriver
@@ -37,13 +37,12 @@ DISK_PER_NODE = 10
 BANDWIDTH_PER_NODE = 250
 
 
-class VPSNetResponse(Response):
+class VPSNetResponse(JsonResponse):
 
     def parse_body(self):
         try:
-            js = json.loads(self.body)
-            return js
-        except ValueError:
+            return super(VPSNetResponse, self).parse_body()
+        except MalformedResponseError:
             return self.body
 
     def success(self):
@@ -54,8 +53,8 @@ class VPSNetResponse(Response):
 
     def parse_error(self):
         try:
-            errors = json.loads(self.body)['errors'][0]
-        except ValueError:
+            errors = super(VPSNetResponse, self).parse_body()['errors'][0]
+        except MalformedResponseError:
             return self.body
         else:
             return "\n".join(errors)
diff --git libcloud/dns/drivers/zerigo.py libcloud/dns/drivers/zerigo.py
index 7ec09b2..15dc864 100644
--- libcloud/dns/drivers/zerigo.py
+++ libcloud/dns/drivers/zerigo.py
@@ -26,7 +26,7 @@ from xml.etree import ElementTree as ET
 
 from libcloud.utils import fixxpath, findtext, findattr, findall
 from libcloud.utils import merge_valid_keys, get_new_obj
-from libcloud.common.base import Response, ConnectionUserAndKey
+from libcloud.common.base import XmlResponse, ConnectionUserAndKey
 from libcloud.common.types import InvalidCredsError, LibcloudError
 from libcloud.common.types import MalformedResponseError, LazyList
 from libcloud.dns.types import Provider, RecordType
@@ -72,17 +72,7 @@ class ZerigoError(LibcloudError):
                                                            len(self.errors)))
 
 
-class ZerigoDNSResponse(Response):
-    def parse_body(self):
-        if not self.body or (self.body and not self.body.strip()):
-            return None
-
-        try:
-            body = ET.XML(self.body)
-        except:
-            raise MalformedResponseError('Failed to parse XML', body=self.body)
-        return body
-
+class ZerigoDNSResponse(XmlResponse):
     def success(self):
         return self.status in [httplib.OK, httplib.CREATED, httplib.ACCEPTED]
 
diff --git libcloud/loadbalancer/drivers/rackspace.py libcloud/loadbalancer/drivers/rackspace.py
index e26138c..5900e08 100644
--- libcloud/loadbalancer/drivers/rackspace.py
+++ libcloud/loadbalancer/drivers/rackspace.py
@@ -21,7 +21,7 @@ except ImportError:
     import json
 
 from libcloud.utils import reverse_dict
-from libcloud.common.base import Response
+from libcloud.common.base import JsonResponse
 from libcloud.loadbalancer.base import LoadBalancer, Member, Driver, Algorithm
 from libcloud.loadbalancer.base import DEFAULT_ALGORITHM
 from libcloud.loadbalancer.types import State
@@ -29,16 +29,15 @@ from libcloud.common.openstack import OpenStackBaseConnection
 from libcloud.common.rackspace import (
         AUTH_URL_US, AUTH_URL_UK)
 
-class RackspaceResponse(Response):
-
-    def success(self):
-        return 200 <= int(self.status) <= 299
+class RackspaceResponse(JsonResponse):
 
     def parse_body(self):
         if not self.body:
             return None
-        else:
-            return json.loads(self.body)
+        return super(RackspaceResponse, self).parse_body()
+
+    def success(self):
+        return 200 <= int(self.status) <= 299
 
 
 class RackspaceConnection(OpenStackBaseConnection):
diff --git libcloud/storage/drivers/atmos.py libcloud/storage/drivers/atmos.py
index 2d9a3c7..cf17b41 100644
--- libcloud/storage/drivers/atmos.py
+++ libcloud/storage/drivers/atmos.py
@@ -24,7 +24,7 @@ import urlparse
 from xml.etree import ElementTree
 
 from libcloud import utils
-from libcloud.common.base import ConnectionUserAndKey, Response
+from libcloud.common.base import ConnectionUserAndKey, XmlResponse
 from libcloud.common.types import LazyList
 
 from libcloud.storage.base import Object, Container, StorageDriver, CHUNK_SIZE
@@ -41,21 +41,17 @@ class AtmosError(Exception):
         self.code = code
         self.message = message
 
-class AtmosResponse(Response):
+class AtmosResponse(XmlResponse):
     def success(self):
         return self.status in (httplib.OK, httplib.CREATED, httplib.NO_CONTENT,
                                httplib.PARTIAL_CONTENT)
 
-    def parse_body(self):
-        if not self.body:
-            return None
-        tree = ElementTree.fromstring(self.body)
-        return tree
-
     def parse_error(self):
-        if not self.body:
+        tree = self.parse_body()
+
+        if tree is None:
             return None
-        tree = ElementTree.fromstring(self.body)
+
         code = int(tree.find('Code').text)
         message = tree.find('Message').text
         raise AtmosError(code, message)
