Index: src/Common/SharpMap/Web/Wms/Client.cs =================================================================== diff -u -r8f6ae890fed8e8eae3a32f9c0498a10f82e0ddf9 -r5fc71a385897af92ccb092f2f969b5709afab85a --- src/Common/SharpMap/Web/Wms/Client.cs (.../Client.cs) (revision 8f6ae890fed8e8eae3a32f9c0498a10f82e0ddf9) +++ src/Common/SharpMap/Web/Wms/Client.cs (.../Client.cs) (revision 5fc71a385897af92ccb092f2f969b5709afab85a) @@ -1,496 +1,534 @@ using System; using System.Collections.ObjectModel; +using System.Drawing; +using System.Globalization; +using System.IO; +using System.Net; using System.Text; using System.Xml; using GeoAPI.Geometries; +using SharpMap.Converters.Geometries; namespace SharpMap.Web.Wms { - /// - /// Class for requesting and parsing a WMS servers capabilities - /// - [Serializable] - public class Client - { - private XmlNamespaceManager nsmgr; + /// + /// Class for requesting and parsing a WMS servers capabilities + /// + [Serializable] + public class Client + { + private XmlNamespaceManager nsmgr; - #region WMS Data structures + /// + /// Initalizes WMS server and parses the Capabilities request + /// + /// URL of wms server + public Client(string url) + : this(url, null) {} - /// - /// Structure for holding information about a WMS Layer - /// - public struct WmsServerLayer - { - /// - /// Layer title - /// - public string Title; - /// - /// Unique name of this layer used for requesting layer - /// - public string Name; - /// - /// Abstract - /// - public string Abstract; - /// - /// Specifies whether this layer is queryable using GetFeatureInfo requests - /// - public bool Queryable; - /// - /// Keywords - /// - public string[] Keywords; - /// - /// List of styles supported by layer - /// - public WmsLayerStyle[] Style; - /// - /// Coordinate Reference Systems supported by layer - /// - public string[] CRS; - /// - /// Collection of child layers - /// - public WmsServerLayer[] ChildLayers; - /// - /// Latitudal/longitudal extent of this layer - /// - public IEnvelope LatLonBoundingBox; - } + /// + /// Initalizes WMS server and parses the Capabilities request + /// + /// URL of wms server + /// Proxy to use + public Client(string url, WebProxy proxy) + { + StringBuilder strReq = new StringBuilder(url); + if (!url.Contains("?")) + { + strReq.Append("?"); + } + if (!strReq.ToString().EndsWith("&") && !strReq.ToString().EndsWith("?")) + { + strReq.Append("&"); + } + if (!url.ToLower().Contains("service=wms")) + { + strReq.AppendFormat("SERVICE=WMS&"); + } + if (!url.ToLower().Contains("request=getcapabilities")) + { + strReq.AppendFormat("REQUEST=GetCapabilities&"); + } - /// - /// Structure for storing information about a WMS Layer Style - /// - public struct WmsLayerStyle - { - /// - /// Name - /// - public string Name; - /// - /// Title - /// - public string Title; - /// - /// Abstract - /// - public string Abstract; - /// - /// Legend - /// - public WmsStyleLegend LegendUrl; - /// - /// Style Sheet Url - /// - public WmsOnlineResource StyleSheetUrl; - } + XmlDocument xml = GetRemoteXml(strReq.ToString(), proxy); + ParseCapabilities(xml); + } - /// - /// Structure for storing WMS Legend information - /// - public struct WmsStyleLegend - { - /// - /// Online resource for legend style - /// - public WmsOnlineResource OnlineResource; - /// - /// Size of legend - /// - public System.Drawing.Size Size; - } + /// + /// Downloads servicedescription from WMS service + /// + /// XmlDocument from Url. Null if Url is empty or inproper XmlDocument + private XmlDocument GetRemoteXml(string Url, WebProxy proxy) + { + try + { + WebRequest myRequest = WebRequest.Create(Url); + if (proxy != null) + { + myRequest.Proxy = proxy; + } + WebResponse myResponse = myRequest.GetResponse(); + Stream stream = myResponse.GetResponseStream(); + XmlTextReader r = new XmlTextReader(Url, stream); + XmlDocument doc = new XmlDocument(); + doc.Load(r); + stream.Close(); + nsmgr = new XmlNamespaceManager(doc.NameTable); + return doc; + } + catch (Exception ex) + { + throw new ApplicationException("Could now download capabilities", ex); + } + } - /// - /// Structure for storing info on an Online Resource - /// - public struct WmsOnlineResource - { - /// - /// Type of online resource (Ex. request method 'Get' or 'Post') - /// - public string Type; - /// - /// URI of online resource - /// - public string OnlineResource; - } + /// + /// Parses a servicedescription and stores the data in the ServiceDescription property + /// + /// XmlDocument containing a valid Service Description + private void ParseCapabilities(XmlDocument doc) + { + if (doc.DocumentElement.Attributes["version"] != null) + { + WmsVersion = doc.DocumentElement.Attributes["version"].Value; + if (WmsVersion != "1.0.0" && WmsVersion != "1.1.0" && WmsVersion != "1.1.1" && WmsVersion != "1.3.0") + { + throw new ApplicationException("WMS Version " + WmsVersion + " not supported"); + } - #endregion + nsmgr.AddNamespace(String.Empty, "http://www.opengis.net/wms"); + if (WmsVersion == "1.3.0") + { + nsmgr.AddNamespace("sm", "http://www.opengis.net/wms"); + } + else + { + nsmgr.AddNamespace("sm", ""); + } + nsmgr.AddNamespace("xlink", "http://www.w3.org/1999/xlink"); + nsmgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); + } + else + { + throw (new ApplicationException("No service version number found!")); + } - #region Properties + XmlNode xnService = doc.DocumentElement.SelectSingleNode("sm:Service", nsmgr); + XmlNode xnCapability = doc.DocumentElement.SelectSingleNode("sm:Capability", nsmgr); + if (xnService != null) + { + ParseServiceDescription(xnService); + } + else + { + throw (new ApplicationException("No service tag found!")); + } - private Capabilities.WmsServiceDescription _ServiceDescription; + if (xnCapability != null) + { + ParseCapability(xnCapability); + } + else + { + throw (new ApplicationException("No capability tag found!")); + } + } - /// - /// Gets the service description - /// - public Capabilities.WmsServiceDescription ServiceDescription - { - get { return _ServiceDescription; } - } - private string _WmsVersion; + /// + /// Parses service description node + /// + /// + private void ParseServiceDescription(XmlNode xnlServiceDescription) + { + XmlNode node = xnlServiceDescription.SelectSingleNode("sm:Title", nsmgr); + _ServiceDescription.Title = (node != null ? node.InnerText : null); + node = xnlServiceDescription.SelectSingleNode("sm:OnlineResource/@xlink:href", nsmgr); + _ServiceDescription.OnlineResource = (node != null ? node.InnerText : null); + node = xnlServiceDescription.SelectSingleNode("sm:Abstract", nsmgr); + _ServiceDescription.Abstract = (node != null ? node.InnerText : null); + node = xnlServiceDescription.SelectSingleNode("sm:Fees", nsmgr); + _ServiceDescription.Fees = (node != null ? node.InnerText : null); + node = xnlServiceDescription.SelectSingleNode("sm:AccessConstraints", nsmgr); + _ServiceDescription.AccessConstraints = (node != null ? node.InnerText : null); - /// - /// Gets the version of the WMS server (ex. "1.3.0") - /// - public string WmsVersion - { - get { return _WmsVersion; } - } + XmlNodeList xnlKeywords = xnlServiceDescription.SelectNodes("sm:KeywordList/sm:Keyword", nsmgr); + if (xnlKeywords != null) + { + _ServiceDescription.Keywords = new string[xnlKeywords.Count]; + for (int i = 0; i < xnlKeywords.Count; i++) + { + ServiceDescription.Keywords[i] = xnlKeywords[i].InnerText; + } + } + //Contact information + _ServiceDescription.ContactInformation = new Capabilities.WmsContactInformation(); + node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactAddress/sm:Address", nsmgr); + _ServiceDescription.ContactInformation.Address.Address = (node != null ? node.InnerText : null); + node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactAddress/sm:AddressType", nsmgr); + _ServiceDescription.ContactInformation.Address.AddressType = (node != null ? node.InnerText : null); + node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactAddress/sm:City", nsmgr); + _ServiceDescription.ContactInformation.Address.City = (node != null ? node.InnerText : null); + node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactAddress/sm:Country", nsmgr); + _ServiceDescription.ContactInformation.Address.Country = (node != null ? node.InnerText : null); + node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactAddress/sm:PostCode", nsmgr); + _ServiceDescription.ContactInformation.Address.PostCode = (node != null ? node.InnerText : null); + node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactElectronicMailAddress", nsmgr); + _ServiceDescription.ContactInformation.Address.StateOrProvince = (node != null ? node.InnerText : null); + node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactElectronicMailAddress", nsmgr); + _ServiceDescription.ContactInformation.ElectronicMailAddress = (node != null ? node.InnerText : null); + node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactFacsimileTelephone", nsmgr); + _ServiceDescription.ContactInformation.FacsimileTelephone = (node != null ? node.InnerText : null); + node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactPersonPrimary/sm:ContactOrganisation", nsmgr); + _ServiceDescription.ContactInformation.PersonPrimary.Organisation = (node != null ? node.InnerText : null); + node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactPersonPrimary/sm:ContactPerson", nsmgr); + _ServiceDescription.ContactInformation.PersonPrimary.Person = (node != null ? node.InnerText : null); + node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactVoiceTelephone", nsmgr); + _ServiceDescription.ContactInformation.VoiceTelephone = (node != null ? node.InnerText : null); + } - private Collection _GetMapOutputFormats; + /// + /// Parses capability node + /// + /// + private void ParseCapability(XmlNode xnCapability) + { + XmlNode xnRequest = xnCapability.SelectSingleNode("sm:Request", nsmgr); + if (xnRequest == null) + { + throw (new Exception("Request parameter not specified in Service Description")); + } + ParseRequest(xnRequest); + XmlNode xnLayer = xnCapability.SelectSingleNode("sm:Layer", nsmgr); + if (xnLayer == null) + { + throw (new Exception("No layer tag found in Service Description")); + } + Layer = ParseLayer(xnLayer); - /// - /// Gets a list of available image mime type formats - /// - public Collection GetMapOutputFormats - { - get { return _GetMapOutputFormats; } - } + XmlNode xnException = xnCapability.SelectSingleNode("sm:Exception", nsmgr); + if (xnException != null) + { + ParseExceptions(xnException); + } + } - private string[] _ExceptionFormats; + /// + /// Parses valid exceptions + /// + /// + private void ParseExceptions(XmlNode xnlExceptionNode) + { + XmlNodeList xnlFormats = xnlExceptionNode.SelectNodes("sm:Format", nsmgr); + if (xnlFormats != null) + { + ExceptionFormats = new string[xnlFormats.Count]; + for (int i = 0; i < xnlFormats.Count; i++) + { + ExceptionFormats[i] = xnlFormats[i].InnerText; + } + } + } - /// - /// Gets a list of available exception mime type formats - /// - public string[] ExceptionFormats - { - get { return _ExceptionFormats; } - } + /// + /// Parses request node + /// + /// + private void ParseRequest(XmlNode xmlRequestNode) + { + XmlNode xnGetMap = xmlRequestNode.SelectSingleNode("sm:GetMap", nsmgr); + ParseGetMapRequest(xnGetMap); + //TODO: + //XmlNode xnGetFeatureInfo = xmlRequestNodes.SelectSingleNode("sm:GetFeatureInfo", nsmgr); + //XmlNode xnCapa = xmlRequestNodes.SelectSingleNode("sm:GetCapabilities", nsmgr); <-- We don't really need this do we? + } - private WmsOnlineResource[] _GetMapRequests; + /// + /// Parses GetMap request nodes + /// + /// + private void ParseGetMapRequest(XmlNode GetMapRequestNodes) + { + XmlNode xnlHttp = GetMapRequestNodes.SelectSingleNode("sm:DCPType/sm:HTTP", nsmgr); + if (xnlHttp != null && xnlHttp.HasChildNodes) + { + GetMapRequests = new WmsOnlineResource[xnlHttp.ChildNodes.Count]; + for (int i = 0; i < xnlHttp.ChildNodes.Count; i++) + { + WmsOnlineResource wor = new WmsOnlineResource(); + wor.Type = xnlHttp.ChildNodes[i].Name; + wor.OnlineResource = xnlHttp.ChildNodes[i].SelectSingleNode("sm:OnlineResource", nsmgr).Attributes["xlink:href"].InnerText; + GetMapRequests[i] = wor; + } + } + XmlNodeList xnlFormats = GetMapRequestNodes.SelectNodes("sm:Format", nsmgr); + //_GetMapOutputFormats = new Collection(xnlFormats.Count); + GetMapOutputFormats = new Collection(); + for (int i = 0; i < xnlFormats.Count; i++) + { + GetMapOutputFormats.Add(xnlFormats[i].InnerText); + } + } - /// - /// Gets the available GetMap request methods and Online Resource URI - /// - public WmsOnlineResource[] GetMapRequests - { - get { return _GetMapRequests; } - } + /// + /// Iterates through the layer nodes recursively + /// + /// + /// + private WmsServerLayer ParseLayer(XmlNode xmlLayer) + { + WmsServerLayer layer = new WmsServerLayer(); + XmlNode node = xmlLayer.SelectSingleNode("sm:Name", nsmgr); + layer.Name = (node != null ? node.InnerText : null); + node = xmlLayer.SelectSingleNode("sm:Title", nsmgr); + layer.Title = (node != null ? node.InnerText : null); + if (string.IsNullOrEmpty(layer.Name)) + { + layer.Name = layer.Title; + } + node = xmlLayer.SelectSingleNode("sm:Abstract", nsmgr); + layer.Abstract = (node != null ? node.InnerText : null); + XmlAttribute attr = xmlLayer.Attributes["queryable"]; + layer.Queryable = (attr != null && attr.InnerText == "1"); - private WmsServerLayer _Layer; - /// - /// Gets the hiarchial layer structure - /// - public WmsServerLayer Layer - { - get { return _Layer; } - } - #endregion + XmlNodeList xnlKeywords = xmlLayer.SelectNodes("sm:KeywordList/sm:Keyword", nsmgr); + if (xnlKeywords != null) + { + layer.Keywords = new string[xnlKeywords.Count]; + for (int i = 0; i < xnlKeywords.Count; i++) + { + layer.Keywords[i] = xnlKeywords[i].InnerText; + } + } + XmlNodeList xnlCrs = xmlLayer.SelectNodes("sm:CRS", nsmgr); + if (xnlCrs != null) + { + layer.CRS = new string[xnlCrs.Count]; + for (int i = 0; i < xnlCrs.Count; i++) + { + layer.CRS[i] = xnlCrs[i].InnerText; + } + } + XmlNodeList xnlStyle = xmlLayer.SelectNodes("sm:Style", nsmgr); + if (xnlStyle != null) + { + layer.Style = new WmsLayerStyle[xnlStyle.Count]; + for (int i = 0; i < xnlStyle.Count; i++) + { + node = xnlStyle[i].SelectSingleNode("sm:Name", nsmgr); + layer.Style[i].Name = (node != null ? node.InnerText : null); + node = xnlStyle[i].SelectSingleNode("sm:Title", nsmgr); + layer.Style[i].Title = (node != null ? node.InnerText : null); + node = xnlStyle[i].SelectSingleNode("sm:Abstract", nsmgr); + layer.Style[i].Abstract = (node != null ? node.InnerText : null); + node = xnlStyle[i].SelectSingleNode("sm:LegendUrl", nsmgr); + if (node != null) + { + layer.Style[i].LegendUrl = new WmsStyleLegend(); + layer.Style[i].LegendUrl.Size = new Size( + int.Parse(node.Attributes["width"].InnerText), int.Parse(node.Attributes["height"].InnerText)); + layer.Style[i].LegendUrl.OnlineResource.OnlineResource = node.SelectSingleNode("sm:OnlineResource", nsmgr).Attributes["xlink:href"].InnerText; + layer.Style[i].LegendUrl.OnlineResource.Type = node.SelectSingleNode("sm:Format", nsmgr).InnerText; + } + node = xnlStyle[i].SelectSingleNode("sm:StyleSheetURL", nsmgr); + if (node != null) + { + layer.Style[i].StyleSheetUrl = new WmsOnlineResource(); + layer.Style[i].StyleSheetUrl.OnlineResource = node.SelectSingleNode("sm:OnlineResource", nsmgr).Attributes["xlink:href"].InnerText; + //layer.Style[i].StyleSheetUrl.OnlineResource = node.SelectSingleNode("sm:Format", nsmgr).InnerText; + } + } + } + XmlNodeList xnlLayers = xmlLayer.SelectNodes("sm:Layer", nsmgr); + if (xnlLayers != null) + { + layer.ChildLayers = new WmsServerLayer[xnlLayers.Count]; + for (int i = 0; i < xnlLayers.Count; i++) + { + layer.ChildLayers[i] = ParseLayer(xnlLayers[i]); + } + } + node = xmlLayer.SelectSingleNode("sm:LatLonBoundingBox", nsmgr); + if (node == null) + { + node = xmlLayer.SelectSingleNode("sm:BoundingBox", nsmgr); + } + if (node != null) + { + double minx = 0; + double miny = 0; + double maxx = 0; + double maxy = 0; + if (!double.TryParse(node.Attributes["minx"].Value, NumberStyles.Any, Map.numberFormat_EnUS, out minx) & + !double.TryParse(node.Attributes["miny"].Value, NumberStyles.Any, Map.numberFormat_EnUS, out miny) & + !double.TryParse(node.Attributes["maxx"].Value, NumberStyles.Any, Map.numberFormat_EnUS, out maxx) & + !double.TryParse(node.Attributes["maxy"].Value, NumberStyles.Any, Map.numberFormat_EnUS, out maxy)) + { + throw new ArgumentException("Invalid LatLonBoundingBox on layer '" + layer.Name + "'"); + } + layer.LatLonBoundingBox = GeometryFactory.CreateEnvelope(minx, maxx, miny, maxy); + } + return layer; + } - /// - /// Initalizes WMS server and parses the Capabilities request - /// - /// URL of wms server - public Client(string url) - : this(url, null) - { - } + #region WMS Data structures - /// - /// Initalizes WMS server and parses the Capabilities request - /// - /// URL of wms server - /// Proxy to use - public Client(string url, System.Net.WebProxy proxy) - { - System.Text.StringBuilder strReq = new StringBuilder(url); - if (!url.Contains("?")) - strReq.Append("?"); - if (!strReq.ToString().EndsWith("&") && !strReq.ToString().EndsWith("?")) - strReq.Append("&"); - if(!url.ToLower().Contains("service=wms")) - strReq.AppendFormat("SERVICE=WMS&"); - if (!url.ToLower().Contains("request=getcapabilities")) - strReq.AppendFormat("REQUEST=GetCapabilities&"); + /// + /// Structure for holding information about a WMS Layer + /// + public struct WmsServerLayer + { + /// + /// Layer title + /// + public string Title; - XmlDocument xml = GetRemoteXml(strReq.ToString(), proxy); - ParseCapabilities(xml); - } + /// + /// Unique name of this layer used for requesting layer + /// + public string Name; + /// + /// Abstract + /// + public string Abstract; - /// - /// Downloads servicedescription from WMS service - /// - /// XmlDocument from Url. Null if Url is empty or inproper XmlDocument - private XmlDocument GetRemoteXml(string Url, System.Net.WebProxy proxy) - { - try - { - System.Net.WebRequest myRequest = System.Net.WebRequest.Create(Url); - if (proxy != null) myRequest.Proxy = proxy; - System.Net.WebResponse myResponse = myRequest.GetResponse(); - System.IO.Stream stream = myResponse.GetResponseStream(); - XmlTextReader r = new XmlTextReader(Url, stream); - XmlDocument doc = new XmlDocument(); - doc.Load(r); - stream.Close(); - nsmgr = new XmlNamespaceManager(doc.NameTable); - return doc; - } - catch (System.Exception ex) - { - throw new ApplicationException("Could now download capabilities", ex); - } - } + /// + /// Specifies whether this layer is queryable using GetFeatureInfo requests + /// + public bool Queryable; + /// + /// Keywords + /// + public string[] Keywords; - /// - /// Parses a servicedescription and stores the data in the ServiceDescription property - /// - /// XmlDocument containing a valid Service Description - private void ParseCapabilities(XmlDocument doc) - { - if (doc.DocumentElement.Attributes["version"] != null) - { - _WmsVersion = doc.DocumentElement.Attributes["version"].Value; - if (_WmsVersion != "1.0.0" && _WmsVersion != "1.1.0" && _WmsVersion != "1.1.1" && _WmsVersion != "1.3.0") - throw new ApplicationException("WMS Version " + _WmsVersion + " not supported"); + /// + /// List of styles supported by layer + /// + public WmsLayerStyle[] Style; - nsmgr.AddNamespace(String.Empty, "http://www.opengis.net/wms"); - if (_WmsVersion == "1.3.0") - { - nsmgr.AddNamespace("sm", "http://www.opengis.net/wms"); - } - else - nsmgr.AddNamespace("sm", ""); - nsmgr.AddNamespace("xlink", "http://www.w3.org/1999/xlink"); - nsmgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); - } - else - throw (new ApplicationException("No service version number found!")); + /// + /// Coordinate Reference Systems supported by layer + /// + public string[] CRS; - XmlNode xnService = doc.DocumentElement.SelectSingleNode("sm:Service", nsmgr); - XmlNode xnCapability = doc.DocumentElement.SelectSingleNode("sm:Capability", nsmgr); - if (xnService != null) - ParseServiceDescription(xnService); - else - throw (new ApplicationException("No service tag found!")); + /// + /// Collection of child layers + /// + public WmsServerLayer[] ChildLayers; + /// + /// Latitudal/longitudal extent of this layer + /// + public IEnvelope LatLonBoundingBox; + } + /// + /// Structure for storing information about a WMS Layer Style + /// + public struct WmsLayerStyle + { + /// + /// Name + /// + public string Name; - if (xnCapability != null) - ParseCapability(xnCapability); - else - throw (new ApplicationException("No capability tag found!")); - } + /// + /// Title + /// + public string Title; - /// - /// Parses service description node - /// - /// - private void ParseServiceDescription(XmlNode xnlServiceDescription) - { - XmlNode node = xnlServiceDescription.SelectSingleNode("sm:Title", nsmgr); - _ServiceDescription.Title = (node != null ? node.InnerText : null); - node = xnlServiceDescription.SelectSingleNode("sm:OnlineResource/@xlink:href", nsmgr); - _ServiceDescription.OnlineResource = (node != null ? node.InnerText : null); - node = xnlServiceDescription.SelectSingleNode("sm:Abstract", nsmgr); - _ServiceDescription.Abstract = (node != null ? node.InnerText : null); - node = xnlServiceDescription.SelectSingleNode("sm:Fees", nsmgr); - _ServiceDescription.Fees = (node != null ? node.InnerText : null); - node = xnlServiceDescription.SelectSingleNode("sm:AccessConstraints", nsmgr); - _ServiceDescription.AccessConstraints = (node != null ? node.InnerText : null); + /// + /// Abstract + /// + public string Abstract; - XmlNodeList xnlKeywords = xnlServiceDescription.SelectNodes("sm:KeywordList/sm:Keyword", nsmgr); - if (xnlKeywords != null) - { - _ServiceDescription.Keywords = new string[xnlKeywords.Count]; - for (int i = 0; i < xnlKeywords.Count; i++) - ServiceDescription.Keywords[i] = xnlKeywords[i].InnerText; - } - //Contact information - _ServiceDescription.ContactInformation = new Capabilities.WmsContactInformation(); - node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactAddress/sm:Address", nsmgr); - _ServiceDescription.ContactInformation.Address.Address = (node != null ? node.InnerText : null); - node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactAddress/sm:AddressType", nsmgr); - _ServiceDescription.ContactInformation.Address.AddressType = (node != null ? node.InnerText : null); - node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactAddress/sm:City", nsmgr); - _ServiceDescription.ContactInformation.Address.City = (node != null ? node.InnerText : null); - node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactAddress/sm:Country", nsmgr); - _ServiceDescription.ContactInformation.Address.Country = (node != null ? node.InnerText : null); - node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactAddress/sm:PostCode", nsmgr); - _ServiceDescription.ContactInformation.Address.PostCode = (node != null ? node.InnerText : null); - node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactElectronicMailAddress", nsmgr); - _ServiceDescription.ContactInformation.Address.StateOrProvince = (node != null ? node.InnerText : null); - node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactElectronicMailAddress", nsmgr); - _ServiceDescription.ContactInformation.ElectronicMailAddress = (node != null ? node.InnerText : null); - node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactFacsimileTelephone", nsmgr); - _ServiceDescription.ContactInformation.FacsimileTelephone = (node != null ? node.InnerText : null); - node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactPersonPrimary/sm:ContactOrganisation", nsmgr); - _ServiceDescription.ContactInformation.PersonPrimary.Organisation = (node != null ? node.InnerText : null); - node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactPersonPrimary/sm:ContactPerson", nsmgr); - _ServiceDescription.ContactInformation.PersonPrimary.Person = (node != null ? node.InnerText : null); - node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactVoiceTelephone", nsmgr); - _ServiceDescription.ContactInformation.VoiceTelephone = (node != null ? node.InnerText : null); - } - - /// - /// Parses capability node - /// - /// - private void ParseCapability(XmlNode xnCapability) - { - XmlNode xnRequest = xnCapability.SelectSingleNode("sm:Request", nsmgr); - if (xnRequest == null) - throw (new System.Exception("Request parameter not specified in Service Description")); - ParseRequest(xnRequest); - XmlNode xnLayer = xnCapability.SelectSingleNode("sm:Layer", nsmgr); - if (xnLayer == null) - throw (new System.Exception("No layer tag found in Service Description")); - _Layer = ParseLayer(xnLayer); - - XmlNode xnException = xnCapability.SelectSingleNode("sm:Exception", nsmgr); - if (xnException != null) - ParseExceptions(xnException); - } + /// + /// Legend + /// + public WmsStyleLegend LegendUrl; - /// - /// Parses valid exceptions - /// - /// - private void ParseExceptions(XmlNode xnlExceptionNode) - { - XmlNodeList xnlFormats = xnlExceptionNode.SelectNodes("sm:Format", nsmgr); - if (xnlFormats != null) - { - _ExceptionFormats = new string[xnlFormats.Count]; - for (int i = 0; i < xnlFormats.Count; i++) - { - _ExceptionFormats[i] = xnlFormats[i].InnerText; - } - } - } + /// + /// Style Sheet Url + /// + public WmsOnlineResource StyleSheetUrl; + } - /// - /// Parses request node - /// - /// - private void ParseRequest(XmlNode xmlRequestNode) - { - XmlNode xnGetMap = xmlRequestNode.SelectSingleNode("sm:GetMap",nsmgr); - ParseGetMapRequest(xnGetMap); - //TODO: - //XmlNode xnGetFeatureInfo = xmlRequestNodes.SelectSingleNode("sm:GetFeatureInfo", nsmgr); - //XmlNode xnCapa = xmlRequestNodes.SelectSingleNode("sm:GetCapabilities", nsmgr); <-- We don't really need this do we? - } + /// + /// Structure for storing WMS Legend information + /// + public struct WmsStyleLegend + { + /// + /// Online resource for legend style + /// + public WmsOnlineResource OnlineResource; - /// - /// Parses GetMap request nodes - /// - /// - private void ParseGetMapRequest(XmlNode GetMapRequestNodes) - { - XmlNode xnlHttp = GetMapRequestNodes.SelectSingleNode("sm:DCPType/sm:HTTP", nsmgr); - if (xnlHttp != null && xnlHttp.HasChildNodes) - { - _GetMapRequests = new WmsOnlineResource[xnlHttp.ChildNodes.Count]; - for (int i = 0; i < xnlHttp.ChildNodes.Count; i++) - { + /// + /// Size of legend + /// + public Size Size; + } - WmsOnlineResource wor = new WmsOnlineResource(); - wor.Type = xnlHttp.ChildNodes[i].Name; - wor.OnlineResource = xnlHttp.ChildNodes[i].SelectSingleNode("sm:OnlineResource", nsmgr).Attributes["xlink:href"].InnerText; - _GetMapRequests[i] = wor; - } - } - XmlNodeList xnlFormats = GetMapRequestNodes.SelectNodes("sm:Format", nsmgr); - //_GetMapOutputFormats = new Collection(xnlFormats.Count); - _GetMapOutputFormats = new Collection(); - for (int i = 0; i < xnlFormats.Count;i++ ) - _GetMapOutputFormats.Add(xnlFormats[i].InnerText); - } + /// + /// Structure for storing info on an Online Resource + /// + public struct WmsOnlineResource + { + /// + /// Type of online resource (Ex. request method 'Get' or 'Post') + /// + public string Type; - /// - /// Iterates through the layer nodes recursively - /// - /// - /// - private WmsServerLayer ParseLayer(XmlNode xmlLayer) - { - WmsServerLayer layer = new WmsServerLayer(); - XmlNode node = xmlLayer.SelectSingleNode("sm:Name", nsmgr); - layer.Name = (node != null ? node.InnerText : null); - node = xmlLayer.SelectSingleNode("sm:Title", nsmgr); - layer.Title = (node != null ? node.InnerText : null); - if (string.IsNullOrEmpty(layer.Name)) - { - layer.Name = layer.Title; - } - node = xmlLayer.SelectSingleNode("sm:Abstract", nsmgr); - layer.Abstract = (node != null ? node.InnerText : null); - XmlAttribute attr = xmlLayer.Attributes["queryable"]; - layer.Queryable = (attr != null && attr.InnerText == "1"); + /// + /// URI of online resource + /// + public string OnlineResource; + } + #endregion - XmlNodeList xnlKeywords = xmlLayer.SelectNodes("sm:KeywordList/sm:Keyword", nsmgr); - if (xnlKeywords != null) - { - layer.Keywords = new string[xnlKeywords.Count]; - for (int i = 0; i < xnlKeywords.Count; i++) - layer.Keywords[i] = xnlKeywords[i].InnerText; - } - XmlNodeList xnlCrs = xmlLayer.SelectNodes("sm:CRS", nsmgr); - if (xnlCrs != null) - { - layer.CRS = new string[xnlCrs.Count]; - for (int i = 0; i < xnlCrs.Count; i++) - layer.CRS[i] = xnlCrs[i].InnerText; - } - XmlNodeList xnlStyle = xmlLayer.SelectNodes("sm:Style", nsmgr); - if (xnlStyle != null) - { - layer.Style = new WmsLayerStyle[xnlStyle.Count]; - for (int i = 0; i < xnlStyle.Count; i++) - { - node = xnlStyle[i].SelectSingleNode("sm:Name", nsmgr); - layer.Style[i].Name = (node != null ? node.InnerText : null); - node = xnlStyle[i].SelectSingleNode("sm:Title", nsmgr); - layer.Style[i].Title = (node != null ? node.InnerText : null); - node = xnlStyle[i].SelectSingleNode("sm:Abstract", nsmgr); - layer.Style[i].Abstract = (node != null ? node.InnerText : null); - node = xnlStyle[i].SelectSingleNode("sm:LegendUrl", nsmgr); - if (node != null) - { - layer.Style[i].LegendUrl = new WmsStyleLegend(); - layer.Style[i].LegendUrl.Size = new System.Drawing.Size( - int.Parse(node.Attributes["width"].InnerText), int.Parse(node.Attributes["height"].InnerText)); - layer.Style[i].LegendUrl.OnlineResource.OnlineResource = node.SelectSingleNode("sm:OnlineResource",nsmgr).Attributes["xlink:href"].InnerText; - layer.Style[i].LegendUrl.OnlineResource.Type = node.SelectSingleNode("sm:Format", nsmgr).InnerText; - } - node = xnlStyle[i].SelectSingleNode("sm:StyleSheetURL", nsmgr); - if (node != null) - { - layer.Style[i].StyleSheetUrl = new WmsOnlineResource(); - layer.Style[i].StyleSheetUrl.OnlineResource = node.SelectSingleNode("sm:OnlineResource", nsmgr).Attributes["xlink:href"].InnerText; - //layer.Style[i].StyleSheetUrl.OnlineResource = node.SelectSingleNode("sm:Format", nsmgr).InnerText; - } - } - } - XmlNodeList xnlLayers = xmlLayer.SelectNodes("sm:Layer", nsmgr); - if (xnlLayers != null) - { - layer.ChildLayers = new WmsServerLayer[xnlLayers.Count]; - for (int i = 0; i < xnlLayers.Count; i++) - layer.ChildLayers[i] = ParseLayer(xnlLayers[i]); - } - node = xmlLayer.SelectSingleNode("sm:LatLonBoundingBox", nsmgr); - if(node == null) + #region Properties + + private Capabilities.WmsServiceDescription _ServiceDescription; + + /// + /// Gets the service description + /// + public Capabilities.WmsServiceDescription ServiceDescription + { + get { - node = xmlLayer.SelectSingleNode("sm:BoundingBox", nsmgr); + return _ServiceDescription; } - if (node != null) - { - double minx = 0; double miny = 0; double maxx = 0; double maxy = 0; - if (!double.TryParse(node.Attributes["minx"].Value, System.Globalization.NumberStyles.Any, SharpMap.Map.numberFormat_EnUS, out minx) & - !double.TryParse(node.Attributes["miny"].Value, System.Globalization.NumberStyles.Any, SharpMap.Map.numberFormat_EnUS, out miny) & - !double.TryParse(node.Attributes["maxx"].Value, System.Globalization.NumberStyles.Any, SharpMap.Map.numberFormat_EnUS, out maxx) & - !double.TryParse(node.Attributes["maxy"].Value, System.Globalization.NumberStyles.Any, SharpMap.Map.numberFormat_EnUS, out maxy)) - throw new ArgumentException("Invalid LatLonBoundingBox on layer '" + layer.Name + "'"); - layer.LatLonBoundingBox = SharpMap.Converters.Geometries.GeometryFactory.CreateEnvelope(minx, maxx, miny, maxy); - } - return layer; - } - } -} + } + + /// + /// Gets the version of the WMS server (ex. "1.3.0") + /// + public string WmsVersion { get; private set; } + + /// + /// Gets a list of available image mime type formats + /// + public Collection GetMapOutputFormats { get; private set; } + + /// + /// Gets a list of available exception mime type formats + /// + public string[] ExceptionFormats { get; private set; } + + /// + /// Gets the available GetMap request methods and Online Resource URI + /// + public WmsOnlineResource[] GetMapRequests { get; private set; } + + /// + /// Gets the hiarchial layer structure + /// + public WmsServerLayer Layer { get; private set; } + + #endregion + } +} \ No newline at end of file