CSharp · Console
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Xml.Serialization;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;
using System.IO;
using System.Data;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO.Compression;
// https://stackoverflow.com/questions/50047542/xmlserializer-aborts-reading-after-reader-read?noredirect=1#comment87133934_50047542
public abstract class StreamingXmlSerializableBase : IXmlSerializable
{
// Populate the object with the XmlReader returned by ReadSubtree
protected abstract void Populate(XmlReader reader);
public XmlSchema GetSchema() => null;
public void ReadXml(XmlReader reader)
{
reader.MoveToContent();
// Consume all child nodes of the current element using ReadSubtree()
using (var subReader = reader.ReadSubtree())
{
subReader.MoveToContent();
Populate(subReader);
}
reader.Read(); // Consume the end element itself.
}
public abstract void WriteXml(XmlWriter writer);
}
public abstract class XmlSerializableBase : IXmlSerializable
{
// Populate the object with an XElement loaded from the XmlReader for the current node
protected abstract void Populate(XElement element);
public XmlSchema GetSchema() => null;
public void ReadXml(XmlReader reader)
{
reader.MoveToContent();
var element = (XElement)XNode.ReadFrom(reader);
Populate(element);
}
public abstract void WriteXml(XmlWriter writer);
}
public class SerializableClass : XmlSerializableBase
{
public string Title { get; set; } = "Test title";
public string Description { get; set; } = "Super description";
public int Number { get; set; } = (int)(DateTime.Now.Ticks % 99);
protected override void Populate(XElement element)
{
this.Title = (string)element.Element(nameof(this.Title));
this.Description = (string)element.Element(nameof(this.Description));
// Leave Number unchanged if not present in the XML
this.Number = (int?)element.Element(nameof(this.Number)) ?? this.Number;
}
public override void WriteXml(XmlWriter writer)
{
writer.WriteStartElement(nameof(this.Title));
writer.WriteString(this.Title);
writer.WriteEndElement();
writer.WriteStartElement(nameof(this.Description));
writer.WriteString(this.Description);
writer.WriteEndElement();
writer.WriteStartElement(nameof(this.Number));
// Do not use ToString() as it is locale-dependent.
// Instead use XmlConvert.ToString(), or just writer.WriteValue
writer.WriteValue(this.Number);
writer.WriteEndElement();
}
}
public class MainModel
{
public int Count { get => ChildItems.Count; }
public List<Child> ChildItems { get; set; } = new List<Child>();
public MainModel(bool createDemoContent) : this()
{
if (createDemoContent)
{
ChildItems.Add(new Child() { Id = 0, Nickname = DateTime.Now.ToLongDateString() });
System.Threading.Thread.Sleep(1);
ChildItems.Add(new Child() { Id = 1, Nickname = DateTime.Now.AddHours(-99).ToLongDateString() });
System.Threading.Thread.Sleep(1);
ChildItems.Add(new Child() { Id = 2, Nickname = DateTime.Now.AddDays(-99).ToLongDateString() });
}
}
public MainModel()
{
}
}
public class Child
{
public int Id { get; set; }
public string Nickname { get; set; }
public SerializableClass SerializableClass { get; set; } = new SerializableClass();
}
public class SubChildren
{
public string Title { get; set; }
}
public class TestClass
{
public static void Test()
{
var xml = GetXml();
Test(XElement.Parse(xml).ToString(SaveOptions.None));
Test(XElement.Parse(xml).ToString(SaveOptions.DisableFormatting));
}
static void Test(string xml)
{
var mainModel = xml.LoadFromXml<MainModel>();
var xml2 = mainModel.GetXml();
Console.WriteLine("\nOriginal XML: ");
Console.WriteLine(xml);
Console.WriteLine("\nDeserialized and re-serialized XML: ");
Console.WriteLine(xml2);
Assert.IsTrue(XNode.DeepEquals(XElement.Parse(xml), XElement.Parse(xml2)));
}
static string GetXml()
{
var xml = @"<?xml version=""1.0"" encoding=""utf-8""?>
<MainModel xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"">
<ChildItems>
<Child>
<Id>0</Id>
<Nickname>Freitag, 27. April 2018</Nickname>
<SerializableClass>
<Title>Test title 1</Title>
<Description>Super description 1</Description>
<Number>53</Number>
</SerializableClass>
</Child>
<Child>
<Id>1</Id>
<Nickname>Montag, 23. April 2018</Nickname>
<SerializableClass>
<Title>Test title 2</Title>
<Description>Super description 2</Description>
<Number>79</Number>
</SerializableClass>
</Child>
<Child>
<Id>2</Id>
<Nickname>Donnerstag, 18. Januar 2018</Nickname>
<SerializableClass>
<Title>Test title 3</Title>
<Description>Super description 3</Description>
<Number>9</Number>
</SerializableClass>
</Child>
</ChildItems>
</MainModel>";
return xml;
}
}
public static class XmlSerializationHelper
{
public static T LoadFromXml<T>(this string xmlString, XmlSerializer serial = null)
{
serial = serial ?? new XmlSerializer(typeof(T));
using (var reader = new StringReader(xmlString))
{
return (T)serial.Deserialize(reader);
}
}
public static string GetXml<T>(this T obj, bool omitStandardNamespaces)
{
return obj.GetXml(null, omitStandardNamespaces);
}
public static string GetXml<T>(this T obj, XmlSerializer serializer = null, bool omitStandardNamespaces = false)
{
XmlSerializerNamespaces ns = null;
if (omitStandardNamespaces)
{
ns = new XmlSerializerNamespaces();
ns.Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines.
}
using (var textWriter = new StringWriter())
{
var settings = new XmlWriterSettings() { Indent = true }; // For cosmetic purposes.
using (var xmlWriter = XmlWriter.Create(textWriter, settings))
(serializer ?? new XmlSerializer(obj.GetType())).Serialize(xmlWriter, obj, ns);
return textWriter.ToString();
}
}
}
public class AssertionFailedException : System.Exception
{
public AssertionFailedException() : base() { }
public AssertionFailedException(string s) : base(s) { }
}
public static class Assert
{
public static void IsTrue(bool value)
{
IsTrue(value, "failed");
}
public static void IsTrue(bool value, string message)
{
if (value == false)
throw new AssertionFailedException(message ?? "failed");
}
}
public class Program
{
public static void Main()
{
Console.WriteLine("Roslyn 2.0 Compiler; Environment version: " + Environment.Version);
Console.WriteLine();
try
{
TestClass.Test();
}
catch (Exception ex)
{
Console.WriteLine("Uncaught exception: ");
Console.WriteLine(ex);
throw;
}
}
}