OVERRIDDEN: Initialize required ISO-19115 data map with XPATHS and specialized functions

def _init_data_map(self):
        """ OVERRIDDEN: Initialize required ISO-19115 data map with XPATHS and specialized functions """

        if self._data_map is not None:
            return  # Initiation happens once

        # Parse and validate the ISO metadata root

        if self._xml_tree is None:
            iso_root = ISO_ROOTS[0]
        else:
            iso_root = get_element_name(self._xml_tree)

        if iso_root not in ISO_ROOTS:
            raise InvalidContent('Invalid XML root for ISO-19115 standard: {root}', root=iso_root)

        iso_data_map = {'_root': iso_root}
        iso_data_map.update(_iso_tag_roots)
        iso_data_map.update(_iso_tag_formats)

        iso_data_structures = {}

        # Capture and format complex XPATHs

        ad_format = iso_data_map[ATTRIBUTES]
        ft_source = iso_data_map['_attr_src'].replace('/carrierOfCharacteristics/FC_FeatureAttribute', '')

        iso_data_structures[ATTRIBUTES] = format_xpaths(
            _iso_definitions[ATTRIBUTES],

            label=ad_format.format(ad_path='memberName/LocalName'),
            aliases=ad_format.format(ad_path='aliases/LocalName'),  # Not in spec
            definition=ad_format.format(ad_path='definition/CharacterString'),

            # First try to populate attribute definition source from FC_FeatureAttribute
            definition_src=iso_data_map['_attr_src'] + '/organisationName/CharacterString',
            _definition_src=iso_data_map['_attr_src'] + '/individualName/CharacterString',

            # Then assume feature type source is the same as attribute: populate from FC_FeatureType
            __definition_src=ft_source + '/organisationName/CharacterString',
            ___definition_src=ft_source + '/individualName/CharacterString'
        )

        bb_format = iso_data_map[BOUNDING_BOX]
        iso_data_structures[BOUNDING_BOX] = format_xpaths(
            _iso_definitions[BOUNDING_BOX],
            east=bb_format.format(bbox_path='eastBoundLongitude/Decimal'),
            south=bb_format.format(bbox_path='southBoundLatitude/Decimal'),
            west=bb_format.format(bbox_path='westBoundLongitude/Decimal'),
            north=bb_format.format(bbox_path='northBoundLatitude/Decimal')
        )

        ct_format = iso_data_map[CONTACTS]
        iso_data_structures[CONTACTS] = format_xpaths(
            _iso_definitions[CONTACTS],
            name=ct_format.format(ct_path='individualName/CharacterString'),
            organization=ct_format.format(ct_path='organisationName/CharacterString'),
            position=ct_format.format(ct_path='positionName/CharacterString'),
            email=ct_format.format(
                ct_path='contactInfo/CI_Contact/address/CI_Address/electronicMailAddress/CharacterString'
            )
        )

        dt_format = iso_data_map[DATES]
        iso_data_structures[DATES] = {
            DATE_TYPE_MULTIPLE: dt_format.format(type_path='TimeInstant/timePosition'),
            DATE_TYPE_RANGE_BEGIN: dt_format.format(type_path='TimePeriod/begin/TimeInstant/timePosition'),
            DATE_TYPE_RANGE_END: dt_format.format(type_path='TimePeriod/end/TimeInstant/timePosition'),
            DATE_TYPE_SINGLE: dt_format.format(type_path='TimeInstant/timePosition')  # Same as multiple
        }
        iso_data_structures[DATES][DATE_TYPE_RANGE] = [
            iso_data_structures[DATES][DATE_TYPE_RANGE_BEGIN],
            iso_data_structures[DATES][DATE_TYPE_RANGE_END]
        ]

        df_format = iso_data_map[DIGITAL_FORMS]
        iso_data_structures[DIGITAL_FORMS] = format_xpaths(
            _iso_definitions[DIGITAL_FORMS],
            name=df_format.format(df_path='name/CharacterString'),
            content='',  # Not supported in ISO-19115 (appending to spec)
            decompression=df_format.format(df_path='fileDecompressionTechnique/CharacterString'),
            version=df_format.format(df_path='version/CharacterString'),
            specification=df_format.format(df_path='specification/CharacterString'),
            access_desc=iso_data_map['_access_desc'],
            access_instrs=iso_data_map['_access_instrs'],
            network_resource=iso_data_map['_network_resource']
        )

        keywords_structure = {
            'keyword_root': 'MD_Keywords/keyword',
            'keyword_type': 'MD_Keywords/type/MD_KeywordTypeCode',
            'keyword': 'MD_Keywords/keyword/CharacterString'
        }
        for keyword_prop in KEYWORD_PROPS:
            iso_data_structures[keyword_prop] = deepcopy(keywords_structure)

        lw_format = iso_data_map[LARGER_WORKS]
        iso_data_structures[LARGER_WORKS] = format_xpaths(
            _iso_definitions[LARGER_WORKS],
            title=lw_format.format(lw_path='title/CharacterString'),
            edition=lw_format.format(lw_path='edition/CharacterString'),
            origin=iso_data_map['_lw_citation'].format(lw_path='individualName/CharacterString'),
            online_linkage=iso_data_map['_lw_linkage'].format(lw_path='linkage/URL'),
            other_citation=lw_format.format(lw_path='otherCitationDetails/CharacterString'),
            date=lw_format.format(lw_path='editionDate/Date'),
            place=iso_data_map['_lw_contact'].format(lw_path='address/CI_Address/city/CharacterString'),
            info=iso_data_map['_lw_citation'].format(lw_path='organisationName/CharacterString')
        )

        ps_format = iso_data_map[PROCESS_STEPS]
        iso_data_structures[PROCESS_STEPS] = format_xpaths(
            _iso_definitions[PROCESS_STEPS],
            description=ps_format.format(ps_path='description/CharacterString'),
            date=ps_format.format(ps_path='dateTime/DateTime'),
            sources=ps_format.format(
                ps_path='source/LI_Source/sourceCitation/CI_Citation/alternateTitle/CharacterString'
            )
        )

        ri_format = iso_data_map[RASTER_INFO]
        iso_data_structures[RASTER_INFO] = format_xpaths(
            _iso_definitions[RASTER_DIMS],
            type=ri_format.format(ri_path='dimensionName/MD_DimensionNameTypeCode'),
            _type=ri_format.format(ri_path='dimensionName/MD_DimensionNameTypeCode/@codeListValue'),
            size=ri_format.format(ri_path='dimensionSize/Integer'),
            value=ri_format.format(ri_path='resolution/Measure'),
            units=ri_format.format(ri_path='resolution/Measure/@uom')
        )

        # Assign XPATHS and gis_metadata.utils.ParserProperties to data map

        for prop, xpath in iteritems(dict(iso_data_map)):
            if prop == ATTRIBUTES:
                iso_data_map[prop] = ParserProperty(self._parse_attribute_details, self._update_attribute_details)

            elif prop in (CONTACTS, PROCESS_STEPS):
                iso_data_map[prop] = ParserProperty(self._parse_complex_list, self._update_complex_list)

            elif prop in (BOUNDING_BOX, LARGER_WORKS):
                iso_data_map[prop] = ParserProperty(self._parse_complex, self._update_complex)

            elif prop == DATES:
                iso_data_map[prop] = ParserProperty(self._parse_dates, self._update_dates)

            elif prop == DIGITAL_FORMS:
                iso_data_map[prop] = ParserProperty(self._parse_digital_forms, self._update_digital_forms)

            elif prop in KEYWORD_PROPS:
                iso_data_map[prop] = ParserProperty(self._parse_keywords, self._update_keywords)

            elif prop == RASTER_INFO:
                iso_data_map[prop] = ParserProperty(self._parse_raster_info, self._update_raster_info)

            else:
                iso_data_map[prop] = xpath

        self._data_map = iso_data_map
        self._data_structures = iso_data_structures