Is it possible to load KML from a file?

6396
7
05-12-2015 10:43 AM
DavidElies
New Contributor III

I noticed that the KML utility service at https://utility.arcgis.com/sharing/kml is able to convert a KML (XML) string.  Is it possible to use this ability to create a KMLLayer using the contents of a file rather than a URL?

0 Kudos
7 Replies
ChrisSmith7
Frequent Contributor

Looking at the Esri example:

KML | ArcGIS API for JavaScript

It looks like the utility is hit when the KML layer is instantiated:

http://utility.arcgis.com/sharing/kml?url=https%3A%2F%2Fdl.dropboxusercontent.com%2Fu%2F2654618%2Fkm...

Instead of sending the "url" querystring param try sending it manually with an encoded KML string as kmlString="myKmlString..."

ChrisSmith7
Frequent Contributor

I tried sending it via the query string, but it is throwing an error on the return:

http://utility.arcgis.com/sharing/kml?kmlString=%3Ckml%20xmlns%3D%22http%3A%2F%2Fwww.opengis.net%2Fk...

You may need to post to the service.

ChrisSmith7
Frequent Contributor

I pulled a KML from the Esri demo, then used an encoder (URL Decoder/Encoder ) to convert the XML into an encoded string. I had to adjust the beginning of the file to avoid the "content not allowed in prolog" error with the following header:

<?xml version="1.0" encoding="UTF-16" standalone="no"?>

This jQuery script should work! You just need to get the encoded string/file. Hope this helps!

$.post( "https://utility.arcgis.com/sharing/kml", { refresh: "false",url: "", kmlString: "%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-16%22%20standalone%3D%22no%22%3F%3E%0A%3Ckml%20xmlns%3D%22http%3A%2F%2Fwww.opengis.net%2Fkml%2F2.2%22%20xmlns%3Akml%3D%22http%3A%2F%2Fwww.opengis.net%2Fkml%2F2.2%22%3E%0A%3CDocument%3E%0A%09%3Cname%3EWY.kml%3C%2Fname%3E%0A%09%3CStyleMap%20id%3D%22msn_ylw-pushpin%22%3E%0A%09%09%3CPair%3E%0A%09%09%09%3Ckey%3Enormal%3C%2Fkey%3E%0A%09%09%09%3CstyleUrl%3E%23sn_ylw-pushpin%3C%2FstyleUrl%3E%0A%09%09%3C%2FPair%3E%0A%09%09%3CPair%3E%0A%09%09%09%3Ckey%3Ehighlight%3C%2Fkey%3E%0A%09%09%09%3CstyleUrl%3E%23sh_ylw-pushpin%3C%2FstyleUrl%3E%0A%09%09%3C%2FPair%3E%0A%09%3C%2FStyleMap%3E%0A%09%3CStyle%20id%3D%22sn_ylw-pushpin%22%3E%0A%09%09%3CLineStyle%3E%0A%09%09%09%3Ccolor%3Eff1378fa%3C%2Fcolor%3E%0A%09%09%3C%2FLineStyle%3E%0A%09%09%3CPolyStyle%3E%0A%09%09%09%3Ccolor%3E590e87ff%3C%2Fcolor%3E%0A%09%09%3C%2FPolyStyle%3E%0A%09%3C%2FStyle%3E%0A%09%3CStyle%20id%3D%22sh_ylw-pushpin%22%3E%0A%09%09%3CLineStyle%3E%0A%09%09%09%3Ccolor%3Eff1378fa%3C%2Fcolor%3E%0A%09%09%3C%2FLineStyle%3E%0A%09%09%3CPolyStyle%3E%0A%09%09%09%3Ccolor%3E590e87ff%3C%2Fcolor%3E%0A%09%09%3C%2FPolyStyle%3E%0A%09%3C%2FStyle%3E%0A%09%3CPlacemark%3E%0A%09%09%3Cname%3EWyoming(WY)%3C%2Fname%3E%0A%09%09%3CstyleUrl%3E%23msn_ylw-pushpin%3C%2FstyleUrl%3E%0A%09%09%3CPolygon%3E%0A%09%09%09%3CouterBoundaryIs%3E%0A%09%09%09%09%3CLinearRing%3E%0A%09%09%09%09%09%3Ccoordinates%3E%0A%09%09%09%09%09%09-111.0104571412223%2C41.0089819627255%2C0%20-104.030274231128%2C41.02828129140075%2C0%20-104.0319709660267%2C44.99724476991338%2C0%20-111.0393843561171%2C45.01103168687777%2C0%20-111.0104571412223%2C41.0089819627255%2C0%20%0A%09%09%09%09%09%3C%2Fcoordinates%3E%0A%09%09%09%09%3C%2FLinearRing%3E%0A%09%09%09%3C%2FouterBoundaryIs%3E%0A%09%09%3C%2FPolygon%3E%0A%09%3C%2FPlacemark%3E%0A%3C%2FDocument%3E%0A%3C%2Fkml%3E" })
  .done(function( data ) {
    alert( "Data Loaded: " + data );
  });
DavidElies
New Contributor III

Thanks for your efforts, Chris Smith​,

I was able to replicate your process, but I don't know how to get the returned data onto a map.  Is there a way to make the esri/layer/KMLLayer load this info?

ChrisSmith7
Frequent Contributor

According to the API:

Note: The KMLLayer uses a utility service from ArcGIS.com, therefore your kml/kmz must be publicly accessible on the internet. If your kml/kmz files are behind the firewall you will need to set the esriConfig.defaults.kmlService to your own utility service. (Requires Portal for ArcGIS).

KMLLayer | API Reference | ArcGIS API for JavaScript

So it seems possible - I'm not familiar with Portal, though.

UPDATE:

Lol, it's been a long day... I just realized the service you posted is on ArcGIS.com, so... if we can already get a KML response from local data sent to the service, then I don't see why we wouldn't be able to do this - maybe someone from Esri can chime in.

DavidElies
New Contributor III

I found that I was able to use the kmlstring parameter for the KMLLayer by subclassing the KMLLayer class and changing the internal esriRequest to use the kmlstring instead of the URL. This allows me to load KML files provided by the users. It required only replacing this one line in one internal function.  I just place the kmlString (the url-escaped contents of the KML file) into the options object in the constructor.

define([
  "dojo/_base/declare",
  "dojo/_base/json",
  "dojo/_base/lang",
  "esri/request",
  "esri/layers/KMLLayer"
], function ( declare, json, lang, esriRequest, KMLLayer) {
    return declare(KMLLayer, {
        _parseKml: function (map) {
            var that = this;
            this._fireUpdateStart();
            this._io = esriRequest({
                url: this.serviceUrl,
                content: {
                    //url: this._url.path + this._getQueryParameters(map),
                    kmlString: this._options.kmlString,
                    model: "simple",
                    folders: "",
                    refresh: this.loaded ? !0 : void 0,
                    outSR: json.toJson(this._outSR.toJson())
                },
                callbackParamName: "callback",
                load: function (response) {
                    that._io = null;
                    that._initLayer(response)
                },
                error: function (response) {
                    that._io = null;
                    var err = lang.mixin(Error(), response);
                    err.message = "Unable to load KML from text: " + that._options.kmlString + " " + (err.message || "");
                    that._fireUpdateEnd(err);
                    that.onError(err);
                }
            });
        }
    });
});
HarleyParks
New Contributor

was this with 3.x version? so, the KMLLayer is a little different with version 4.x. and I can't implement what you wrote directly... but interesting none the less.  the data returned from the kml service is what?  a feature layer?  

0 Kudos