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?
Looking at the Esri example:
KML | ArcGIS API for JavaScript
It looks like the utility is hit when the KML layer is instantiated:
Instead of sending the "url" querystring param try sending it manually with an encoded KML string as kmlString="myKmlString..."
I tried sending it via the query string, but it is throwing an error on the return:
You may need to post to the service.
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 ); });
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?
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.
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);
}
});
}
});
});
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?