Client.cs
上传用户:sex100000
上传日期:2013-11-09
资源大小:1377k
文件大小:18k
源码类别:

GIS编程

开发平台:

C#

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.Text;
  5. using System.Xml;
  6. namespace SharpMap.Web.Wms
  7. {
  8. /// <summary>
  9. /// Class for requesting and parsing a WMS servers capabilities
  10. /// </summary>
  11. [Serializable]
  12. public class Client
  13. {
  14. private XmlNamespaceManager nsmgr;
  15. #region WMS Data structures
  16. /// <summary>
  17. /// Structure for holding information about a WMS Layer 
  18. /// </summary>
  19. public struct WmsServerLayer
  20. {
  21. /// <summary>
  22. /// Layer title
  23. /// </summary>
  24. public string Title;
  25. /// <summary>
  26. /// Unique name of this layer used for requesting layer
  27. /// </summary>
  28. public string Name;
  29. /// <summary>
  30. /// Abstract
  31. /// </summary>
  32. public string Abstract;
  33. /// <summary>
  34. /// Specifies whether this layer is queryable using GetFeatureInfo requests
  35. /// </summary>
  36. public bool Queryable;
  37. /// <summary>
  38. /// Keywords
  39. /// </summary>
  40. public string[] Keywords;
  41. /// <summary>
  42. /// List of styles supported by layer
  43. /// </summary>
  44. public WmsLayerStyle[] Style;
  45. /// <summary>
  46. /// Coordinate Reference Systems supported by layer
  47. /// </summary>
  48. public string[] CRS;
  49. /// <summary>
  50. /// Collection of child layers
  51. /// </summary>
  52. public WmsServerLayer[] ChildLayers;
  53. /// <summary>
  54. /// Latitudal/longitudal extent of this layer
  55. /// </summary>
  56. public SharpMap.Geometries.BoundingBox LatLonBoundingBox;
  57. }
  58. /// <summary>
  59. /// Structure for storing information about a WMS Layer Style
  60. /// </summary>
  61. public struct WmsLayerStyle
  62. {
  63. /// <summary>
  64. /// Name
  65. /// </summary>
  66. public string Name;
  67. /// <summary>
  68. /// Title
  69. /// </summary>
  70. public string Title;
  71. /// <summary>
  72. /// Abstract
  73. /// </summary>
  74. public string Abstract;
  75. /// <summary>
  76. /// Legend
  77. /// </summary>
  78. public WmsStyleLegend LegendUrl;
  79. /// <summary>
  80. /// Style Sheet Url
  81. /// </summary>
  82. public WmsOnlineResource StyleSheetUrl;
  83. }
  84. /// <summary>
  85. /// Structure for storing WMS Legend information
  86. /// </summary>
  87. public struct WmsStyleLegend
  88. {
  89. /// <summary>
  90. /// Online resource for legend style 
  91. /// </summary>
  92. public WmsOnlineResource OnlineResource;
  93. /// <summary>
  94. /// Size of legend
  95. /// </summary>
  96. public System.Drawing.Size Size;
  97. }
  98. /// <summary>
  99. /// Structure for storing info on an Online Resource
  100. /// </summary>
  101. public struct WmsOnlineResource
  102. {
  103. /// <summary>
  104. /// Type of online resource (Ex. request method 'Get' or 'Post')
  105. /// </summary>
  106. public string Type;
  107. /// <summary>
  108. /// URI of online resource
  109. /// </summary>
  110. public string OnlineResource;
  111. }
  112. #endregion
  113. #region Properties
  114. private Capabilities.WmsServiceDescription _ServiceDescription;
  115. /// <summary>
  116. /// Gets the service description
  117. /// </summary>
  118. public Capabilities.WmsServiceDescription ServiceDescription
  119. {
  120. get { return _ServiceDescription; }
  121. }
  122. private string _WmsVersion;
  123. /// <summary>
  124. /// Gets the version of the WMS server (ex. "1.3.0")
  125. /// </summary>
  126. public string WmsVersion
  127. {
  128. get { return _WmsVersion; }
  129. }
  130. private Collection<string> _GetMapOutputFormats;
  131. /// <summary>
  132. /// Gets a list of available image mime type formats
  133. /// </summary>
  134. public Collection<string> GetMapOutputFormats
  135. {
  136. get { return _GetMapOutputFormats; }
  137. }
  138. private string[] _ExceptionFormats;
  139. /// <summary>
  140. /// Gets a list of available exception mime type formats
  141. /// </summary>
  142. public string[] ExceptionFormats
  143. {
  144. get { return _ExceptionFormats; }
  145. }
  146. private WmsOnlineResource[] _GetMapRequests;
  147. /// <summary>
  148. /// Gets the available GetMap request methods and Online Resource URI
  149. /// </summary>
  150. public WmsOnlineResource[] GetMapRequests
  151. {
  152. get { return _GetMapRequests; }
  153. }
  154. private WmsServerLayer _Layer;
  155. /// <summary>
  156. /// Gets the hiarchial layer structure
  157. /// </summary>
  158. public WmsServerLayer Layer
  159. {
  160. get { return _Layer; }
  161. }
  162. #endregion
  163. /// <summary>
  164. /// Initalizes WMS server and parses the Capabilities request
  165. /// </summary>
  166. /// <param name="url">URL of wms server</param>
  167. public Client(string url)
  168. : this(url, null)
  169. {
  170. }
  171. /// <summary>
  172. /// Initalizes WMS server and parses the Capabilities request
  173. /// </summary>
  174. /// <param name="url">URL of wms server</param>
  175. /// <param name="proxy">Proxy to use</param>
  176. public Client(string url, System.Net.WebProxy proxy)
  177. {
  178. System.Text.StringBuilder strReq = new StringBuilder(url);
  179. if (!url.Contains("?"))
  180. strReq.Append("?");
  181. if (!strReq.ToString().EndsWith("&") && !strReq.ToString().EndsWith("?"))
  182. strReq.Append("&");
  183. if(!url.ToLower().Contains("service=wms"))
  184. strReq.AppendFormat("SERVICE=WMS&");
  185. if (!url.ToLower().Contains("request=getcapabilities"))
  186. strReq.AppendFormat("REQUEST=GetCapabilities&");
  187. XmlDocument xml = GetRemoteXml(strReq.ToString(), proxy);
  188. ParseCapabilities(xml);
  189. }
  190. /// <summary>
  191. /// Downloads servicedescription from WMS service
  192. /// </summary>
  193. /// <returns>XmlDocument from Url. Null if Url is empty or inproper XmlDocument</returns>
  194. private XmlDocument GetRemoteXml(string Url, System.Net.WebProxy proxy)
  195. {
  196. try
  197. {
  198. System.Net.WebRequest myRequest = System.Net.WebRequest.Create(Url);
  199. if (proxy != null) myRequest.Proxy = proxy;
  200. System.Net.WebResponse myResponse = myRequest.GetResponse();
  201. System.IO.Stream stream = myResponse.GetResponseStream();
  202. XmlTextReader r = new XmlTextReader(Url, stream);
  203. XmlDocument doc = new XmlDocument();
  204. doc.Load(r);
  205. stream.Close();
  206. nsmgr = new XmlNamespaceManager(doc.NameTable);
  207. return doc;
  208. }
  209. catch (System.Exception ex)
  210. {
  211. throw new ApplicationException("Could now download capabilities", ex);
  212. }
  213. }
  214. /// <summary>
  215. /// Parses a servicedescription and stores the data in the ServiceDescription property
  216. /// </summary>
  217. /// <param name="doc">XmlDocument containing a valid Service Description</param>
  218. private void ParseCapabilities(XmlDocument doc)
  219. {
  220. if (doc.DocumentElement.Attributes["version"] != null)
  221. {
  222. _WmsVersion = doc.DocumentElement.Attributes["version"].Value;
  223. if (_WmsVersion != "1.0.0" && _WmsVersion != "1.1.0" && _WmsVersion != "1.1.1" && _WmsVersion != "1.3.0")
  224. throw new ApplicationException("WMS Version " + _WmsVersion + " not supported");
  225. nsmgr.AddNamespace(String.Empty, "http://www.opengis.net/wms");
  226. if (_WmsVersion == "1.3.0")
  227. {
  228. nsmgr.AddNamespace("sm", "http://www.opengis.net/wms");
  229. }
  230. else
  231. nsmgr.AddNamespace("sm", "");
  232. nsmgr.AddNamespace("xlink", "http://www.w3.org/1999/xlink");
  233. nsmgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
  234. }
  235. else
  236. throw (new ApplicationException("No service version number found!"));
  237. XmlNode xnService = doc.DocumentElement.SelectSingleNode("sm:Service", nsmgr);
  238. XmlNode xnCapability = doc.DocumentElement.SelectSingleNode("sm:Capability", nsmgr);
  239. if (xnService != null)
  240. ParseServiceDescription(xnService);
  241. else
  242. throw (new ApplicationException("No service tag found!"));
  243. if (xnCapability != null)
  244. ParseCapability(xnCapability);
  245. else
  246. throw (new ApplicationException("No capability tag found!"));
  247. }
  248. /// <summary>
  249. /// Parses service description node
  250. /// </summary>
  251. /// <param name="xnlServiceDescription"></param>
  252. private void ParseServiceDescription(XmlNode xnlServiceDescription)
  253. {
  254. XmlNode node = xnlServiceDescription.SelectSingleNode("sm:Title", nsmgr);
  255. _ServiceDescription.Title = (node != null ? node.InnerText : null);
  256. node = xnlServiceDescription.SelectSingleNode("sm:OnlineResource/@xlink:href", nsmgr);
  257. _ServiceDescription.OnlineResource = (node != null ? node.InnerText : null);
  258. node = xnlServiceDescription.SelectSingleNode("sm:Abstract", nsmgr);
  259. _ServiceDescription.Abstract = (node != null ? node.InnerText : null);
  260. node = xnlServiceDescription.SelectSingleNode("sm:Fees", nsmgr);
  261. _ServiceDescription.Fees = (node != null ? node.InnerText : null);
  262. node = xnlServiceDescription.SelectSingleNode("sm:AccessConstraints", nsmgr);
  263. _ServiceDescription.AccessConstraints = (node != null ? node.InnerText : null);
  264. XmlNodeList xnlKeywords = xnlServiceDescription.SelectNodes("sm:KeywordList/sm:Keyword", nsmgr);
  265. if (xnlKeywords != null)
  266. {
  267. _ServiceDescription.Keywords = new string[xnlKeywords.Count];
  268. for (int i = 0; i < xnlKeywords.Count; i++)
  269. ServiceDescription.Keywords[i] = xnlKeywords[i].InnerText;
  270. }
  271. //Contact information
  272. _ServiceDescription.ContactInformation = new Capabilities.WmsContactInformation();
  273. node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactAddress/sm:Address", nsmgr);
  274. _ServiceDescription.ContactInformation.Address.Address = (node != null ? node.InnerText : null);
  275. node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactAddress/sm:AddressType", nsmgr);
  276. _ServiceDescription.ContactInformation.Address.AddressType = (node != null ? node.InnerText : null);
  277. node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactAddress/sm:City", nsmgr);
  278. _ServiceDescription.ContactInformation.Address.City = (node != null ? node.InnerText : null);
  279. node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactAddress/sm:Country", nsmgr);
  280. _ServiceDescription.ContactInformation.Address.Country = (node != null ? node.InnerText : null);
  281. node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactAddress/sm:PostCode", nsmgr);
  282. _ServiceDescription.ContactInformation.Address.PostCode = (node != null ? node.InnerText : null);
  283. node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactElectronicMailAddress", nsmgr);
  284. _ServiceDescription.ContactInformation.Address.StateOrProvince = (node != null ? node.InnerText : null);
  285. node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactElectronicMailAddress", nsmgr);
  286. _ServiceDescription.ContactInformation.ElectronicMailAddress = (node != null ? node.InnerText : null);
  287. node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactFacsimileTelephone", nsmgr);
  288. _ServiceDescription.ContactInformation.FacsimileTelephone = (node != null ? node.InnerText : null);
  289. node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactPersonPrimary/sm:ContactOrganisation", nsmgr);
  290. _ServiceDescription.ContactInformation.PersonPrimary.Organisation = (node != null ? node.InnerText : null);
  291. node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactPersonPrimary/sm:ContactPerson", nsmgr);
  292. _ServiceDescription.ContactInformation.PersonPrimary.Person = (node != null ? node.InnerText : null);
  293. node = xnlServiceDescription.SelectSingleNode("sm:ContactInformation/sm:ContactVoiceTelephone", nsmgr);
  294. _ServiceDescription.ContactInformation.VoiceTelephone = (node != null ? node.InnerText : null);
  295. }
  296. /// <summary>
  297. /// Parses capability node
  298. /// </summary>
  299. /// <param name="xnCapability"></param>
  300. private void ParseCapability(XmlNode xnCapability)
  301. {
  302. XmlNode xnRequest = xnCapability.SelectSingleNode("sm:Request", nsmgr);
  303. if (xnRequest == null)
  304. throw (new System.Exception("Request parameter not specified in Service Description"));
  305. ParseRequest(xnRequest);
  306. XmlNode xnLayer = xnCapability.SelectSingleNode("sm:Layer", nsmgr);
  307. if (xnLayer == null)
  308. throw (new System.Exception("No layer tag found in Service Description")); 
  309. _Layer = ParseLayer(xnLayer);
  310. XmlNode xnException = xnCapability.SelectSingleNode("sm:Exception", nsmgr);
  311. if (xnException != null)
  312. ParseExceptions(xnException);
  313. }
  314. /// <summary>
  315. /// Parses valid exceptions
  316. /// </summary>
  317. /// <param name="xnlExceptionNode"></param>
  318. private void ParseExceptions(XmlNode xnlExceptionNode)
  319. {
  320. XmlNodeList xnlFormats = xnlExceptionNode.SelectNodes("sm:Format", nsmgr);
  321. if (xnlFormats != null)
  322. {
  323. _ExceptionFormats = new string[xnlFormats.Count];
  324. for (int i = 0; i < xnlFormats.Count; i++)
  325. {
  326. _ExceptionFormats[i] = xnlFormats[i].InnerText;
  327. }
  328. }
  329. }
  330. /// <summary>
  331. /// Parses request node
  332. /// </summary>
  333. /// <param name="xmlRequestNode"></param>
  334. private void ParseRequest(XmlNode xmlRequestNode)
  335. {
  336. XmlNode xnGetMap = xmlRequestNode.SelectSingleNode("sm:GetMap",nsmgr);
  337. ParseGetMapRequest(xnGetMap);
  338. //TODO:
  339. //XmlNode xnGetFeatureInfo = xmlRequestNodes.SelectSingleNode("sm:GetFeatureInfo", nsmgr);
  340. //XmlNode xnCapa = xmlRequestNodes.SelectSingleNode("sm:GetCapabilities", nsmgr); <-- We don't really need this do we?
  341. }
  342. /// <summary>
  343. /// Parses GetMap request nodes
  344. /// </summary>
  345. /// <param name="GetMapRequestNodes"></param>
  346. private void ParseGetMapRequest(XmlNode GetMapRequestNodes)
  347. {
  348. XmlNode xnlHttp = GetMapRequestNodes.SelectSingleNode("sm:DCPType/sm:HTTP", nsmgr);
  349. if (xnlHttp != null && xnlHttp.HasChildNodes)
  350. {
  351. _GetMapRequests = new WmsOnlineResource[xnlHttp.ChildNodes.Count];
  352. for (int i = 0; i < xnlHttp.ChildNodes.Count; i++)
  353. {
  354. WmsOnlineResource wor = new WmsOnlineResource();
  355. wor.Type = xnlHttp.ChildNodes[i].Name;
  356. wor.OnlineResource = xnlHttp.ChildNodes[i].SelectSingleNode("sm:OnlineResource", nsmgr).Attributes["xlink:href"].InnerText;
  357. _GetMapRequests[i] = wor;
  358. }
  359. }
  360. XmlNodeList xnlFormats = GetMapRequestNodes.SelectNodes("sm:Format", nsmgr);
  361.             //_GetMapOutputFormats = new Collection<string>(xnlFormats.Count);
  362.             _GetMapOutputFormats = new Collection<string>();
  363. for (int i = 0; i < xnlFormats.Count;i++ )
  364. _GetMapOutputFormats.Add(xnlFormats[i].InnerText);
  365. }
  366. /// <summary>
  367. /// Iterates through the layer nodes recursively
  368. /// </summary>
  369. /// <param name="xmlLayer"></param>
  370. /// <returns></returns>
  371. private WmsServerLayer ParseLayer(XmlNode xmlLayer)
  372. {
  373. WmsServerLayer layer = new WmsServerLayer();
  374. XmlNode node = xmlLayer.SelectSingleNode("sm:Name", nsmgr);
  375. layer.Name = (node != null ? node.InnerText : null);
  376. node = xmlLayer.SelectSingleNode("sm:Title", nsmgr);
  377. layer.Title = (node != null ? node.InnerText : null);
  378. node = xmlLayer.SelectSingleNode("sm:Abstract", nsmgr);
  379. layer.Abstract = (node != null ? node.InnerText : null);
  380. XmlAttribute attr = xmlLayer.Attributes["queryable"];
  381. layer.Queryable = (attr != null && attr.InnerText == "1");
  382. XmlNodeList xnlKeywords = xmlLayer.SelectNodes("sm:KeywordList/sm:Keyword", nsmgr);
  383. if (xnlKeywords != null)
  384. {
  385. layer.Keywords = new string[xnlKeywords.Count];
  386. for (int i = 0; i < xnlKeywords.Count; i++)
  387. layer.Keywords[i] = xnlKeywords[i].InnerText;
  388. }
  389. XmlNodeList xnlCrs = xmlLayer.SelectNodes("sm:CRS", nsmgr);
  390. if (xnlCrs != null)
  391. {
  392. layer.CRS = new string[xnlCrs.Count];
  393. for (int i = 0; i < xnlCrs.Count; i++)
  394. layer.CRS[i] = xnlCrs[i].InnerText;
  395. }
  396. XmlNodeList xnlStyle = xmlLayer.SelectNodes("sm:Style", nsmgr);
  397. if (xnlStyle != null)
  398. {
  399. layer.Style = new WmsLayerStyle[xnlStyle.Count];
  400. for (int i = 0; i < xnlStyle.Count; i++)
  401. {
  402. node = xnlStyle[i].SelectSingleNode("sm:Name", nsmgr);
  403. layer.Style[i].Name = (node != null ? node.InnerText : null);
  404. node = xnlStyle[i].SelectSingleNode("sm:Title", nsmgr);
  405. layer.Style[i].Title = (node != null ? node.InnerText : null);
  406. node = xnlStyle[i].SelectSingleNode("sm:Abstract", nsmgr);
  407. layer.Style[i].Abstract = (node != null ? node.InnerText : null);
  408. node = xnlStyle[i].SelectSingleNode("sm:LegendUrl", nsmgr);
  409. if (node != null)
  410. {
  411. layer.Style[i].LegendUrl = new WmsStyleLegend();
  412. layer.Style[i].LegendUrl.Size = new System.Drawing.Size(
  413. int.Parse(node.Attributes["width"].InnerText), int.Parse(node.Attributes["height"].InnerText));
  414. layer.Style[i].LegendUrl.OnlineResource.OnlineResource = node.SelectSingleNode("sm:OnlineResource",nsmgr).Attributes["xlink:href"].InnerText;
  415. layer.Style[i].LegendUrl.OnlineResource.Type = node.SelectSingleNode("sm:Format", nsmgr).InnerText;
  416. }
  417. node = xnlStyle[i].SelectSingleNode("sm:StyleSheetURL", nsmgr);
  418. if (node != null)
  419. {
  420. layer.Style[i].StyleSheetUrl  = new WmsOnlineResource();
  421. layer.Style[i].StyleSheetUrl.OnlineResource = node.SelectSingleNode("sm:OnlineResource", nsmgr).Attributes["xlink:href"].InnerText;
  422. //layer.Style[i].StyleSheetUrl.OnlineResource = node.SelectSingleNode("sm:Format", nsmgr).InnerText;
  423. }
  424. }
  425. }
  426. XmlNodeList xnlLayers = xmlLayer.SelectNodes("sm:Layer", nsmgr);
  427. if (xnlLayers != null)
  428. {
  429. layer.ChildLayers = new WmsServerLayer[xnlLayers.Count];
  430. for (int i = 0; i < xnlLayers.Count; i++)
  431. layer.ChildLayers[i] = ParseLayer(xnlLayers[i]);
  432. }
  433. node = xmlLayer.SelectSingleNode("sm:LatLonBoundingBox", nsmgr);
  434. if (node != null)
  435. {
  436. double minx = 0; double miny = 0; double maxx = 0; double maxy = 0;
  437. if (!double.TryParse(node.Attributes["minx"].Value, System.Globalization.NumberStyles.Any, SharpMap.Map.numberFormat_EnUS, out minx) &
  438. !double.TryParse(node.Attributes["miny"].Value, System.Globalization.NumberStyles.Any, SharpMap.Map.numberFormat_EnUS, out miny) &
  439. !double.TryParse(node.Attributes["maxx"].Value, System.Globalization.NumberStyles.Any, SharpMap.Map.numberFormat_EnUS, out maxx) &
  440. !double.TryParse(node.Attributes["maxy"].Value, System.Globalization.NumberStyles.Any, SharpMap.Map.numberFormat_EnUS, out maxy))
  441. throw new ArgumentException("Invalid LatLonBoundingBox on layer '" + layer.Name + "'");
  442. layer.LatLonBoundingBox = new SharpMap.Geometries.BoundingBox(minx, miny, maxx, maxy);
  443. }
  444. return layer;
  445. }
  446. }
  447. }