'A class that handles loading from xml.  Does some munging to ensure that
all elements have unique slugs.
xmlstore: the XMLModuleStore to store the loaded modules in'

def __init__(self, xmlstore, course_id, course_dir, error_tracker, load_error_modules=True, target_course_id=None, **kwargs):

    self.unnamed = defaultdict(int)
    self.used_names = defaultdict(set)
    self.course_id = course_id
    self.load_error_modules = load_error_modules
    self.modulestore = xmlstore
    def process_xml(xml):
        'Takes    an    xml    string,    and    returns    a    XBlock    created    from\n                                                that    xml.\n                                                '
        def make_name_unique(xml_data):
            "\n                                                                Make    sure    that    the    url_name    of    xml_data    is    unique.        If    a    previously    loaded\n                                                                unnamed    descriptor    stole    this    element's    url_name,    create    a    new    one.\n\n                                                                Removes    'slug'    attribute    if    present,    and    adds    or    overwrites    the    'url_name'    attribute.\n                                                                "
            need_uniq_names = ('problem', 'sequential', 'video', 'course', 'chapter', 'videosequence', 'poll_question', 'vertical')
            attr = xml_data.attrib
            tag = xml_data.tag
            id = (lambda x: x)
            lookups = [('url_name', id, False), ('slug', id, True), ('name', Location.clean, False), ('display_name', Location.clean, False)]
            url_name = None
            for (key, clean, remove) in lookups:
                if (key in attr):
                    url_name = clean(attr[key])
                    if remove:
                        del attr[key]
                    break
            def looks_like_fallback(url_name):
                'Does    this    look    like    something    that    came    from    fallback_name()?'
                return ((url_name is not None) and url_name.startswith(tag) and re.search('[0-9a-fA-F]{12}$', url_name))
            def fallback_name(orig_name=None):
                'Return    the    fallback    name    for    this    module.        This    is    a    function    instead    of    a    variable\n                                                                                because    we    want    it    to    be    lazy.'
                dog_stats_api.increment(DEPRECATION_VSCOMPAT_EVENT, tags=('location:import_system_fallback_name', u'name:{}'.format(orig_name)))
                if looks_like_fallback(orig_name):
                    orig_name = orig_name[(len(tag) + 1):(-12)]
                orig_name = (('_' + orig_name) if (orig_name not in (None, '')) else '')
                xml_bytes = xml.encode('utf8')
                return (((tag + orig_name) + '_') + hashlib.sha1(xml_bytes).hexdigest()[:12])
            if ((url_name is None) or (url_name == '')):
                url_name = fallback_name()
                if (tag in need_uniq_names):
                    error_tracker(u"PROBLEM:    no    name    of    any    kind    specified    for    {tag}.        Student    state    will    not    be    properly    tracked    for    this    module.        Problem    xml:    '{xml}...'".format(tag=tag, xml=xml[:100]))
                else:
                    pass
            if (url_name in self.used_names[tag]):
                if (tag in need_uniq_names):
                    msg = u'Non-unique    url_name    in    xml.        This    may    break    state    tracking    for    content.        url_name={0}.        Content={1}'.format(url_name, xml[:100])
                    error_tracker(('PROBLEM:    ' + msg))
                    log.warning(msg)
                    url_name = fallback_name(url_name)
            self.used_names[tag].add(url_name)
            xml_data.set('url_name', url_name)
        try:
            xml = clean_out_mako_templating(xml)
            xml_data = etree.fromstring(xml)
            make_name_unique(xml_data)
            descriptor = self.xblock_from_node(xml_data, None, id_manager)
        except Exception as err:
            if (not self.load_error_modules):
                raise
            msg = 'Error    loading    from    xml.    %s'
            log.warning(msg, unicode(err)[:200])
            msg = (msg % unicode(err)[:200])
            self.error_tracker(msg)
            err_msg = ((msg + '\n') + exc_info_to_str(sys.exc_info()))
            descriptor = ErrorDescriptor.from_xml(xml, self, id_manager, err_msg)
        descriptor.data_dir = course_dir
        if (descriptor.scope_ids.usage_id in xmlstore.modules[course_id]):
            other_copy = xmlstore.modules[course_id][descriptor.scope_ids.usage_id]
            descriptor.parent = other_copy.parent
            if (descriptor != other_copy):
                log.warning('%s    has    more    than    one    definition', descriptor.scope_ids.usage_id)
        xmlstore.modules[course_id][descriptor.scope_ids.usage_id] = descriptor
        if descriptor.has_children:
            for child in descriptor.get_children():
                if ((child.parent is None) or (child.parent > descriptor.scope_ids.usage_id)):
                    child.parent = descriptor.location
                    child.save()
        descriptor.save()
        return descriptor
    render_template = (lambda template, context: u'')
    def load_item(usage_key, for_parent=None):
        'Return    the    XBlock    for    the    specified    location'
        return xmlstore.get_item(usage_key, for_parent=for_parent)
    resources_fs = OSFS((xmlstore.data_dir / course_dir))
    id_manager = CourseImportLocationManager(course_id, target_course_id)
    super(ImportSystem, self).__init__(load_item=load_item, resources_fs=resources_fs, render_template=render_template, error_tracker=error_tracker, process_xml=process_xml, id_generator=id_manager, id_reader=id_manager, **kwargs)
