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];
}
}