internal class XmlGeoSerializationFormatter : GeoSerializationFormatter { /// /// Creates an instance of GeoSerializationFormatter. /// public XmlGeoSerializationFormatter() { } /// /// Format a GeoObjectModel into XML, and save the XML into a stream. /// /// The GeoObjectModel to create XML for. /// The Stream to save XML into. protected override void SaveCore(GeoObjectModel model, Stream stream) { if (model.RootNode.Name == "GridFeatureSource") { for (int i = model.RootNode.Children.Count - 1; i >= 0; i--) { if (model.RootNode.Children[i] is GeoObjectNode) { var objectNode = (GeoObjectNode)model.RootNode.Children[i]; if (objectNode.Name == "gridValuesString") { model.RootNode.Children.RemoveAt(i); break; } } } } StreamWriter sw = new StreamWriter(stream, Encoding); using (XmlWriter xmlWriter = XmlWriter.Create(sw, new XmlWriterSettings { Indent = true })) { Save(model.RootNode, xmlWriter); } } /// /// Load a stream that contains XML into a GeoObjectModel. /// /// The Stream that contains XML. /// The GeoObjectModel recreated from the stream. protected override GeoObjectModel LoadCore(Stream stream) { StreamReader sr = new StreamReader(stream, Encoding); using (XmlReader xmlReader = XmlReader.Create(sr)) { GeoObjectNode node = Load(xmlReader); GeoObjectModel model = new GeoObjectModel("GeoObjectModel", node); return model; } } private void Save(GeoObjectNode node, XmlWriter xmlWriter) { //Simple Type if (!string.IsNullOrEmpty(node.Value)) { xmlWriter.WriteElementString(node.Name, node.Value); } else { xmlWriter.WriteStartElement(node.Name); foreach (var attribute in node.Attributes) { xmlWriter.WriteAttributeString(attribute.Key, attribute.Value); } foreach (var child in node.Children) { //remove redundant attributes for children, but not for the top node. //because when we deserialize, we need the type information to create an instance. RemoveRedundant(child); Save(child, xmlWriter); } xmlWriter.WriteEndElement(); } } private static void RemoveRedundant(GeoObjectNode node) { if (string.IsNullOrEmpty(GetAttribute(node,"circularReference"))) { if (string.IsNullOrEmpty(GetAttribute(node,"inherit"))) { RemoveAttribute(node, "type"); } if (string.IsNullOrEmpty(GetAttribute(node,"duplicateReference"))) { RemoveAttribute(node,"hashCode"); } } } internal static void RemoveAttribute(GeoObjectNode node, string attributeName) { if (node.Attributes.ContainsKey(attributeName)) node.Attributes.Remove(attributeName); } internal static string GetAttribute(GeoObjectNode node, string attributeName) { if (node.Attributes.ContainsKey(attributeName)) return node.Attributes[attributeName]; return string.Empty; } private static GeoObjectNode Load(XmlReader xmlReader) { GeoObjectNode rootNode = new GeoObjectNode("root"); GeoObjectNode currentNode = rootNode; while (xmlReader.Read()) { if (xmlReader.NodeType == XmlNodeType.Element) { GeoObjectNode node = new GeoObjectNode(xmlReader.Name); if (xmlReader.HasAttributes) { for (int i = 0; i < xmlReader.AttributeCount; i++) { xmlReader.MoveToAttribute(i); node.Attributes[xmlReader.Name] = xmlReader.Value; } xmlReader.MoveToElement(); } currentNode.Children.Add(node); node.Parent = currentNode; if (!xmlReader.IsEmptyElement) { currentNode = node; } } else if (xmlReader.NodeType == XmlNodeType.Text) { currentNode.Value = xmlReader.Value; } else if (xmlReader.NodeType == XmlNodeType.EndElement) { currentNode = currentNode.Parent; } } if (rootNode.Children == null || rootNode.Children.Count == 0) return null; return rootNode.Children[0]; } }