questions/42716646/order-xml-elements-for-serialization

CSharp · Console

/Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Xml;
using System.IO;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.Threading;
using System.ComponentModel;
using System.Xml.Linq;
using System.Reflection;
using System.Data;
using System.Xml.Schema;
using System.Text.RegularExpressions;
using System.Net;
using System.Xml.XPath;
using System.Globalization;
using System.Collections;
					
    // https://stackoverflow.com/questions/42716646/order-xml-elements-for-serialization


    public class Service
    {
        [XmlAttribute("__serviceType")]
        public string ServiceType { get; set; }

        [XmlIgnore]
        public Perform Perform { get; set; }

        [XmlIgnore]
        public List<InputData> InputData { get; set; }

        [XmlElement("__perform", Type = typeof(Perform))]
        [XmlElement("__inputData", Type = typeof(InputData))]
        public object[] XmlInputAndPerformance
        {
            get
            {
                var inputData = (InputData ?? Enumerable.Empty<InputData>()).Cast<object>();
                var performData = Perform == null ? Enumerable.Empty<object>() : new object[] { Perform };

                return inputData.Take(1)
                    .Concat(performData)
                    .Concat(inputData.Skip(1))
                    .ToArray();
            }
            set
            {
                if (value == null)
                    return;
                var newInputs = value.OfType<InputData>().ToList();
                var newPerform = value.OfType<Perform>().ToList();
                if (newInputs.Count + newPerform.Count != value.Length)
                    throw new ArgumentException("Unknown type.");
                if (newPerform.Count > 1)
                    throw new ArgumentException("Too many Perform objects.");

                if (newPerform.Count > 0)
                    Perform = newPerform[0];
                (InputData = InputData ?? new List<InputData>()).AddRange(newInputs);
            }
        }

        [XmlElement("__execute")]
        public Execute Execute { get; set; }

        [XmlElement("__requestData")]
        public RequestData RequestData { get; set; }

        public Service() { }
    }

    [XmlRoot(ElementName = "__execute")]
    public class Execute
    {
    }

    [XmlRoot(ElementName = "BaseToChange")]
    public class BaseToChange
    {
        [XmlElement(ElementName = "__name")]
        public string __name { get; set; }
    }

    [XmlRoot(ElementName = "__inputData")]
    public class InputData
    {
        [XmlElement(ElementName = "BaseToChange")]
        public BaseToChange BaseToChange { get; set; }
        [XmlElement(ElementName = "ObjectChanges")]
        public ObjectChanges ObjectChanges { get; set; }
    }

    [XmlRoot(ElementName = "__perform")]
    public class Perform
    {
        [XmlElement(ElementName = "__eventName")]
        public string __eventName { get; set; }
    }

    [XmlRoot(ElementName = "ObjectChanges")]
    public class ObjectChanges
    {
        [XmlElement(ElementName = "Name")]
        public string Name { get; set; }
    }

    [XmlRoot(ElementName = "__requestData")]
    public class RequestData
    {
        [XmlElement(ElementName = "CompletionMsg")]
        public string CompletionMsg { get; set; }
    }

    [XmlRoot(ElementName = "__Root")]
    public class __Root
    {
        [XmlElement(ElementName = "__service")]
        public Service __service { get; set; }
        [XmlAttribute(AttributeName = "__version")]
        public string __version { get; set; }
        [XmlAttribute(AttributeName = "__encryption")]
        public string __encryption { get; set; }
    }

    static class TestClass
    {
        static string GetXml()
        {
            var xml = @"<?xml version=""1.0""?>
<__Root __version=""1.1"" __encryption=""2"">
  <__service __serviceType=""Test"">
  <__inputData>
   <BaseToChange>
    <__name>TestName</__name>
   </BaseToChange>
  </__inputData>
  <__perform> 
   <__eventName>Event</__eventName>
  </__perform>    
  <__inputData>
      <ObjectChanges>
        <Name>Test</Name>
      </ObjectChanges>
    </__inputData>
    <__execute />
    <__requestData>
      <CompletionMsg />
    </__requestData>
  </__service>
</__Root>";
            return xml;
        }

        public static void Test()
        {
            Test0();

            Console.WriteLine("");

            Test1();
        }

        public static void Test0()
        {
            var xml = GetXml();

            Console.WriteLine("Testing input XML: ");
            Console.WriteLine(xml);

            var root = xml.LoadFromXml<__Root>();

            var xml2 = root.GetXml(true);

            Console.WriteLine("\nDeserialized and re-serialized XML: ");
            Console.WriteLine(xml2);

            var ok = XNode.DeepEquals(XElement.Parse(xml), XElement.Parse(xml2));
            if (!ok)
                throw new AssertionFailedException("Original and re-serialized XML are NOT equivalent.");
            else
                Console.WriteLine("Original and re-serialized XML are equivalent.");
        }

        private static void Test1()
        {
            Console.WriteLine("Testing empty {0}", typeof(__Root));

            var root3 = new __Root() { __service = new Service() };
            var xml3 = root3.GetXml();
            Console.WriteLine(xml3);
            var root4 = xml3.LoadFromXml<__Root>();
            var xml4 = root4.GetXml();
            Console.WriteLine(xml4);
        }
    }


	public class Program
	{
		public static void Main()
		{
			TestClass.Test();
		}
	}

    public static class XmlSerializationHelper
    {
        public static T LoadFromXml<T>(this string xmlString, XmlSerializer serial = null)
        {
            serial = serial ?? new XmlSerializer(typeof(T));
            T returnValue = default(T);
            using (StringReader reader = new StringReader(xmlString))
            {
                object result = serial.Deserialize(reader);
                if (result is T)
                {
                    returnValue = (T)result;
                }
            }
            return returnValue;
        }

        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)
        {
            if (value == false)
                throw new AssertionFailedException("failed");
        }
    }
;