ESRI.ArcGIS.Client.Toolkit.DataSources.Kml.KmlToFeatureDefinition.Convert C# (CSharp) Method

Convert() public method

Takes features in the KML element and converts them into equivalent features and adds them to the FeatureDefinition. Only the direct children of the KML element are converted.
public Convert ( KmlLayerContext context ) : FeatureDefinition
context KmlLayerContext Context containing the XElement with the KML definition to be converted.
return FeatureDefinition
        public FeatureDefinition Convert(KmlLayerContext context)
        {
            ICredentials credentials = context.Credentials;
            #if !SILVERLIGHT
            var clientCertificate = context.ClientCertificate;
            #endif
            XElement xElement = context.Element;
            XNamespace kmlNS = xElement.Name.Namespace;
            _waitHelper.Reset();

            // Remove any existing features so only those contained in the input KML element file are stored
            featureDefs.Clear();

            // Process the styles if they are not already known (the styles are shared by all folders/documents, so process them only once)
            if (context.Styles == null)
            {
                featureDefs.styles = new Dictionary<string, KMLStyle>();

                // Find all Style elements that have an ID and can thus be referenced by other styleURLs.
                IEnumerable<XElement> styles = xElement.Descendants().Where(e => e.Name.LocalName == "Style" && (string)e.Attribute("id") != null);
                foreach (XElement style in styles)
                {
                    KMLStyle kmlStyle = new KMLStyle();
                    GetStyle(style, kmlStyle);
                    featureDefs.AddStyle(kmlStyle.StyleId, kmlStyle);
                }

                // Find all StyleMap elements that have an ID and can thus be referenced by other styleURLs.
                IEnumerable<XElement> styleMaps = xElement.Descendants().Where(e => e.Name.LocalName == "StyleMap" && (string)e.Attribute("id") != null);
                foreach (XElement map in styleMaps)
                {
                    // A style map may need to download styles in other documents.
                    // Need to use asynchronous pattern.
                    GetStyleMapAsync(map, null, credentials
                                     , kmlStyle =>
                                       	{
                                       		if (kmlStyle != null)
                                       			featureDefs.AddStyle(kmlStyle.StyleId, kmlStyle);
                                       	}
            #if !SILVERLIGHT
            , clientCertificate
            #endif
            );
                }

                // Wait for getting all styles before creating the feature definition
                _waitHelper.Wait();
            }
            else
            {
                foreach (var style in context.Styles)
                    featureDefs.AddStyle(style.Key, style.Value);
            }

            // Process the optional NetworkLinkControl
            XElement networkLinkControl = xElement.Element(kmlNS + "NetworkLinkControl");
            if (networkLinkControl != null)
            {
                featureDefs.networkLinkControl = new NetworkLinkControl();
                XElement minRefreshPeriod = networkLinkControl.Element(kmlNS + "minRefreshPeriod");
                if (minRefreshPeriod != null)
                    featureDefs.networkLinkControl.MinRefreshPeriod = GetDoubleValue(minRefreshPeriod);
            }

            // Find the containers which will be represented by a sublayer i.e Document/Folder/NetworkLink
            foreach (XElement container in xElement.Elements().Where(element => element.Name.LocalName == "Folder" || element.Name.LocalName == "Document" || element.Name.LocalName == "NetworkLink"))
            {
                ContainerInfo containerInfo = new ContainerInfo
                                         	{
                                         		Element = container,
                                         		Url = null, // only for networklink
                                         		Visible = true,
                                         		AtomAuthor = context.AtomAuthor, // Use parent value by default
                                         		AtomHref = context.AtomHref  // Use parent value by default
                                         	};

                XNamespace kmlContainerNS = container.Name.Namespace;
                if (container.Name.LocalName == "NetworkLink")
                {
                    string hrefValue = "";
                    string composite = "";
                    string layerids = "";

                    // Link takes precedence over Url from KML version 2.1 and later:
                    XElement url = container.Element(kmlContainerNS + "Link") ?? container.Element(kmlContainerNS + "Url");
                    if (url != null)
                    {
                        XElement href = url.Element(kmlContainerNS + "href");
                        if (href != null)
                        {
                            hrefValue = href.Value;
                        }

                        // This next section is to parse special elements that only occur when an ArcGIS Server KML
                        // is to be processed.
                        XElement view = url.Element(kmlContainerNS + "viewFormat");
                        if (view != null)
                        {
                            int begIdx = view.Value.IndexOf("Composite");
                            if (begIdx != -1)
                            {
                                int endIdx = view.Value.IndexOf("&", begIdx);
                                if (endIdx != -1)
                                    composite = view.Value.Substring(begIdx, endIdx - begIdx);
                            }

                            begIdx = view.Value.IndexOf("LayerIDs");
                            if (begIdx != -1)
                            {
                                int endIdx = view.Value.IndexOf("&", begIdx);
                                if (endIdx != -1)
                                    layerids = view.Value.Substring(begIdx, endIdx - begIdx);
                            }
                        }

                        // If network link URL is successfully extracted, then add to container list
                        if (!String.IsNullOrEmpty(hrefValue))
                        {
                            // extract refreshInterval
                            XElement refreshMode = url.Element(kmlContainerNS + "refreshMode");
                            if (refreshMode != null && refreshMode.Value == "onInterval")
                            {
                                XElement refreshInterval = url.Element(kmlContainerNS + "refreshInterval");
                                if (refreshInterval != null)
                                    containerInfo.RefreshInterval = GetDoubleValue(refreshInterval);
                                else
                                    containerInfo.RefreshInterval = 4; // default value
                            }

                            XElement viewRefreshMode = url.Element(kmlContainerNS + "viewRefreshMode");
                            if (viewRefreshMode != null)
                            {
                                ViewRefreshMode viewRefreshModeEnum;

                                try // Enum.TryParse doesn't exist in 3.5
                                {
                                    viewRefreshModeEnum = (ViewRefreshMode)Enum.Parse(typeof(ViewRefreshMode), viewRefreshMode.Value, true);
                                    containerInfo.ViewRefreshMode = viewRefreshModeEnum;
                                }
                                catch{}
                            }

                            // the following values are for processing specialized ArcGIS Server KML links
                            // generated from REST endpoints.
                            if (!String.IsNullOrEmpty(composite))
                                hrefValue += "?" + composite;

                            if (!String.IsNullOrEmpty(layerids))
                            {
                                if (!String.IsNullOrEmpty(hrefValue))
                                    hrefValue += "&" + layerids;
                                else
                                    hrefValue += "?" + layerids;
                            }
                            containerInfo.Url = hrefValue;

                        }
                        else
                            containerInfo = null; // Link without href. Should not happen. Skip it.
                    }
                    else
                        containerInfo = null; // NetworkLink without Link/Url. Should not happen. Skip it.
                }
                else
                {
                    // Folder or Document XElement
                    XElement linkElement = container.Elements(atomNS + "link").Where(element => element.HasAttributes).FirstOrDefault();
                    if (linkElement != null)
                    {
                        // Overwrite global default value only upon successful extraction from element
                        string tempHref = GetAtomHref(linkElement);
                        if (!String.IsNullOrEmpty(tempHref))
                            containerInfo.AtomHref = new Uri(tempHref);
                    }

                    XElement authorElement = container.Element(atomNS + "author");
                    if (authorElement != null)
                    {
                        // Overwrite global default value only upon successful extraction from element
                        string tempAuthor = GetAtomAuthor(authorElement);
                        if (!String.IsNullOrEmpty(tempAuthor))
                            containerInfo.AtomAuthor = tempAuthor;
                    }
                }

                if (containerInfo != null)
                {
                    XElement visibilityElement = container.Element(kmlContainerNS + "visibility");
                    if (visibilityElement != null)
                    {
                        containerInfo.Visible = GetBooleanValue(visibilityElement);
                    }

                    XElement nameElement = container.Element(kmlContainerNS + "name");
                    if (nameElement != null)
                    {
                        containerInfo.Name = nameElement.Value.Trim();
                    }

                    containerInfo.RegionInfo = ExtractRegion(container);

                    // Look for a listItemType element that can be set to 'checkHideChildren' to prevent cildren to be seen in the legend
                    XElement listItemTypeElement = container.XPathSelectElement("Style/ListStyle/listItemType", kmlContainerNS);
                    if (listItemTypeElement != null)
                    {
                        if (listItemTypeElement.Value == "checkHideChildren")
                            containerInfo.HideChildren = true;
                    }

                    if (container.HasAttributes && container.Attribute(KmlLayer.FolderIdAttributeName) != null)
                    {
                        containerInfo.FolderId = (int)container.Attribute(KmlLayer.FolderIdAttributeName);
                    }

                    containerInfo.TimeExtent = ExtractTimeExtent(container);
                    featureDefs.AddContainer(containerInfo);
                }
            }

            // Process all children placemarks or groundoverlays
            foreach (XElement element in xElement.Elements().Where(element => element.Name == kmlNS + "Placemark" || element.Name == kmlNS + "GroundOverlay" ))
            {
                // Establish baseline style if a "styleUrl" setting is present
                XElement styleElement = element.Element(kmlNS + "styleUrl");
                if (styleElement != null)
                {
                    // get the style asynchronously and create the feature definition as soon as the style is there
                    XElement featureElement = element;
                    GetStyleUrlAsync(styleElement.Value, null, credentials, kmlStyle => CreateFeatureDefinition(kmlStyle, featureElement, null, context)
            #if !SILVERLIGHT
            , clientCertificate
            #endif
            );
                }
                else
                {
                    // Create feature definition synchronously using default KML style, meta data and placemark information
                    CreateFeatureDefinition(null, element, null, context);
                }
            }

            // Get the name of the XElement
            XElement nameXElement = xElement.Element(kmlNS + "name");
            if (nameXElement != null && string.IsNullOrEmpty(featureDefs.name))
            {
                featureDefs.name = nameXElement.Value.Trim();
            }

            // At this point, some inner styles are possibly on the way to being downloaded and so the feature definitions are not created yet
            // Wait for all downloads to be sure all feature definitions are created before terminating the background worker
            _waitHelper.Wait();

            int folderId = 0;
            if (xElement.HasAttributes && xElement.Attribute(KmlLayer.FolderIdAttributeName) != null)
            {
                folderId = (int)xElement.Attribute(KmlLayer.FolderIdAttributeName);
            }

            ContainerInfo singleContainer = featureDefs.containers.Count() == 1 ? featureDefs.containers.First() : null;
            if (!featureDefs.groundOverlays.Any() && !featureDefs.placemarks.Any() && singleContainer != null && folderId == 0
                && (singleContainer.RegionInfo == null || !singleContainer.RegionInfo.HasLods())
                && string.IsNullOrEmpty(singleContainer.Url) && singleContainer.TimeExtent ==  null)
            {
                // Avoid useless level when there is no groundoverlay, no placemark and only one folder or document at the root level without any lod info
                Dictionary<string, KMLStyle> styles = featureDefs.styles.ToDictionary(style => style.Key, style => style.Value);

                KmlLayerContext childContext = new KmlLayerContext
                                               	{
                                               		Element = singleContainer.Element, // The XElement that the KML layer has to process
                                               		Styles = styles,
                                               		Images = context.Images,
                                               		AtomAuthor = singleContainer.AtomAuthor,
                                               		AtomHref = singleContainer.AtomHref,
                                               		Credentials = context.Credentials
            #if !SILVERLIGHT
                                                    ,ClientCertificate = context.ClientCertificate
            #endif
                                               	};

                featureDefs.hasRootContainer = true;
                return Convert(childContext);
            }

            return featureDefs;
        }

Usage Example

示例#1
0
        private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            // Instantiate KML To Graphics converter engine, and
            // feed XDocument. Store resulting feature definition in the result object of the event
            // arguments so it is transmitted to the Work Completed handler for subsequent processing.
            KmlToFeatureDefinition ktg = new KmlToFeatureDefinition(GetBaseUri(), ProxyUrl);

            e.Result = ktg.Convert((KmlLayerContext)e.Argument);
        }