Index: src/Common/SharpMap/Web/Wms/Capabilities.cs =================================================================== diff -u -r8f6ae890fed8e8eae3a32f9c0498a10f82e0ddf9 -r5fc71a385897af92ccb092f2f969b5709afab85a --- src/Common/SharpMap/Web/Wms/Capabilities.cs (.../Capabilities.cs) (revision 8f6ae890fed8e8eae3a32f9c0498a10f82e0ddf9) +++ src/Common/SharpMap/Web/Wms/Capabilities.cs (.../Capabilities.cs) (revision 5fc71a385897af92ccb092f2f969b5709afab85a) @@ -16,436 +16,518 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA using System; +using System.Drawing.Imaging; +using System.IO; +using System.Reflection; +using System.Web; using System.Xml; +using System.Xml.Schema; using GeoAPI.Geometries; using SharpMap.Api.Layers; +using SharpMap.Layers; namespace SharpMap.Web.Wms { - /// - /// Class for generating the WmsCapabilities Xml - /// - public class Capabilities - { - /// - /// The Wms Service Description stores metadata parameters for a WMS service - /// - public struct WmsServiceDescription - { - /// - /// Initializes a WmsServiceDescription object - /// - /// Mandatory Human-readable title for pick lists - /// Top-level web address of service or service provider. - public WmsServiceDescription(string title, string onlineResource) - { - Title = title; - OnlineResource = onlineResource; - Keywords = null; - Abstract = ""; - ContactInformation = new WmsContactInformation(); - Fees = ""; - AccessConstraints = ""; - LayerLimit = 0; - MaxWidth = 0; - MaxHeight = 0; - } - /// - /// Mandatory Human-readable title for pick lists - /// - public string Title; - /// - /// Optional narrative description providing additional information - /// - public string Abstract; - /// - /// Optional list of keywords or keyword phrases describing the server as a whole to help catalog searching - /// - public string[] Keywords; - /// - /// Mandatory Top-level web address of service or service provider. - /// - public string OnlineResource; - /// - /// Optional WMS contact information - /// - public WmsContactInformation ContactInformation; - /// - /// The optional element "Fees" may be omitted if it do not apply to the server. If - /// the element is present, the reserved word "none" (case-insensitive) shall be used if there are no - /// fees, as follows: "none". - /// - public string Fees; - /// - /// The optional element "AccessConstraints" may be omitted if it do not apply to the server. If - /// the element is present, the reserved word "none" (case-insensitive) shall be used if there are no - /// access constraints, as follows: "none". - /// When constraints are imposed, no precise syntax has been defined for the text content of these elements, but - /// client applications may display the content for user information and action. - /// - public string AccessConstraints; - /// - /// Maximum number of layers allowed (0=no restrictions) - /// - public uint LayerLimit; - /// - /// Maximum width allowed in pixels (0=no restrictions) - /// - public uint MaxWidth; - /// - /// Maximum height allowed in pixels (0=no restrictions) - /// - public uint MaxHeight; - } + /// + /// Class for generating the WmsCapabilities Xml + /// + public class Capabilities + { + private const string wmsNamespaceURI = "http://www.opengis.net/wms"; + private const string xlinkNamespaceURI = "http://www.w3.org/1999/xlink"; - /// - /// Stores contact metadata about WMS service - /// - public struct WmsContactInformation - { - /// - /// Primary contact person - /// - public ContactPerson PersonPrimary; - /// - /// Position of contact person - /// - public string Position; - /// - /// Address - /// - public ContactAddress Address; - /// - /// Telephone - /// - public string VoiceTelephone; - /// - /// Fax number - /// - public string FacsimileTelephone; - /// - /// Email address - /// - public string ElectronicMailAddress; - /// - /// Information about a contact person for the service. - /// - public struct ContactPerson - { - /// - /// Primary contact person - /// - public string Person; - /// - /// Organisation of primary person - /// - public string Organisation; - } - /// - /// Information about a contact address for the service. - /// - public struct ContactAddress - { - /// - /// Type of address (usually "postal"). - /// - public string AddressType; - /// - /// Contact address - /// - public string Address; - /// - /// Contact City - /// - public string City; - /// - /// State or province of contact - /// - public string StateOrProvince; - /// - /// Zipcode of contact - /// - public string PostCode; - /// - /// Country of contact address - /// - public string Country; - } - } + /// + /// Generates a capabilities file from a map object for use in WMS services + /// + /// The capabilities document uses the v1.3.0 OpenGIS WMS specification + /// The map to create capabilities for + /// Additional description of WMS + /// Returns XmlDocument describing capabilities + public static XmlDocument GetCapabilities(Map map, WmsServiceDescription serviceDescription) + { + XmlDocument capabilities = new XmlDocument(); - private const string wmsNamespaceURI = "http://www.opengis.net/wms"; - private const string xlinkNamespaceURI = "http://www.w3.org/1999/xlink"; - - /// - /// Generates a capabilities file from a map object for use in WMS services - /// - /// The capabilities document uses the v1.3.0 OpenGIS WMS specification - /// The map to create capabilities for - /// Additional description of WMS - /// Returns XmlDocument describing capabilities - public static XmlDocument GetCapabilities(SharpMap.Map map, WmsServiceDescription serviceDescription) - { - XmlDocument capabilities = new XmlDocument(); - - - //Set XMLSchema - //capabilities.Schemas.Add(GetCapabilitiesSchema()); + //Set XMLSchema + //capabilities.Schemas.Add(GetCapabilitiesSchema()); - //Instantiate an XmlNamespaceManager object. - //System.Xml.XmlNamespaceManager xmlnsManager = new System.Xml.XmlNamespaceManager(capabilities.NameTable); - //xmlnsManager.AddNamespace(xlinkNamespaceURI, "urn:Books"); - - //Insert XML tag - capabilities.InsertBefore(capabilities.CreateXmlDeclaration("1.0", "UTF-8", string.Empty), capabilities.DocumentElement); - capabilities.AppendChild(capabilities.CreateComment("Capabilities generated by SharpMap v. " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString())); - //Create root node - XmlNode RootNode = capabilities.CreateNode(XmlNodeType.Element, "WMS_Capabilities", wmsNamespaceURI); - RootNode.Attributes.Append(CreateAttribute("version", "1.3.0", capabilities)); - - XmlAttribute attr = capabilities.CreateAttribute("xmlns", "xsi", "http://www.w3.org/2000/xmlns/"); - attr.InnerText = "http://www.w3.org/2001/XMLSchema-instance"; - RootNode.Attributes.Append(attr); + //Instantiate an XmlNamespaceManager object. + //System.Xml.XmlNamespaceManager xmlnsManager = new System.Xml.XmlNamespaceManager(capabilities.NameTable); + //xmlnsManager.AddNamespace(xlinkNamespaceURI, "urn:Books"); - RootNode.Attributes.Append(CreateAttribute("xmlns:xlink", xlinkNamespaceURI, capabilities)); - XmlAttribute attr2 = capabilities.CreateAttribute("xsi", "schemaLocation", "http://www.w3.org/2001/XMLSchema-instance"); - attr2.InnerText = "http://schemas.opengis.net/wms/1.3.0/capabilities_1_3_0.xsd"; - RootNode.Attributes.Append(attr2); + //Insert XML tag + capabilities.InsertBefore(capabilities.CreateXmlDeclaration("1.0", "UTF-8", string.Empty), capabilities.DocumentElement); + capabilities.AppendChild(capabilities.CreateComment("Capabilities generated by SharpMap v. " + Assembly.GetExecutingAssembly().GetName().Version.ToString())); + //Create root node + XmlNode RootNode = capabilities.CreateNode(XmlNodeType.Element, "WMS_Capabilities", wmsNamespaceURI); + RootNode.Attributes.Append(CreateAttribute("version", "1.3.0", capabilities)); - //Build Service node - RootNode.AppendChild(GenerateServiceNode(ref serviceDescription, capabilities)); + XmlAttribute attr = capabilities.CreateAttribute("xmlns", "xsi", "http://www.w3.org/2000/xmlns/"); + attr.InnerText = "http://www.w3.org/2001/XMLSchema-instance"; + RootNode.Attributes.Append(attr); - //Build Capability node - RootNode.AppendChild(GenerateCapabilityNode(map, capabilities)); + RootNode.Attributes.Append(CreateAttribute("xmlns:xlink", xlinkNamespaceURI, capabilities)); + XmlAttribute attr2 = capabilities.CreateAttribute("xsi", "schemaLocation", "http://www.w3.org/2001/XMLSchema-instance"); + attr2.InnerText = "http://schemas.opengis.net/wms/1.3.0/capabilities_1_3_0.xsd"; + RootNode.Attributes.Append(attr2); - capabilities.AppendChild(RootNode); + //Build Service node + RootNode.AppendChild(GenerateServiceNode(ref serviceDescription, capabilities)); - //TODO: Validate output against schema + //Build Capability node + RootNode.AppendChild(GenerateCapabilityNode(map, capabilities)); - return capabilities; - } + capabilities.AppendChild(RootNode); - private static XmlNode GenerateServiceNode(ref WmsServiceDescription serviceDescription, XmlDocument capabilities) - { - //XmlNode ServiceNode = capabilities.CreateNode(XmlNodeType.Element, "Service", ""); - XmlElement ServiceNode = capabilities.CreateElement("Service", wmsNamespaceURI); - ServiceNode.AppendChild(CreateElement("Name", "WMS", capabilities, false, wmsNamespaceURI)); - ServiceNode.AppendChild(CreateElement("Title", serviceDescription.Title, capabilities, false, wmsNamespaceURI)); //Add WMS Title - if (!String.IsNullOrEmpty(serviceDescription.Abstract)) //Add WMS abstract - ServiceNode.AppendChild(CreateElement("Abstract", serviceDescription.Abstract, capabilities, false, wmsNamespaceURI)); - if (serviceDescription.Keywords.Length > 0) //Add keywords - { - XmlElement KeywordListNode = capabilities.CreateElement("KeywordList", wmsNamespaceURI); - foreach (string keyword in serviceDescription.Keywords) - KeywordListNode.AppendChild(CreateElement("Keyword", keyword, capabilities, false, wmsNamespaceURI)); - ServiceNode.AppendChild(KeywordListNode); - } - //Add Online resource - XmlElement OnlineResourceNode = GenerateOnlineResourceElement(capabilities, serviceDescription.OnlineResource); - ServiceNode.AppendChild(OnlineResourceNode); + //TODO: Validate output against schema - //Add ContactInformation info - XmlElement ContactInfoNode = GenerateContactInfoElement(capabilities, serviceDescription.ContactInformation); - if(ContactInfoNode.HasChildNodes) - ServiceNode.AppendChild(ContactInfoNode); + return capabilities; + } - if (serviceDescription.Fees != null && serviceDescription.Fees != string.Empty) - ServiceNode.AppendChild(CreateElement("Fees", serviceDescription.Fees, capabilities, false, wmsNamespaceURI)); - if (serviceDescription.AccessConstraints != null && serviceDescription.AccessConstraints != string.Empty) - ServiceNode.AppendChild(CreateElement("AccessConstraints", serviceDescription.AccessConstraints, capabilities, false, wmsNamespaceURI)); - if(serviceDescription.LayerLimit>0) - ServiceNode.AppendChild(CreateElement("LayerLimit", serviceDescription.LayerLimit.ToString(), capabilities, false, wmsNamespaceURI)); - if (serviceDescription.MaxWidth > 0) - ServiceNode.AppendChild(CreateElement("MaxWidth", serviceDescription.MaxWidth.ToString(), capabilities, false, wmsNamespaceURI)); - if (serviceDescription.MaxHeight > 0) - ServiceNode.AppendChild(CreateElement("MaxHeight", serviceDescription.MaxHeight.ToString(), capabilities, false, wmsNamespaceURI)); - return ServiceNode; - } + internal static XmlDocument CreateXml() + { + XmlDocument capabilities = new XmlDocument(); + //Set XMLSchema + capabilities.Schemas = new XmlSchemaSet(); + capabilities.Schemas.Add(GetCapabilitiesSchema()); - private static XmlNode GenerateCapabilityNode(SharpMap.Map map, XmlDocument capabilities) - { - string OnlineResource = ""; - OnlineResource = System.Web.HttpContext.Current.Server.HtmlEncode("http://" + System.Web.HttpContext.Current.Request.Url.Host + System.Web.HttpContext.Current.Request.Url.AbsolutePath); - XmlNode CapabilityNode = capabilities.CreateNode(XmlNodeType.Element, "Capability", wmsNamespaceURI); - XmlNode RequestNode = capabilities.CreateNode(XmlNodeType.Element, "Request", wmsNamespaceURI); - XmlNode GetCapabilitiesNode = capabilities.CreateNode(XmlNodeType.Element, "GetCapabilities", wmsNamespaceURI); - //Set format of supported capabilities mime types (only text/xml supported) - GetCapabilitiesNode.AppendChild(CreateElement("Format", "text/xml", capabilities, false, wmsNamespaceURI)); - GetCapabilitiesNode.AppendChild(GenerateDCPTypeNode(capabilities, OnlineResource)); - RequestNode.AppendChild(GetCapabilitiesNode); + return capabilities; + } - XmlNode GetMapNode = capabilities.CreateNode(XmlNodeType.Element, "GetMap", wmsNamespaceURI); - //Add supported fileformats. Return the ones that GDI+ supports - foreach (System.Drawing.Imaging.ImageCodecInfo encoder in System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()) - GetMapNode.AppendChild(CreateElement("Format", encoder.MimeType, capabilities, false, wmsNamespaceURI)); - - GetMapNode.AppendChild(GenerateDCPTypeNode(capabilities,OnlineResource)); + private static XmlNode GenerateServiceNode(ref WmsServiceDescription serviceDescription, XmlDocument capabilities) + { + //XmlNode ServiceNode = capabilities.CreateNode(XmlNodeType.Element, "Service", ""); + XmlElement ServiceNode = capabilities.CreateElement("Service", wmsNamespaceURI); + ServiceNode.AppendChild(CreateElement("Name", "WMS", capabilities, false, wmsNamespaceURI)); + ServiceNode.AppendChild(CreateElement("Title", serviceDescription.Title, capabilities, false, wmsNamespaceURI)); //Add WMS Title + if (!String.IsNullOrEmpty(serviceDescription.Abstract)) //Add WMS abstract + { + ServiceNode.AppendChild(CreateElement("Abstract", serviceDescription.Abstract, capabilities, false, wmsNamespaceURI)); + } + if (serviceDescription.Keywords.Length > 0) //Add keywords + { + XmlElement KeywordListNode = capabilities.CreateElement("KeywordList", wmsNamespaceURI); + foreach (string keyword in serviceDescription.Keywords) + { + KeywordListNode.AppendChild(CreateElement("Keyword", keyword, capabilities, false, wmsNamespaceURI)); + } + ServiceNode.AppendChild(KeywordListNode); + } + //Add Online resource + XmlElement OnlineResourceNode = GenerateOnlineResourceElement(capabilities, serviceDescription.OnlineResource); + ServiceNode.AppendChild(OnlineResourceNode); - RequestNode.AppendChild(GetMapNode); - CapabilityNode.AppendChild(RequestNode); - XmlElement exceptionNode = capabilities.CreateElement("Exception",wmsNamespaceURI); - exceptionNode.AppendChild(CreateElement("Format", "text/xml", capabilities, false, wmsNamespaceURI)); - CapabilityNode.AppendChild(exceptionNode); //Add supported exception types + //Add ContactInformation info + XmlElement ContactInfoNode = GenerateContactInfoElement(capabilities, serviceDescription.ContactInformation); + if (ContactInfoNode.HasChildNodes) + { + ServiceNode.AppendChild(ContactInfoNode); + } - //Build layerlist - - XmlNode LayerRootNode = capabilities.CreateNode(XmlNodeType.Element, "Layer", wmsNamespaceURI); - LayerRootNode.AppendChild(CreateElement("Title", "SharpMap", capabilities, false, wmsNamespaceURI)); - LayerRootNode.AppendChild(CreateElement("CRS", "EPSG:" + map.Layers[0].DataSource.CoordinateSystem.AuthorityCode.ToString(), capabilities, false, wmsNamespaceURI)); //TODO + if (serviceDescription.Fees != null && serviceDescription.Fees != string.Empty) + { + ServiceNode.AppendChild(CreateElement("Fees", serviceDescription.Fees, capabilities, false, wmsNamespaceURI)); + } + if (serviceDescription.AccessConstraints != null && serviceDescription.AccessConstraints != string.Empty) + { + ServiceNode.AppendChild(CreateElement("AccessConstraints", serviceDescription.AccessConstraints, capabilities, false, wmsNamespaceURI)); + } + if (serviceDescription.LayerLimit > 0) + { + ServiceNode.AppendChild(CreateElement("LayerLimit", serviceDescription.LayerLimit.ToString(), capabilities, false, wmsNamespaceURI)); + } + if (serviceDescription.MaxWidth > 0) + { + ServiceNode.AppendChild(CreateElement("MaxWidth", serviceDescription.MaxWidth.ToString(), capabilities, false, wmsNamespaceURI)); + } + if (serviceDescription.MaxHeight > 0) + { + ServiceNode.AppendChild(CreateElement("MaxHeight", serviceDescription.MaxHeight.ToString(), capabilities, false, wmsNamespaceURI)); + } + return ServiceNode; + } + + private static XmlNode GenerateCapabilityNode(Map map, XmlDocument capabilities) + { + string OnlineResource = ""; + OnlineResource = HttpContext.Current.Server.HtmlEncode("http://" + HttpContext.Current.Request.Url.Host + HttpContext.Current.Request.Url.AbsolutePath); + XmlNode CapabilityNode = capabilities.CreateNode(XmlNodeType.Element, "Capability", wmsNamespaceURI); + XmlNode RequestNode = capabilities.CreateNode(XmlNodeType.Element, "Request", wmsNamespaceURI); + XmlNode GetCapabilitiesNode = capabilities.CreateNode(XmlNodeType.Element, "GetCapabilities", wmsNamespaceURI); + //Set format of supported capabilities mime types (only text/xml supported) + GetCapabilitiesNode.AppendChild(CreateElement("Format", "text/xml", capabilities, false, wmsNamespaceURI)); + GetCapabilitiesNode.AppendChild(GenerateDCPTypeNode(capabilities, OnlineResource)); + RequestNode.AppendChild(GetCapabilitiesNode); + + XmlNode GetMapNode = capabilities.CreateNode(XmlNodeType.Element, "GetMap", wmsNamespaceURI); + //Add supported fileformats. Return the ones that GDI+ supports + foreach (ImageCodecInfo encoder in ImageCodecInfo.GetImageEncoders()) + { + GetMapNode.AppendChild(CreateElement("Format", encoder.MimeType, capabilities, false, wmsNamespaceURI)); + } + + GetMapNode.AppendChild(GenerateDCPTypeNode(capabilities, OnlineResource)); + + RequestNode.AppendChild(GetMapNode); + CapabilityNode.AppendChild(RequestNode); + XmlElement exceptionNode = capabilities.CreateElement("Exception", wmsNamespaceURI); + exceptionNode.AppendChild(CreateElement("Format", "text/xml", capabilities, false, wmsNamespaceURI)); + CapabilityNode.AppendChild(exceptionNode); //Add supported exception types + + //Build layerlist + + XmlNode LayerRootNode = capabilities.CreateNode(XmlNodeType.Element, "Layer", wmsNamespaceURI); + LayerRootNode.AppendChild(CreateElement("Title", "SharpMap", capabilities, false, wmsNamespaceURI)); + LayerRootNode.AppendChild(CreateElement("CRS", "EPSG:" + map.Layers[0].DataSource.CoordinateSystem.AuthorityCode.ToString(), capabilities, false, wmsNamespaceURI)); //TODO LayerRootNode.AppendChild(GenerateBoundingBoxElement(map.GetExtents(), (int) map.Layers[0].DataSource.CoordinateSystem.AuthorityCode, capabilities)); - //This should be changed when Transformation library is complete - XmlElement geoBox = capabilities.CreateElement("EX_GeographicBoundingBox", wmsNamespaceURI); - geoBox.Attributes.Append(CreateAttribute("minx", "-180", capabilities)); - geoBox.Attributes.Append(CreateAttribute("miny", "-90", capabilities)); - geoBox.Attributes.Append(CreateAttribute("maxx", "180", capabilities)); - geoBox.Attributes.Append(CreateAttribute("maxy", "90", capabilities)); - LayerRootNode.AppendChild(geoBox); + //This should be changed when Transformation library is complete + XmlElement geoBox = capabilities.CreateElement("EX_GeographicBoundingBox", wmsNamespaceURI); + geoBox.Attributes.Append(CreateAttribute("minx", "-180", capabilities)); + geoBox.Attributes.Append(CreateAttribute("miny", "-90", capabilities)); + geoBox.Attributes.Append(CreateAttribute("maxx", "180", capabilities)); + geoBox.Attributes.Append(CreateAttribute("maxy", "90", capabilities)); + LayerRootNode.AppendChild(geoBox); foreach (ILayer layer in map.Layers) - LayerRootNode.AppendChild(GetWmsLayerNode(layer, capabilities)); + { + LayerRootNode.AppendChild(GetWmsLayerNode(layer, capabilities)); + } - CapabilityNode.AppendChild(LayerRootNode); - - return CapabilityNode; - } + CapabilityNode.AppendChild(LayerRootNode); - private static XmlNode GenerateDCPTypeNode(XmlDocument capabilities, string OnlineResource) - { - XmlNode DcpType = capabilities.CreateNode(XmlNodeType.Element, "DCPType", wmsNamespaceURI); - XmlNode HttpType = capabilities.CreateNode(XmlNodeType.Element, "HTTP", wmsNamespaceURI); - XmlElement resource = GenerateOnlineResourceElement(capabilities, OnlineResource); + return CapabilityNode; + } - XmlNode GetNode = capabilities.CreateNode(XmlNodeType.Element, "Get", wmsNamespaceURI); - XmlNode PostNode = capabilities.CreateNode(XmlNodeType.Element, "Post", wmsNamespaceURI); - GetNode.AppendChild(resource.Clone()); - PostNode.AppendChild(resource); - HttpType.AppendChild(GetNode); - HttpType.AppendChild(PostNode); - DcpType.AppendChild(HttpType); - return DcpType; - } + private static XmlNode GenerateDCPTypeNode(XmlDocument capabilities, string OnlineResource) + { + XmlNode DcpType = capabilities.CreateNode(XmlNodeType.Element, "DCPType", wmsNamespaceURI); + XmlNode HttpType = capabilities.CreateNode(XmlNodeType.Element, "HTTP", wmsNamespaceURI); + XmlElement resource = GenerateOnlineResourceElement(capabilities, OnlineResource); - private static XmlElement GenerateOnlineResourceElement(XmlDocument capabilities, string OnlineResource) - { - XmlElement resource = capabilities.CreateElement("OnlineResource", wmsNamespaceURI); - XmlAttribute attrType = capabilities.CreateAttribute("xlink", "type", xlinkNamespaceURI); - attrType.Value = "simple"; - resource.Attributes.Append(attrType); - XmlAttribute href = capabilities.CreateAttribute("xlink","href", xlinkNamespaceURI); - href.Value = OnlineResource; - resource.Attributes.Append(href); - XmlAttribute xmlns = capabilities.CreateAttribute("xmlns:xlink"); - xmlns.Value = xlinkNamespaceURI; - resource.Attributes.Append(xmlns); - return resource; - } + XmlNode GetNode = capabilities.CreateNode(XmlNodeType.Element, "Get", wmsNamespaceURI); + XmlNode PostNode = capabilities.CreateNode(XmlNodeType.Element, "Post", wmsNamespaceURI); + GetNode.AppendChild(resource.Clone()); + PostNode.AppendChild(resource); + HttpType.AppendChild(GetNode); + HttpType.AppendChild(PostNode); + DcpType.AppendChild(HttpType); + return DcpType; + } - private static XmlElement GenerateContactInfoElement(XmlDocument capabilities, WmsContactInformation info) - { - XmlElement infoNode = capabilities.CreateElement("ContactInformation", wmsNamespaceURI); - - //Add primary person - XmlElement cpp = capabilities.CreateElement("ContactPersonPrimary", wmsNamespaceURI); - if (info.PersonPrimary.Person != null && info.PersonPrimary.Person != String.Empty) - cpp.AppendChild(CreateElement("ContactPerson", info.PersonPrimary.Person, capabilities, false, wmsNamespaceURI)); - if (info.PersonPrimary.Organisation!=null && info.PersonPrimary.Organisation!=String.Empty) - cpp.AppendChild(CreateElement("ContactOrganization", info.PersonPrimary.Organisation, capabilities, false, wmsNamespaceURI)); - if (cpp.HasChildNodes) - infoNode.AppendChild(cpp); + private static XmlElement GenerateOnlineResourceElement(XmlDocument capabilities, string OnlineResource) + { + XmlElement resource = capabilities.CreateElement("OnlineResource", wmsNamespaceURI); + XmlAttribute attrType = capabilities.CreateAttribute("xlink", "type", xlinkNamespaceURI); + attrType.Value = "simple"; + resource.Attributes.Append(attrType); + XmlAttribute href = capabilities.CreateAttribute("xlink", "href", xlinkNamespaceURI); + href.Value = OnlineResource; + resource.Attributes.Append(href); + XmlAttribute xmlns = capabilities.CreateAttribute("xmlns:xlink"); + xmlns.Value = xlinkNamespaceURI; + resource.Attributes.Append(xmlns); + return resource; + } - if (info.Position != null && info.Position != string.Empty) - infoNode.AppendChild(CreateElement("ContactPosition", info.Position, capabilities, false, wmsNamespaceURI)); + private static XmlElement GenerateContactInfoElement(XmlDocument capabilities, WmsContactInformation info) + { + XmlElement infoNode = capabilities.CreateElement("ContactInformation", wmsNamespaceURI); - //Add address - XmlElement ca = capabilities.CreateElement("ContactAddress", wmsNamespaceURI); - if (info.Address.AddressType != null && info.Address.AddressType != string.Empty) - ca.AppendChild(CreateElement("AddressType", info.Address.AddressType, capabilities, false, wmsNamespaceURI)); - if (info.Address.Address!=null && info.Address.Address != string.Empty) - ca.AppendChild(CreateElement("Address", info.Address.Address, capabilities, false, wmsNamespaceURI)); - if (info.Address.City!=null && info.Address.City != string.Empty) - ca.AppendChild(CreateElement("City", info.Address.City, capabilities, false, wmsNamespaceURI)); - if (info.Address.StateOrProvince!=null && info.Address.StateOrProvince != string.Empty) - ca.AppendChild(CreateElement("StateOrProvince", info.Address.StateOrProvince, capabilities, false, wmsNamespaceURI)); - if (info.Address.PostCode !=null && info.Address.PostCode != string.Empty) - ca.AppendChild(CreateElement("PostCode", info.Address.PostCode, capabilities, false, wmsNamespaceURI)); - if (info.Address.Country!=null && info.Address.Country != string.Empty) - ca.AppendChild(CreateElement("Country", info.Address.Country, capabilities, false, wmsNamespaceURI)); - if (ca.HasChildNodes) - infoNode.AppendChild(ca); + //Add primary person + XmlElement cpp = capabilities.CreateElement("ContactPersonPrimary", wmsNamespaceURI); + if (info.PersonPrimary.Person != null && info.PersonPrimary.Person != String.Empty) + { + cpp.AppendChild(CreateElement("ContactPerson", info.PersonPrimary.Person, capabilities, false, wmsNamespaceURI)); + } + if (info.PersonPrimary.Organisation != null && info.PersonPrimary.Organisation != String.Empty) + { + cpp.AppendChild(CreateElement("ContactOrganization", info.PersonPrimary.Organisation, capabilities, false, wmsNamespaceURI)); + } + if (cpp.HasChildNodes) + { + infoNode.AppendChild(cpp); + } - if (info.VoiceTelephone!=null && info.VoiceTelephone != string.Empty) - infoNode.AppendChild(CreateElement("ContactVoiceTelephone", info.VoiceTelephone, capabilities, false, wmsNamespaceURI)); - if (info.FacsimileTelephone!=null && info.FacsimileTelephone != string.Empty) - infoNode.AppendChild(CreateElement("ContactFacsimileTelephone", info.FacsimileTelephone, capabilities, false, wmsNamespaceURI)); - if (info.ElectronicMailAddress!=null && info.ElectronicMailAddress != string.Empty) - infoNode.AppendChild(CreateElement("ContactElectronicMailAddress", info.ElectronicMailAddress, capabilities, false, wmsNamespaceURI)); + if (info.Position != null && info.Position != string.Empty) + { + infoNode.AppendChild(CreateElement("ContactPosition", info.Position, capabilities, false, wmsNamespaceURI)); + } - return infoNode; - } + //Add address + XmlElement ca = capabilities.CreateElement("ContactAddress", wmsNamespaceURI); + if (info.Address.AddressType != null && info.Address.AddressType != string.Empty) + { + ca.AppendChild(CreateElement("AddressType", info.Address.AddressType, capabilities, false, wmsNamespaceURI)); + } + if (info.Address.Address != null && info.Address.Address != string.Empty) + { + ca.AppendChild(CreateElement("Address", info.Address.Address, capabilities, false, wmsNamespaceURI)); + } + if (info.Address.City != null && info.Address.City != string.Empty) + { + ca.AppendChild(CreateElement("City", info.Address.City, capabilities, false, wmsNamespaceURI)); + } + if (info.Address.StateOrProvince != null && info.Address.StateOrProvince != string.Empty) + { + ca.AppendChild(CreateElement("StateOrProvince", info.Address.StateOrProvince, capabilities, false, wmsNamespaceURI)); + } + if (info.Address.PostCode != null && info.Address.PostCode != string.Empty) + { + ca.AppendChild(CreateElement("PostCode", info.Address.PostCode, capabilities, false, wmsNamespaceURI)); + } + if (info.Address.Country != null && info.Address.Country != string.Empty) + { + ca.AppendChild(CreateElement("Country", info.Address.Country, capabilities, false, wmsNamespaceURI)); + } + if (ca.HasChildNodes) + { + infoNode.AppendChild(ca); + } - private static XmlNode GetWmsLayerNode(ILayer layer, XmlDocument doc) - { - XmlNode LayerNode = doc.CreateNode(XmlNodeType.Element, "Layer", wmsNamespaceURI); - LayerNode.AppendChild(CreateElement("Name", layer.Name, doc, false, wmsNamespaceURI)); - LayerNode.AppendChild(CreateElement("Title", layer.Name, doc, false, wmsNamespaceURI)); - //If this is a grouplayer, add childlayers recursively - if (layer.GetType() == typeof(SharpMap.Layers.GroupLayer)) - foreach (SharpMap.Layers.Layer childlayer in ((SharpMap.Layers.GroupLayer)layer).Layers) - LayerNode.AppendChild(GetWmsLayerNode(childlayer, doc)); - - LayerNode.AppendChild(GenerateBoundingBoxElement(layer.Envelope, (int) layer.DataSource.CoordinateSystem.AuthorityCode, doc)); + if (info.VoiceTelephone != null && info.VoiceTelephone != string.Empty) + { + infoNode.AppendChild(CreateElement("ContactVoiceTelephone", info.VoiceTelephone, capabilities, false, wmsNamespaceURI)); + } + if (info.FacsimileTelephone != null && info.FacsimileTelephone != string.Empty) + { + infoNode.AppendChild(CreateElement("ContactFacsimileTelephone", info.FacsimileTelephone, capabilities, false, wmsNamespaceURI)); + } + if (info.ElectronicMailAddress != null && info.ElectronicMailAddress != string.Empty) + { + infoNode.AppendChild(CreateElement("ContactElectronicMailAddress", info.ElectronicMailAddress, capabilities, false, wmsNamespaceURI)); + } - return LayerNode; - } + return infoNode; + } - private static XmlElement GenerateBoundingBoxElement(IEnvelope bbox, int SRID, XmlDocument doc) - { - XmlElement xmlBbox = doc.CreateElement("BoundingBox", wmsNamespaceURI); - xmlBbox.Attributes.Append(CreateAttribute("minx", bbox.MinX.ToString(SharpMap.Map.numberFormat_EnUS), doc)); - xmlBbox.Attributes.Append(CreateAttribute("miny", bbox.MinY.ToString(SharpMap.Map.numberFormat_EnUS), doc)); - xmlBbox.Attributes.Append(CreateAttribute("maxx", bbox.MaxX.ToString(SharpMap.Map.numberFormat_EnUS), doc)); - xmlBbox.Attributes.Append(CreateAttribute("maxy", bbox.MaxY.ToString(SharpMap.Map.numberFormat_EnUS), doc)); - xmlBbox.Attributes.Append(CreateAttribute("CRS", "EPSG:" + SRID.ToString(), doc)); - return xmlBbox; - } + private static XmlNode GetWmsLayerNode(ILayer layer, XmlDocument doc) + { + XmlNode LayerNode = doc.CreateNode(XmlNodeType.Element, "Layer", wmsNamespaceURI); + LayerNode.AppendChild(CreateElement("Name", layer.Name, doc, false, wmsNamespaceURI)); + LayerNode.AppendChild(CreateElement("Title", layer.Name, doc, false, wmsNamespaceURI)); + //If this is a grouplayer, add childlayers recursively + if (layer.GetType() == typeof(GroupLayer)) + { + foreach (Layer childlayer in ((GroupLayer) layer).Layers) + { + LayerNode.AppendChild(GetWmsLayerNode(childlayer, doc)); + } + } - private static XmlAttribute CreateAttribute(string name, string value, XmlDocument doc) - { - XmlAttribute attr = doc.CreateAttribute(name); - attr.Value = value; - return attr; - } + LayerNode.AppendChild(GenerateBoundingBoxElement(layer.Envelope, (int) layer.DataSource.CoordinateSystem.AuthorityCode, doc)); - private static XmlNode CreateElement(string name, string value, XmlDocument doc, bool IsXml, string namespaceURI) - { - XmlNode node = doc.CreateNode(XmlNodeType.Element, name, namespaceURI); - if (IsXml) - node.InnerXml = value; - else - node.InnerText = value; - return node; - } + return LayerNode; + } - internal static XmlDocument CreateXml() - { - XmlDocument capabilities = new XmlDocument(); - //Set XMLSchema - capabilities.Schemas = new System.Xml.Schema.XmlSchemaSet(); - capabilities.Schemas.Add(GetCapabilitiesSchema()); + private static XmlElement GenerateBoundingBoxElement(IEnvelope bbox, int SRID, XmlDocument doc) + { + XmlElement xmlBbox = doc.CreateElement("BoundingBox", wmsNamespaceURI); + xmlBbox.Attributes.Append(CreateAttribute("minx", bbox.MinX.ToString(Map.numberFormat_EnUS), doc)); + xmlBbox.Attributes.Append(CreateAttribute("miny", bbox.MinY.ToString(Map.numberFormat_EnUS), doc)); + xmlBbox.Attributes.Append(CreateAttribute("maxx", bbox.MaxX.ToString(Map.numberFormat_EnUS), doc)); + xmlBbox.Attributes.Append(CreateAttribute("maxy", bbox.MaxY.ToString(Map.numberFormat_EnUS), doc)); + xmlBbox.Attributes.Append(CreateAttribute("CRS", "EPSG:" + SRID.ToString(), doc)); + return xmlBbox; + } - return capabilities; - } + private static XmlAttribute CreateAttribute(string name, string value, XmlDocument doc) + { + XmlAttribute attr = doc.CreateAttribute(name); + attr.Value = value; + return attr; + } - private static System.Xml.Schema.XmlSchema GetCapabilitiesSchema() - { - //Get XML Schema - System.IO.Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("SharpMap.Web.Wms.Schemas._1._3._0.capabilities_1_3_0.xsd"); - System.Xml.Schema.XmlSchema schema = System.Xml.Schema.XmlSchema.Read(stream, new System.Xml.Schema.ValidationEventHandler(ValidationError)); - stream.Close(); - return schema; - } + private static XmlNode CreateElement(string name, string value, XmlDocument doc, bool IsXml, string namespaceURI) + { + XmlNode node = doc.CreateNode(XmlNodeType.Element, name, namespaceURI); + if (IsXml) + { + node.InnerXml = value; + } + else + { + node.InnerText = value; + } + return node; + } - private static void ValidationError(object sender, System.Xml.Schema.ValidationEventArgs arguments) - { - } - } -} + private static XmlSchema GetCapabilitiesSchema() + { + //Get XML Schema + Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("SharpMap.Web.Wms.Schemas._1._3._0.capabilities_1_3_0.xsd"); + XmlSchema schema = XmlSchema.Read(stream, new ValidationEventHandler(ValidationError)); + stream.Close(); + return schema; + } + + private static void ValidationError(object sender, ValidationEventArgs arguments) {} + + /// + /// Stores contact metadata about WMS service + /// + public struct WmsContactInformation + { + /// + /// Primary contact person + /// + public ContactPerson PersonPrimary; + + /// + /// Position of contact person + /// + public string Position; + + /// + /// Address + /// + public ContactAddress Address; + + /// + /// Telephone + /// + public string VoiceTelephone; + + /// + /// Fax number + /// + public string FacsimileTelephone; + + /// + /// Email address + /// + public string ElectronicMailAddress; + + /// + /// Information about a contact address for the service. + /// + public struct ContactAddress + { + /// + /// Type of address (usually "postal"). + /// + public string AddressType; + + /// + /// Contact address + /// + public string Address; + + /// + /// Contact City + /// + public string City; + + /// + /// State or province of contact + /// + public string StateOrProvince; + + /// + /// Zipcode of contact + /// + public string PostCode; + + /// + /// Country of contact address + /// + public string Country; + } + + /// + /// Information about a contact person for the service. + /// + public struct ContactPerson + { + /// + /// Primary contact person + /// + public string Person; + + /// + /// Organisation of primary person + /// + public string Organisation; + } + } + + /// + /// The Wms Service Description stores metadata parameters for a WMS service + /// + public struct WmsServiceDescription + { + /// + /// Mandatory Human-readable title for pick lists + /// + public string Title; + + /// + /// Optional narrative description providing additional information + /// + public string Abstract; + + /// + /// Optional list of keywords or keyword phrases describing the server as a whole to help catalog searching + /// + public string[] Keywords; + + /// + /// Mandatory Top-level web address of service or service provider. + /// + public string OnlineResource; + + /// + /// Optional WMS contact information + /// + public WmsContactInformation ContactInformation; + + /// + /// The optional element "Fees" may be omitted if it do not apply to the server. If + /// the element is present, the reserved word "none" (case-insensitive) shall be used if there are no + /// fees, as follows: "none". + /// + public string Fees; + + /// + /// The optional element "AccessConstraints" may be omitted if it do not apply to the server. If + /// the element is present, the reserved word "none" (case-insensitive) shall be used if there are no + /// access constraints, as follows: "none". + /// When constraints are imposed, no precise syntax has been defined for the text content of these elements, but + /// client applications may display the content for user information and action. + /// + public string AccessConstraints; + + /// + /// Maximum number of layers allowed (0=no restrictions) + /// + public uint LayerLimit; + + /// + /// Maximum width allowed in pixels (0=no restrictions) + /// + public uint MaxWidth; + + /// + /// Maximum height allowed in pixels (0=no restrictions) + /// + public uint MaxHeight; + + /// + /// Initializes a WmsServiceDescription object + /// + /// Mandatory Human-readable title for pick lists + /// Top-level web address of service or service provider. + public WmsServiceDescription(string title, string onlineResource) + { + Title = title; + OnlineResource = onlineResource; + Keywords = null; + Abstract = ""; + ContactInformation = new WmsContactInformation(); + Fees = ""; + AccessConstraints = ""; + LayerLimit = 0; + MaxWidth = 0; + MaxHeight = 0; + } + } + } +} \ No newline at end of file