-1

I wrote a .kmz file generator using a google places API. The program works great on my local machine but once I launched it on Azure, user's are not receiving the custom icon when opened on google earth. It just displays the white box with red x in the center as the icon. I have verified that the icon is downloading inside the .kmz file along with the kml file by having the remote user change .kmz to .zip and unzipping the file to see the contents. There they find the kml file and the custom icon png file so It must be something with where I'm placing it or how google earth references icons in the kmz...? I'm at a lost I've tried everything. Here's the main part of my app:

import requests
from fastkml import kml
from fastkml import styles
from fastkml.geometry import Point
from fastkml.styles import IconStyle
import xml.etree.ElementTree as ET
from pykml.factory import KML_ElementMaker as KML
from pykml.parser import fromstring as kml_fromstring
import os
import zipfile
import tempfile
import shutil


# Get the path of the current script
script_dir = os.path.dirname(os.path.abspath(__file__))

# Construct the path to the icon file
icon_filename = 'Bank Icon.png'
icon_path = os.path.join(script_dir, icon_filename)

# Google Maps API key
api_key = "My_API_key"

def search_institution_locations(institution, location):
    search_url = "https://maps.googleapis.com/maps/api/place/textsearch/xml"
    query = f"{institution} in {location}"
    params = {
        "query": query,
        "key": api_key,
    }
    try:
        response = requests.get(search_url, params=params)
        response.raise_for_status()
    except Exception as e:
        print(f"An error occurred while searching for {institution} in {location}: {e}")
        return None

    # Print the response text for debugging purposes
    print(response.text)

    return response.text

def generate_kml(institution, city=None, state=None, icon_path=None):
    print('kml generator initiated')

    # Update the icon_path if it's not provided
    if icon_path is None:
        script_dir = os.path.dirname(os.path.abspath(__file__))
        icon_filename = 'Bank Icon.png'
        icon_path = os.path.join(script_dir, icon_filename)

    # Determine the location based on the search scope
    location = f"{city}, {state}"

    # Search for institution locations within the location
    search_results = search_institution_locations(institution, location)

    # Parse the XML search results
    root = ET.fromstring(search_results)

    # Create a KML document
    doc = kml.Document()

    # Create the IconStyle with the custom icon
    icon_style = styles.IconStyle(icon_href=icon_path, scale=2.0)

    # Create the LabelStyle with a scale of 0.0 to hide the text
    label_style = styles.LabelStyle(scale=0.0)

    # Combine the IconStyle and LabelStyle into a Style
    style = styles.Style(id='icon', styles=[icon_style, label_style])
    doc.append_style(style)

    # Add Placemarks for each search result
    for result in root.findall("result"):
        name = result.find("name").text
        address = result.find("formatted_address").text
        lat = float(result.find("geometry/location/lat").text)
        lng = float(result.find("geometry/location/lng").text)

        placemark = kml.Placemark(
            name=name,
            description=address,
            styleUrl="#icon"  # Use the custom icon style
        )
        placemark.geometry = Point((lng, lat))
        doc.append(placemark)

    # Save KML file
    with tempfile.NamedTemporaryFile(suffix='.kml', delete=False) as temp:
        print(doc.to_string(prettyprint=True))
        kml_file_path = temp.name
        with open(kml_file_path, "w", encoding="utf-8") as f:
            f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
            f.write(doc.to_string(prettyprint=True))

    # Create KMZ file
    kmz_file_name = f"{institution.replace(' ', '_')}_locations.kmz"
    with tempfile.NamedTemporaryFile(suffix='.kmz', delete=False) as temp:
        kmz_file_path = temp.name

    with zipfile.ZipFile(kmz_file_path, 'w', zipfile.ZIP_DEFLATED) as zf:
        zf.write(kml_file_path, arcname=os.path.splitext(kmz_file_name)[0] + '.kml')  # Modified line
        zf.write(icon_path, arcname=os.path.basename(icon_path))


    # Remove the temporary KML file
    os.remove(kml_file_path)

    return kmz_file_path

1 Answers1

0

