'XML Importer
@param source: the data source, accepts source=xxx, source=[xxx, yyy, zzz] or
source=[(resourcename1, xxx), (resourcename2, yyy)], where the
xxx has to be either an ElementTree or a file-like object
@param files: attached files (None to read in the HTTP request)
@param id: ID (or list of IDs) of the record(s) to update (performs only update)
@param format: type of source = "xml", "json" or "csv"
@param stylesheet: stylesheet to use for transformation
@param extra_data: for CSV imports, dict of extra cols to add to each row
@param ignore_errors: skip invalid records silently
@param job_id: resume from previous import job_id
@param commit_job: commit the job to the database
@param delete_job: delete the import job from the queue
@param strategy: tuple of allowed import methods (create/update/delete)
@param update_policy: policy for updates (sync)
@param conflict_policy: policy for conflict resolution (sync)
@param last_sync: last synchronization datetime (sync)
@param onconflict: callback hook for conflict resolution (sync)
@param args: parameters to pass to the transformation stylesheet'

def import_xml(self, source, files=None, id=None, format='xml', stylesheet=None, extra_data=None, ignore_errors=False, job_id=None, commit_job=True, delete_job=False, strategy=None, update_policy=None, conflict_policy=None, last_sync=None, onconflict=None, **args):

    has_permission = current.auth.s3_has_permission
    authorised = (has_permission('create', self.table) and has_permission('update', self.table))
    if (not authorised):
        raise IOError('Insufficient    permissions')
    xml = current.xml
    tree = None
    self.job = None
    if (not job_id):
        args.update(domain=xml.domain, base_url=current.response.s3.base_url, prefix=self.prefix, name=self.name, utcnow=s3_format_datetime())
        if (not isinstance(source, (list, tuple))):
            source = [source]
        for item in source:
            if isinstance(item, (list, tuple)):
                (resourcename, s) = item[:2]
            else:
                (resourcename, s) = (None, item)
            if isinstance(s, etree._ElementTree):
                t = s
            elif (format == 'json'):
                if isinstance(s, basestring):
                    source = StringIO(s)
                    t = xml.json2tree(s)
                else:
                    t = xml.json2tree(s)
            elif (format == 'csv'):
                t = xml.csv2tree(s, resourcename=resourcename, extra_data=extra_data)
            elif (format == 'xls'):
                t = xml.xls2tree(s, resourcename=resourcename, extra_data=extra_data)
            else:
                t = xml.parse(s)
            if (not t):
                if xml.error:
                    raise SyntaxError(xml.error)
                else:
                    raise SyntaxError('Invalid    source')
            if (stylesheet is not None):
                t = xml.transform(t, stylesheet, **args)
                if (not t):
                    raise SyntaxError(xml.error)
            if (not tree):
                tree = t.getroot()
            else:
                tree.extend(list(t.getroot()))
        if ((files is not None) and isinstance(files, dict)):
            self.files = Storage(files)
    else:
        pass
    response = current.response
    response.s3.bulk = True
    success = self.import_tree(id, tree, ignore_errors=ignore_errors, job_id=job_id, commit_job=commit_job, delete_job=delete_job, strategy=strategy, update_policy=update_policy, conflict_policy=conflict_policy, last_sync=last_sync, onconflict=onconflict)
    response.s3.bulk = False
    self.files = Storage()
    if (format == 'json'):
        response.headers['Content-Type'] = 'application/json'
    if (self.error_tree is not None):
        tree = xml.tree2json(self.error_tree)
    else:
        tree = None
    import_info = {'records': self.import_count}
    created = list(set(self.import_created))
    if created:
        import_info['created'] = created
    updated = list(set(self.import_updated))
    if updated:
        import_info['updated'] = updated
    deleted = list(set(self.import_deleted))
    if deleted:
        import_info['deleted'] = deleted
    if (success is True):
        postimport = self.get_config('postimport')
        if postimport:
            callback(postimport, import_info, tablename=self.tablename)
        return xml.json_message(message=self.error, tree=tree, **import_info)
    elif (success and hasattr(success, 'job_id')):
        self.job = success
        return xml.json_message(message=self.error, tree=tree, **import_info)
    return xml.json_message(False, 400, message=self.error, tree=tree)
