I am trying to export my feature collection to KML using geotools but only the geometry and id(weird id combination of table name + id) is exporting to KML i am getting the data from postgis and then exporting to kml and after searching cant figure out how to export kml with attributes below is the code which i am using

package com.lmkt.ed.qesco.export;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.data.store.ContentFeatureCollection;
import org.geotools.kml.KML;
import org.geotools.kml.KMLConfiguration;
import org.geotools.xml.Encoder;
import org.junit.Test;

public class KMLTest {

    public void testKMLOut(){
//      System.setProperty("org.geotools.referencing.forceXY", "true");

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("dbtype", "postgis");        //must be postgis
        params.put("host", "localhost");        //the name or ip address of the machine running PostGIS
        params.put("port", new Integer(5432));  //the port that PostGIS is running on (generally 5432)
        params.put("database", "gisdb");      //the name of the database to connect to.
        params.put("user", "postgres");         //the user to connect with
        params.put("passwd", "postgres");               //the password of the user.

        DataStore gisDS = null;


            gisDS = DataStoreFinder.getDataStore(params);

            SimpleFeatureSource sfs;

            sfs = gisDS.getFeatureSource("gistable1");   // point type

            ContentFeatureCollection coll = (ContentFeatureCollection) sfs.getFeatures();

            //                 SimpleFeatureIterator iterator = coll.features();
            //                  try {
            //                      while (iterator.hasNext()) {
            //                          SimpleFeature feature = iterator.next();
            //                          System.out.println(feature.getID());
            //                          System.out.println(feature.getAttribute("id")); // prints null 
            //                          // process feature
            //                      }
            //                  } finally {
            //                      iterator.close();
            //                  }

            KMLConfiguration config = new KMLConfiguration();
            Encoder encoder = new Encoder(config);

            //ByteArrayOutputStream out = new ByteArrayOutputStream();

            encoder.encode(coll, KML.kml, 
                    System.out) ;
        } catch (IOException e) {
        } catch (Exception e) {

The above code is not exporting the attribute of table1 its only exporting id and geometry and id is the combination table name + id i.e. tablename.id ,Below is the sniipet of xml generated by this code

<?xml version="1.0" encoding="UTF-8"?><kml:kml xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:kml="http://earth.google.com/kml/2.1">
<kml:Placemark id="gistable1.2">
<kml:Placemark id="gistable1.1">

Using geotools version 19.1 with following dependency



table structure

CREATE TABLE public.gistable1
    "Name" character varying(30) COLLATE pg_catalog."default" NOT NULL,
    "Address" character varying(30) COLLATE pg_catalog."default",
    geom geometry(Point,4326),
    id integer NOT NULL DEFAULT 0,
    CONSTRAINT gistable1_pkey PRIMARY KEY (id)
TABLESPACE pg_default;

ALTER TABLE public.gistable1
    OWNER to postgres;
  • Does your table have a primary key?
    – Ian Turton
    Commented Sep 16, 2018 at 16:57
  • yes it has a primary key id is 1426 it becomes id="gistable1.1426"
    – Haider
    Commented Sep 16, 2018 at 17:04
  • @IanTurton see updated question for table structure
    – Haider
    Commented Sep 16, 2018 at 17:17

1 Answer 1


All my KML code seems to use the v2.2 configuration and does export the attributes to the KML.

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;

import org.geotools.data.DataUtilities;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.kml.v22.KML;
import org.geotools.kml.v22.KMLConfiguration;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.xml.Encoder;
import org.locationtech.jts.geom.Polygon;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import com.ianturton.cookbook.utilities.GenerateRandomData;

public class KMLWriter {

  public static void main(String[] args)  {
    SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();

    CoordinateReferenceSystem crs = DefaultGeographicCRS.WGS84;

    typeBuilder.add("polyGeom", Polygon.class);
    typeBuilder.add("attrS", String.class);
    ArrayList<SimpleFeature> list = new ArrayList<>();
    SimpleFeatureType featureType = (SimpleFeatureType) typeBuilder.buildFeatureType();
    for (int i = 0; i < 10; i++) {
      SimpleFeature f = GenerateRandomData.createSimplePolygonFeature(featureType);
      f.setAttribute("attrS", "a random string "+i);
      f.setAttribute("attrI", i);
    SimpleFeatureCollection featureCollection = DataUtilities.collection(list);

    Encoder encoder = new Encoder(new KMLConfiguration());
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    try {
      encoder.encode(featureCollection, KML.kml, os );
      String out = os.toString().replaceAll("kml:", "");
    } catch (Exception e) {


Gives the following output:

<?xml version="1.0" encoding="UTF-8"?><kml:kml xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<kml:Document id="featureCollection">
<kml:Placemark id="fid-4a5c09f6_165e6c0b963_-7ff7">
<kml:Data name="attrS">
<kml:value>a random string 9</kml:value>
<kml:Data name="attrI">
<kml:coordinates>33.13967256535696,2.3488063547551974 28.337817634867786,-1.7341316252329522 24.715818660608015,0.8033809627991104 27.093250414412505,-3.1241208971098766 24.72344364443347,-6.872388632082184 33.13967256535696,2.3488063547551974</kml:coordinates>
<kml:Placemark id="fid-4a5c09f6_165e6c0b963_-7ff8">
<kml:Data name="attrS">
<kml:value>a random string 8</kml:value>
<kml:Data name="attrI">

For your Id issue this is normal behaviour as GeoTools wants to try to keep your featureIDs "unique" and immutable across the system so it appends the table name to the primary key and requires you to use feature.getID() to access it (with no setter). If you add the PostgisNGDataStoreFactory.EXPOSE_PK parameter to your PostGIS datastore parameter map it will allow you to access the ID column as an attribute.

  • I have tested and it works fine with postgis and shapefile datasources. Unless you have null attributes in which case you need this github.com/geotools/geotools/pull/2042 fix.
    – Ian Turton
    Commented Sep 17, 2018 at 13:15
  • Yes data was null that the issue :) , thanks spent a whole day in it
    – Haider
    Commented Sep 17, 2018 at 14:37
  • That would not cause the issue you reported
    – Ian Turton
    Commented Sep 17, 2018 at 15:55
  • issue still happens when i use org.geotools.kml.KML classes but in v22 it throw null pointer exception
    – Haider
    Commented Sep 17, 2018 at 17:20
  • according to my understanding this bug is fixed now but will be available with 21 release , is there any way i can use it with version 20 of geotools
    – Haider
    Commented Oct 9, 2018 at 7:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.