Post

A Quick Workaround for the missing Import Function within Nextcloud Maps

Introduction

Nextcloud Maps is a powerful addon for your Nextcloud instance in order to store your GPX points, add fotos and comments, as well as do your own route planning. I primarily use it to store some GPS coordinates of places I have been to within the favorites section - see top-left corner:

Desktop View

Problem

Storing points in the Favourites section is not a problem. However, I realized that I run into problems in case I export the coordinates under Favourites and intend to import them again afterwards. The export works great and leaves a GPX file including all coordinates and metadata under your Maps folder in the Nextcloud root folder. However, the import function does not exist (yet?). I checked the github page and found some comments about the same problem here and here.

So, it seems like this feature doesn’t exist yet. What to do?

The open source community deserves all our gratitude and respect for providing us with a great basic functionality. If we want this to be fixed, we need to be part of the solution, not the problem. Since my programming skills with JS are limited, I searched for a way to fix the import for myself with a quick and dirty workaround based on some LLM support.

Workaround

First, I checked the database structure of the Nextcloud Maps Addon and there is a table named oc_maps_favorites which stores the Favourite points in the following SQL structure:

Desktop View

So this is where our imports need to go. Instead of using an official app import function, we can simply push the coordinates into the SQL database directly. But let’s first review the export extract that you can create via the Favourites menu.

GPX Extract of Favourites within Nextcloud Maps

The exported GPX file within the Maps folder looks like a typical XML GPX file:

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<gpx version="1.1" creator="Nextcloud Maps 1.4.0" xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"> 
<metadata> 
	<name>favourites</name> 
</metadata>
<wpt lat="29.XXX" lon="36.XXX">
	<name>foo</name>
	<time>2024-05-09T09:01:48Z</time>
	<type>bar</type> 
</wpt> 
...
</gpx>

The coordinates we are interested in are represented by the lat and lon values. In order to extract them in a structured way, we can use a simple Python3 script which I asked Microsoft Copilot to create. You can find the outcome below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import xml.etree.ElementTree as ET
import os

def extract_coordinates(gpxfile):
    """
    Parse the GPX file and extract latitude and longitude values.
    
    :param gpxfile: Path to the GPX file
    :return: List of tuples containing latitude and longitude values
    """
    try:
        # Parse the GPX file
        tree = ET.parse(gpxfile)
        root = tree.getroot()

        # Extract latitude and longitude values
        coordinates = []
        for wpt in root.findall('{http://www.topografix.com/GPX/1/1}wpt'):
            lat = wpt.get('lat')
            lon = wpt.get('lon')
            coordinates.append((lat, lon))

        return coordinates
    except ET.ParseError as e:
        print(f"Error parsing the GPX file: {e}")
    except Exception as e:
        print(f"An unexpected error occurred: {e}")
    
    return []

def generate_sql_insert_statements(coordinates, user_id):
    """
    Generate SQL insert statements for the given coordinates.
    
    :param coordinates: List of tuples containing latitude and longitude values
    :param user_id: User ID to be used in the insert statements
    :return: List of SQL insert statements
    """
    sql_statements = []
    for coord in coordinates:
        lat, lon = coord
        sql = f"INSERT INTO `oc_maps_favorites` (`user_id`, `lat`, `lng`) VALUES ('{user_id}', {lat}, {lon});"
        sql_statements.append(sql)
    
    return sql_statements

if __name__ == '__main__':
    # Path to the GPX file
    gpxfile = 'test.gpx'
    user_id = 'myuser'  # Replace this with the actual user ID

    # Check if the file exists
    if not os.path.exists(gpxfile):
        print(f"Error: The file '{gpxfile}' does not exist.")
    else:
        # Extract coordinates and generate SQL insert statements
        coordinates = extract_coordinates(gpxfile)
        if coordinates:
            sql_statements = generate_sql_insert_statements(coordinates, user_id)
            print("Generated SQL insert statements:")
            for sql in sql_statements:
                print(sql)
        else:
            print("No coordinates found or an error occurred.")

Insert Coordinates into Nextcloud Maps Database

As you can see, I asked Copilot also to print out the coordinates in SQL format so that I can easily copy&paste the values into the database. This is what the python script returned and which I added via SQL statements into the MariaDB.

1
2
3
INSERT INTO `oc_maps_favorites` (`user_id`, `lat`, `lng`) VALUES ('myuser', 47.XXX, 8.XXX);
INSERT INTO `oc_maps_favorites` (`user_id`, `lat`, `lng`) VALUES ('myuser', 49.XXX, 9.XXX);
...

I skipped the metadata of each coordinate (except user_id) since I’m only interested in the core coordinates. If you want to keep the metadata of each coordinate you can extract them via the script as well. Copy&Paste the script above into Copilot and ask for support in case you don’t want to do the short adjustment on your own.

Conclusion

One of the key benefits of LLMs is assisting with the creation of concise, uncomplicated scripts. It took me around 20 min to identify the problem, feed it into Copilot and do some minor adjustments afterwards before I ran the script and copy&pasted the coordinates into my SQL.

This post is licensed under CC BY 4.0 by the author.