Just wanted to update this since I ended up figuring out the answer on my own. The issue was that the Bank Icon.png needed to be in a directory named "files" and I had to update the kml_generator to reference the new location. Here is the updated code:

import requests
from fastkml import kml
from fastkml import styles
from fastkml.geometry import Point
from fastkml.styles import IconStyle
import xml.etree.ElementTree as ET
from pykml.factory import KML_ElementMaker as KML
from pykml.parser import fromstring as kml_fromstring
import os
import zipfile
import tempfile
import pathlib
import shutil


# Get the path of the current script
script_dir = os.path.dirname(os.path.abspath(__file__))

# Construct the path to the icon file
icon_filename = 'Bank Icon.png'
icon_path = os.path.join('files', icon_filename)

# Create the 'files' directory if it doesn't exist
files_dir = os.path.join(script_dir, 'files')
pathlib.Path(files_dir).mkdir(parents=True, exist_ok=True)

# Copy the 'Bank Icon.png' to the 'files' directory if it doesn't exist
icon_src_path = os.path.join(script_dir, icon_filename)
icon_dest_path = os.path.join(files_dir, icon_filename)
if not os.path.exists(icon_dest_path):
    shutil.copy(icon_src_path, icon_dest_path)

# Google Maps API key
api_key = "My_Google_Place_API_Key"

def search_institution_locations(institution, location):
    search_url = "https://maps.googleapis.com/maps/api/place/textsearch/xml"
    query = f"{institution} in {location}"
    params = {
        "query": query,
        "key": api_key,
    }
    try:
        response = requests.get(search_url, params=params)
        response.raise_for_status()
    except Exception as e:
        print(f"An error occurred while searching for {institution} in {location}: {e}")
        return None

    # Print the response text for debugging purposes
    print(response.text)

    return response.text

def generate_kml(institution, city=None, state=None, icon_path=None):
    print('kml generator initiated')

    # Update the icon_path if it's not provided
    if icon_path is None:
        icon_filename = 'Bank Icon.png'
        icon_path = os.path.join('files', icon_filename)


    # Determine the location based on the search scope
    location = f"{city}, {state}"

    # Search for institution locations within the location
    search_results = search_institution_locations(institution, location)

    # Parse the XML search results
    root = ET.fromstring(search_results)

    # Create a KML document
    doc = kml.Document()

    # Create the IconStyle with the custom icon
    icon_style = styles.IconStyle(icon_href=icon_path, scale=2.0)


    # Create the LabelStyle with a scale of 0.0 to hide the text
    label_style = styles.LabelStyle(scale=0.0)

    # Combine the IconStyle and LabelStyle into a Style
    style = styles.Style(id='icon', styles=[icon_style, label_style])
    doc.append_style(style)

    # Add Placemarks for each search result
    for result in root.findall("result"):
        name = result.find("name").text
        address = result.find("formatted_address").text
        lat = float(result.find("geometry/location/lat").text)
        lng = float(result.find("geometry/location/lng").text)

        placemark = kml.Placemark(
            name=name,
            description=address,
            styleUrl="#icon"  # Use the custom icon style
        )
        placemark.geometry = Point((lng, lat))
        doc.append(placemark)

    # Save KML file
    with tempfile.NamedTemporaryFile(suffix='.kml', delete=False) as temp:
        print(doc.to_string(prettyprint=True))
        kml_file_path = temp.name
        with open(kml_file_path, "w", encoding="utf-8") as f:
            f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
            f.write(doc.to_string(prettyprint=True))

    # Create KMZ file
    kmz_file_name = f"{institution.replace(' ', '_')}_locations.kmz"
    with tempfile.NamedTemporaryFile(suffix='.kmz', delete=False) as temp:
        kmz_file_path = temp.name

    with zipfile.ZipFile(kmz_file_path, 'w', zipfile.ZIP_DEFLATED) as zf:
        zf.write(kml_file_path, arcname=os.path.splitext(kmz_file_name)[0] + '.kml')
        zf.write(os.path.join(script_dir, icon_filename), arcname=os.path.join('files', icon_filename))

    # Remove the temporary KML file
    os.remove(kml_file_path)

    return kmz_file_path