using System.Collections.Generic;
using System.Xml.Serialization;
public abstract class UientryItem;
[XmlType("u"), XmlRoot("u")]
public class UientryId : UientryItem
[XmlText] public string Value { get; set; }
[XmlType("s"), XmlRoot("s")]
public class UientryTitle : UientryItem
[XmlText] public string Value { get; set; }
[XmlType("no"), XmlRoot("no")]
public class UientryNo : UientryItem;
[XmlType("yes"), XmlRoot("yes")]
public class UientryYes : UientryItem;
[XmlType("byte"), XmlRoot("byte")]
public class UientryByte : UientryItem
[XmlText] public byte Value { get; set; }
[XmlType("unicode"), XmlRoot("unicode")]
public class UientryUnicode : UientryItem
[XmlText] public string Value { get; set; }
[XmlType("i"), XmlRoot("i")]
public class UientryInt : UientryItem
[XmlText] public int Value { get; set; }
[XmlType("images"), XmlRoot("images")]
public class UientryImages : UientryItem
public int Count { get => Images?.Count?? 0; set { } }
public List<UientryImage> Images { get; set; } = new();
[XmlType("image"), XmlRoot("image")]
public class UientryImage
[XmlElement(typeof(UientryId)),
XmlElement(typeof(UientryTitle)),
XmlElement(typeof(UientryNo)),
XmlElement(typeof(UientryYes)),
XmlElement(typeof(UientryByte)),
XmlElement(typeof(UientryUnicode)),
XmlElement(typeof(UientryInt)),
XmlElement(typeof(UientryImages)),
XmlElement(typeof(UientryStates)),
XmlElement(typeof(UientryChildren)),
XmlElement(typeof(UientryAdditionalData))]
public List<UientryItem> Items { get; set; } = new();
[XmlType("states"), XmlRoot("states")]
public class UientryStates : UientryItem
[XmlAttribute("count")] public int Count { get; set; }
[XmlType("children"), XmlRoot("children")]
public class UientryChildren : UientryItem
[XmlAttribute("count")] public int Count { get; set; }
[XmlType("additional_data"), XmlRoot("additional_data")]
public class UientryAdditionalData : UientryItem
[XmlAttribute("type")] public string Type { get; set; }
[XmlType("uientry"), XmlRoot("uientry")]
[XmlElement(typeof(UientryId)),
XmlElement(typeof(UientryTitle)),
XmlElement(typeof(UientryNo)),
XmlElement(typeof(UientryYes)),
XmlElement(typeof(UientryByte)),
XmlElement(typeof(UientryUnicode)),
XmlElement(typeof(UientryInt)),
XmlElement(typeof(UientryImages)),
XmlElement(typeof(UientryStates)),
XmlElement(typeof(UientryChildren)),
XmlElement(typeof(UientryAdditionalData))]
public List<UientryItem> Items { get; set; } = new();
public static void Test()
var xmlString = GetXml();
using var textReader = new StringReader(xmlString);
var serializer = new XmlSerializer(typeof(Uientry));
var uiEntry = (Uientry)serializer.Deserialize(textReader);
var xml2 = uiEntry.GetXml(omitStandardNamespaces : true);
Console.WriteLine("Re-serialized {0}:\n", uiEntry);
Assert.That(XNode.DeepEquals(XElement.Parse(xmlString).NormalizeEmptyElements(), XElement.Parse(xml2).NormalizeEmptyElements()));
static string GetXml() =>
<u>606917248</u><!-- ID (80 d2 2c 24) -->
<s>root</s><!-- title -->
<s>CampaignRoot</s><!-- title2 -->
<i>0</i><!-- x offset -->
<i>0</i><!-- y offset -->
<no /><!-- uientry flag 1 -->
<yes /><!-- uientry flag 2 -->
<byte>1</byte><!-- uientry flag 3 -->
<no /><!-- uientry flag 4 -->
<no /><!-- uientry flag 5 -->
<no /><!-- uientry flag 6 -->
<no /><!-- uientry flag 7 -->
<yes /><!-- uientry flag 8 -->
<no /><!-- uientry flag 9 -->
<no /><!-- uientry flag 10 -->
<no /><!-- uientry flag 11 -->
<no /><!-- uientry flag 12 -->
<unicode></unicode><!-- tooltip text -->
<unicode></unicode><!-- tooltip id -->
<i>0</i><!-- 00:00:00:00 --><!-- docking? -->
<i>0</i><!-- 00:00:00:00 --><!-- docking x? -->
<i>0</i><!-- 00:00:00:00 --><!-- docking y? -->
<i>0</i><!-- default state id -->
<u>606535040</u><!-- ID (80 fd 26 24) -->
<i>1280</i><!-- x size -->
<i>960</i><!-- y size -->
<i>0</i><!-- 00:00:00:00 --><!-- mask image? -->
<additional_data type="none" />
public static class XmlSerializationHelper
public static T LoadFromXml<T>(this string xmlString, XmlSerializer serializer = null)
using (var reader = new StringReader(xmlString))
return (T)(serializer ?? new(typeof(T))).Deserialize(reader);
public static string GetXml<T>(this T obj, bool omitStandardNamespaces) =>
obj.GetXml(null, omitStandardNamespaces);
public static string GetXml<T>(this T obj, XmlSerializer serializer = null, bool omitStandardNamespaces = false)
XmlSerializerNamespaces ns = null;
if (omitStandardNamespaces)
using var textWriter = new StringWriter();
var settings = new XmlWriterSettings() { Indent = true };
using (var xmlWriter = XmlWriter.Create(textWriter, settings))
(serializer ?? new(obj.GetType())).Serialize(xmlWriter, obj, ns);
return textWriter.ToString();
public static string GetOuterXml(this XmlNode node, bool indent = true)
using var textWriter = new StringWriter();
var settings = new XmlWriterSettings
OmitXmlDeclaration = true,
using (var xmlWriter = XmlWriter.Create(textWriter, settings))
return textWriter.ToString();
public static class XmlAssert
public static XElement NormalizeEmptyElements(this XElement root)
foreach (XElement child in root.DescendantsAndSelf().Where(e => e.IsEmpty))
child.Value = string.Empty;
root.DescendantNodes().OfType<XComment>().Remove();
public static void Main()
Console.WriteLine("Environment version: {0} ({1}), {2}", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription, Environment.Version, Environment.OSVersion);
Console.WriteLine("Uncaught exception: ");