question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Field names mixed up writing via "KML" driver

See original GitHub issue

Expected behavior and actual behavior.

Attempting to save a GeoPandas dataframe using:

        with fiona.Env():
            gdf.to_file(kml_path, driver='KML', NameField='name')

produces a KML file in which the value for <name> is taken from another field, and likewise <description>. If the file is written the hard way (using ogr) it is correct. Perhaps there are some kwargs that need to be passed along to correct this? In the example above NameField='name' was an unsuccessful attempt.

Correct KML using ogr:

<?xml version="1.0" encoding="utf-8" ?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document id="root_doc">
<Schema name="walk" id="walk">
	<SimpleField name="id" type="string"></SimpleField>
	<SimpleField name="date" type="string"></SimpleField>
	<SimpleField name="distance" type="string"></SimpleField>
	<SimpleField name="speed" type="string"></SimpleField>
	<SimpleField name="time" type="string"></SimpleField>
	<SimpleField name="activity_name" type="string"></SimpleField>
</Schema>
<Folder><name>walk</name>
  <Placemark>
	<name>Walked 3.97 km on 22/1/17</name>
	<Style><LineStyle><color>ff0000ff</color></LineStyle><PolyStyle><fill>0</fill></PolyStyle></Style>
	<ExtendedData><SchemaData schemaUrl="#walk">
		<SimpleData name="id">1965703340</SimpleData>
		<SimpleData name="date">01/22/2017</SimpleData>
		<SimpleData name="distance">3.96978493824</SimpleData>
		<SimpleData name="speed">1.397811597971831</SimpleData>
		<SimpleData name="time">2840</SimpleData>
		<SimpleData name="activity_name">Walk</SimpleData>
	</SchemaData></ExtendedData>
      <LineString><coordinates>151.165393442,-33.7688339688 ... 151.16551338,-33.7687453898</coordinates></LineString>
  </Placemark> ...

Incorrect KML using Fiona (see Placemark name and description):

<?xml version="1.0" encoding="utf-8" ?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document id="root_doc">
<Schema name="walk" id="walk">
	<SimpleField name="id" type="string"></SimpleField>
	<SimpleField name="date" type="string"></SimpleField>
	<SimpleField name="distance" type="float"></SimpleField>
	<SimpleField name="speed" type="float"></SimpleField>
	<SimpleField name="time" type="string"></SimpleField>
	<SimpleField name="activity_name" type="string"></SimpleField>
</Schema>
<Folder><name>walk</name>
  <Placemark>
	<name>2840</name>
	<description>01/22/2017</description>
	<Style><LineStyle><color>ff0000ff</color></LineStyle><PolyStyle><fill>0</fill></PolyStyle></Style>
	<ExtendedData><SchemaData schemaUrl="#walk">
		<SimpleData name="id">3.96978493824</SimpleData>
		<SimpleData name="date">Walked 3.97 km on 22/1/17</SimpleData>
		<SimpleData name="distance">1.39781159797183</SimpleData>
		<SimpleData name="speed">0</SimpleData>
	</SchemaData></ExtendedData>
      <LineString><coordinates>151.165393442,-33.7688339688 ... 151.16551338,-33.7687453898</coordinates></LineString>
  </Placemark> ...

Steps to reproduce the problem.

I don’t think there was anything special about the GeoDataFrame, but can provide a script and sample data if the answer is not trivial.

Operating system

Mac OS X 10.15.4

Fiona and GDAL version and provenance

Fiona 1.8.13.post1 loaded by PyCharm GDAL 2.4.0 loaded by PyCharm

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:7 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
wheeledcommented, Jun 30, 2020

So https://github.com/Toblerity/Fiona/blob/master/fiona/ogrext.pyx#L1119-L1122 explains how the fields get mixed up. If I simulate the behaviour of the dict(zip()) it produces a mapping that agrees with the result:

coll_schema = ["id", "date", "distance", "name", "speed", "time", "activity_name"]
ogr_schema = ["Name", "Description", "id", "date", "distance", "name", "speed", "time", "activity_name"]
schema_mapping = dict(zip(coll_schema, ogr_schema))
print(schema_mapping)

{'id': 'Name', 'date': 'Description', 'distance': 'id', 'name': 'date', 'speed': 'distance', 'time': 'name', 'activity_name': 'speed'}

[note that this process remaps time to name and then later on the ogr driver remaps name to Name]

I understand that you are not necessarily keen to support KML, but if this issue also affects some other drivers would it be possible to classify it as a bug?

I imagine the fix would be to check that the collection.schema['properties'].keys() and ogr_schema['properties'].keys() were the same length prior to zipping them. If all of the offending ogr drivers add their special fields at the beginning of the schema, this might work as a fix:

        ogr_schema = self.get_schema()['properties'].keys()
        coll_schema = collection.schema['properties'].keys()
        offset = len(ogr_schema) - len(coll_schema)
        self._schema_mapping = dict(zip(
            coll_schema,
            ogr_schema[offset:] ))

This assumes that the driver will look after its own Name and Description fields.

I apologise again that I am not set up to be able to test it.

0reactions
rbuffatcommented, Jun 29, 2020

The real issue is, that the KML driver automatically adds fields: https://github.com/OSGeo/gdal/blob/master/gdal/ogr/ogrsf_frmts/kml/ogrkmllayer.cpp#L116-L120

https://github.com/Toblerity/Fiona/blob/master/fiona/ogrext.pyx#L1119-L1122 assumes that only the fields in the schema provided to Fiona exist. The same issue is also present for the DXF, GPX, GPSTrackMacker and DGN driver.

Tested by adding:

diff --git a/fiona/ogrext.pyx b/fiona/ogrext.pyx
index a0b2a6c..c8163ca 100644
--- a/fiona/ogrext.pyx
+++ b/fiona/ogrext.pyx
@@ -1083,6 +1083,12 @@ cdef class WritingSession(Session):
 
             encoding = self._get_internal_encoding()
 
+            _schema = self.get_schema()
+            log.debug("before schema: {}".format(_schema))
+
+            if len(_schema['properties']) > 0:
+                raise ValueError("Driver {} has non empty schema: {}".format(self.collection.driver, _schema))
+
             for key, value in collection.schema['properties'].items():
 
                 log.debug("Begin creating field: %r value: %r", key, value)

Read more comments on GitHub >

github_iconTop Results From Across the Web

KML - Keyhole Markup Language — GDAL documentation
KML Writing ​​ The KML Driver will rename some layers, or source KML folder names, into new names it considers valid, for example...
Read more >
Adding Custom Data | Keyhole Markup Language
KML offers three ways to add custom data to a KML Feature. Which approach you choose depends on the kind of data you're...
Read more >
How to load all fields/ExtendedData (not just 'name' and ...
The underlying problem is the missing library LibKML for windows. My solution is extracting the data directly from the KML via a function....
Read more >
ogr2ogr export to KML from SQLite, when using SELECT for ...
db. Now, I'd like to ommit the creation of the ExtendedData by the KML driver and tried so by putting the columns 'name'...
Read more >
KML - Keyhole Markup Language - MapServer
First you should make sure that your GDAL/OGR build contains the «KML» driver, by using the ‹–formats› command: >ogrinfo --formats Loaded OGR Format...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found