'Update an existing zone.
:param zone: Zone to update.
:type  zone: :class:`Zone`
:param domain: Name of zone, followed by a dot (.) (e.g. example.com.)
:type  domain: ``str``
:param type: Zone type (master / slave).
:type  type: ``str``
:param ttl: TTL for new records. (optional)
:type  ttl: ``int``
:param extra: Extra attributes (\'ns\', \'mbox\', \'refresh\', \'retry\',
\'expire\', \'minimum\', \'xfer\', \'update_acl\'). (optional)
:type  extra: ``dict``
:rtype: :class:`Zone`'

def update_zone(self, zone, domain, type='master', ttl=None, extra=None):

    if (ttl is None):
        ttl = zone.ttl
    if (extra is None):
        extra = zone.extra
    else:
        extra_fields = ZONE_EXTRA_PARAMS_DEFAULT_VALUES.keys()
        missing = set(extra_fields).difference(set(extra.keys()))
        for field in missing:
            extra[field] = zone.extra.get(field)
    schema_params = SCHEMA_BUILDER_MAP.get('update_zone')
    attributes = schema_params.get('attributes')
    schema = api_schema_builder(schema_params.get('urn_nid'), schema_params.get('method'), attributes)
    params = {'apiuser': self.key, 'apikey': self.secret, 'zonename': domain, 'ttl': ttl}
    params.update(extra)
    urn = schema.getchildren()[0]
    for child in urn:
        key = child.tag.split(':')[2]
        if (key in attributes):
            if isinstance(params.get(key), int):
                child.text = '%d'
            else:
                child.text = '%s'
    skel = ensure_string(tostring(schema))
    req_data = (skel % (self.key, self.secret, domain, extra['ns'], extra['mbox'], extra['refresh'], extra['retry'], extra['expire'], extra['minimum'], ttl, extra['xfer'], extra['update_acl']))
    action = '/services/dns/updateZone.php?'
    headers = {'SOAPAction': 'urn:updateZonewsdl#updateZone'}
    try:
        self.connection.request(action=action, data=req_data, method='POST', headers=headers)
    except DurableDNSException:
        e = sys.exc_info()[1]
        if ('Zone    does    not    exist' in e.message):
            raise ZoneDoesNotExistError(zone_id=zone.id, driver=self, value=e.message)
        raise e
    zone = self.get_zone(zone.id)
    return zone
