def gis_encode(self,
                   resource,
                   record,
                   element,
                   location_data={},
                   ):
        """
            GIS-encodes the master resource so that it can be transformed into
            a mappable format.

            @param resource: the referencing resource
            @param record: the particular record
            @param element: the XML element
            @param location_data: dictionary of location data from gis.get_location_data()

            @ToDo: Support multiple locations per master resource (e.g. event_event.location)
        """

        format = current.auth.permission.format
        if format not in ("geojson", "georss", "gpx", "kml"):
            return

        tablename = resource.tablename
        if tablename == "gis_feature_query":
            # Requires no special handling: XSLT uses normal fields
            return

        gis = current.gis
        request = current.request
        settings = current.deployment_settings

        ATTRIBUTE = self.ATTRIBUTE

        # Retrieve data prepared earlier in gis.get_location_data()
        latlons = location_data.get("latlons", [])
        geojsons = location_data.get("geojsons", [])
        #wkts = location_data.get("wkts", [])
        attributes = location_data.get("attributes", [])
        markers = location_data.get("markers", [])
        styles = location_data.get("styles", [])

        map_data = element.find("map")
        if map_data:
            map_data = map_data[0]
        else:
            map_data = etree.SubElement(element, "map")

        attr = map_data.attrib
        record_id = record.id

        if tablename == "gis_location":
            if tablename in geojsons:
                # These have been looked-up in bulk
                geojson = geojsons[tablename].get(record_id, None)
                if geojson:
                    # Always single
                    geometry = etree.SubElement(map_data, "geometry")
                    geometry.set("value", geojson)

            #  @ToDo: KML/GPX/GeoRSS Polygons (or we should also do these outside XSLT)
            #elif tablename in wkts:
            #    wkt = wkts[tablename][record_id]
            #    # Convert the WKT in XSLT
            #    attr[ATTRIBUTE.wkt] = wkt

            elif tablename in latlons:
                # These have been looked-up in bulk
                LatLon = latlons[tablename].get(record_id, None)
                if LatLon:
                    # Always single
                    lat = LatLon[0]
                    lon = LatLon[1]
                    if lat is not None and lon is not None:
                        attr[ATTRIBUTE.lat] = "%.4f" % lat
                        attr[ATTRIBUTE.lon] = "%.4f" % lon

            else:
                # Lookup record by record :/
                # Nothing should get here
                return
                #table = resource.table
                #wkts = gis.get_locations(table,
                #                         (table._id == record_id),
                #                         join=False,
                #                         geojson=False)
                ## Convert the WKT in XSLT
                #if record_id in wkts:
                #    attr[ATTRIBUTE.wkt] = wkts[record_id]

            if format == "geojson":
                if tablename in attributes:
                    # Add Attributes
                    attrs = attributes[tablename][record_id]
                    if attrs:
                        # Encode in a way which we can decode in static/formats/geojson/export.xsl
                        # - double up all tokens to reduce chances of them being within represents
                        # NB Ensure we don't double-encode unicode!
                        _attr = json.dumps(attrs, separators=(",,", "::"),
                                           ensure_ascii=False)
                        attr[ATTRIBUTE.attributes] = "{%s}" % _attr.replace('"', "||")

                if tablename in markers:
                    _markers = markers[tablename]
                    if _markers.get("image", None):
                        # Single Marker here
                        m = _markers
                    else:
                        # We have a separate Marker per-Feature
                        m = _markers[record_id]
                    if m:
                        # Assume being used within the Sahana Mapping client
                        # so use local URLs to keep filesize down
                        download_url = "/%s/static/img/markers" % \
                            request.application
                        attr[ATTRIBUTE.marker_url] = "%s/%s" % (download_url,
                                                                m["image"])
                        attr[ATTRIBUTE.marker_height] = str(m["height"])
                        attr[ATTRIBUTE.marker_width] = str(m["width"])

                if tablename in styles:
                    # Add Styles
                    style = styles[tablename].get(record_id)
                    if style:
                        _style = etree.SubElement(map_data, "style")
                        _style.set("value", style)

                # Now built client-side from the id (=> saves bandwidth)
                # Use gis/location controller in all reports
                #url = URL(c="gis", f="location").split(".", 1)[0]
                # Assume being used within the Sahana Mapping client
                # so use local URLs to keep filesize down
                #url = "%s/%i.plain" % (url, record_id)
                #attr[ATTRIBUTE.popup_url] = url

                # End: format == "geojson"
                return

            elif format == "kml":
                # GIS marker
                marker = gis.get_marker() # Default Marker
                # Quicker to download Icons from Static
                # also doesn't require authentication so KML files can work in
                # Google Earth
                marker_download_url = "%s/%s/static/img/markers" % \
                    (current.deployment_settings.get_base_public_url(),
                     request.application)
                marker_url = "%s/%s" % (marker_download_url, marker.image)
                attr[ATTRIBUTE.marker] = marker_url

            elif format =="gpx":
                symbol = "White Dot"
                attr[ATTRIBUTE.sym] = symbol

            # End: tablename == "gis_location"
            return

        elif len(tablename) > 19 and \
             tablename.startswith("gis_layer_shapefile"):
            # Shapefile data
            if tablename in geojsons:
                # These have been looked-up in bulk
                geojson = geojsons[tablename].get(record_id, None)
                if geojson:
                    # Always single
                    geometry = etree.SubElement(map_data, "geometry")
                    geometry.set("value", geojson)
                    if tablename in attributes:
                        # Add Attributes
                        attrs = attributes[tablename][record_id]
                        if attrs:
                            # Encode in a way which we can decode in static/formats/geojson/export.xsl
                            # - double up all tokens to reduce chances of them being within represents
                            # NB Ensure we don't double-encode unicode!
                            _attr = json.dumps(attrs, separators=(",,", "::"),
                                               ensure_ascii=False)
                            attr[ATTRIBUTE.attributes] = "{%s}" % _attr.replace('"', "||")

            #  @ToDo: KML/GPX/GeoRSS Polygons (or we should also do these outside XSLT)
            #elif tablename in wkts:
            #    wkt = wkts[tablename][record_id]
            #    # Convert the WKT in XSLT
            #    attr[ATTRIBUTE.wkt] = wkt

            else:
                # Lookup record by record :/
                # Nothing should get here
                return
                #table = resource.table
                #wkts = gis.get_locations(table,
                #                         (table._id == record_id),
                #                         join=False,
                #                         geojson=False)
                ## Convert the WKT in XSLT
                #if record_id in wkts:
                #    attr[ATTRIBUTE.wkt] = wkts[record_id]

            # End: Shapefile data
            return

        # Normal Resources
        if format == "geojson":
            if tablename in geojsons:
                # These have been looked-up in bulk
                geojson = geojsons[tablename].get(record_id, None)
                if geojson:
                    for g in geojson:
                        geometry = etree.SubElement(map_data, "geometry")
                        geometry.set("value", g)

            elif tablename in latlons:
                # These have been looked-up in bulk
                LatLon = latlons[tablename].get(record_id, None)
                if LatLon:
                    # @ToDo: Support records with multiple locations
                    #        via making these also use the map element
                    lat = LatLon[0]
                    lon = LatLon[1]
                    if lat is not None and lon is not None:
                        attr[ATTRIBUTE.lat] = "%.4f" % lat
                        attr[ATTRIBUTE.lon] = "%.4f" % lon
            else:
                # Error
                raise RuntimeError("Bulk lookup of GeoJSON or Lat/Lon data failed for %s" % tablename)

            if tablename in attributes:
                # Add Attributes
                try:
                    attrs = attributes[tablename][record_id]
                except KeyError:
                    from s3utils import s3_debug
                    s3_debug("S3XML", "record not found in lookup")
                    attrs = {}
                if attrs:
                    # Encode in a way which we can decode in static/formats/geojson/export.xsl
                    # - double up all tokens to reduce chances of them being within represents
                    # NB Ensure we don't double-encode unicode!
                    _attr = json.dumps(attrs, separators=(",,", "::"),
                                       ensure_ascii=False)
                    attr[ATTRIBUTE.attributes] = "{%s}" % _attr.replace('"', "||")

            if tablename in markers:
                _markers = markers[tablename]
                if _markers:
                    if _markers.get("image", None):
                        # Single Marker here
                        m = _markers
                    else:
                        # We have a separate Marker per-Feature
                        m = _markers[record_id]
                    if m:
                        # Assume being used within the Sahana Mapping client
                        # so use local URLs to keep filesize down
                        download_url = "/%s/static/img/markers" % \
                            request.application
                        attr[ATTRIBUTE.marker_url] = "%s/%s" % (download_url,
                                                                m["image"])
                        attr[ATTRIBUTE.marker_height] = str(m["height"])
                        attr[ATTRIBUTE.marker_width] = str(m["width"])

            if tablename in styles:
                # Add Styles
                style = styles[tablename].get(record_id)
                if style:
                    _style = etree.SubElement(map_data, "style")
                    _style.set("value", style)

            # Now built client-side from the id (=> saves bandwidth)
            # Use the current controller for map popup URLs to get
            # the controller settings applied even for map popups
            # url = URL(request.controller,
            #           request.function).split(".", 1)[0]
            # Assume being used within the Sahana Mapping client
            # so use local URLs to keep filesize down
            #url = "%s/%i.plain" % (url, record_id)
            #attr[ATTRIBUTE.popup_url] = url
            # End: format == "geojson"
            return

        elif tablename in latlons:
            # These have been looked-up in bulk
            LatLon = latlons[tablename].get(record_id, None)
            if LatLon:
                # @ToDo: Support records with multiple locations
                lat = LatLon[0]
                lon = LatLon[1]
                if lat is not None and lon is not None:
                    attr[ATTRIBUTE.lat] = "%.4f" % lat
                    attr[ATTRIBUTE.lon] = "%.4f" % lon

        #  @ToDo: KML/GPX/GeoRSS Polygons (or we should also do these outside XSLT)
        #elif tablename in wkts:
        #    wkt = wkts[tablename][record_id]
        #    # Convert the WKT in XSLT
        #    attr[ATTRIBUTE.wkt] = wkt

        else:
            # Lookup record by record :/
            # Nothing should get here
            return

        if tablename in markers:
            _markers = markers[tablename]
            if _markers.get("image", None):
                # Single Marker here
                m = _markers
            else:
                # We have a separate Marker per-Feature
                m = _markers[record_id]
            if m:
                if format == "gpx":
                    attr[ATTRIBUTE.sym] = m.get("gps_marker",
                                                gis.DEFAULT_SYMBOL)
                else:
                    # Assume being used outside the Sahana Mapping client
                    # so use public URLs
                    download_url = "%s/%s/static/img/markers" % \
                        (settings.get_base_public_url(), request.application)
                    attr[ATTRIBUTE.marker] = "%s/%s" % (download_url,
                                                        m["image"])

    # -------------------------------------------------------------------------
dataset/ETHPy150Open sahana/eden/modules/s3/s3xml.py/S3XML.gis_encode/original