I am currently trying to understand the concept of serializing objects to XML with C#. I already got to a point where everything is working fine, but now I got the task to format the XML Output file in such a way, where the elements are side-by-side instead of underneath each other. For example:
This is how it needs to look like
<House>
<Address>
<Street>Some Street</Street><HouseNo>123</HouseNo><State>Texas</State>
</Address>
<House>
But I only manage to get it to look like this:
<House>
<Address>
<Street>Some Street</Street>
<HouseNo>123</HouseNo>
<State>Texas</State>
</Address>
</House>
Is there any way to format the output the way I described in the first example? Any help would be much appreciated.
I already tried to change some XmlWriterSettings
, like Indent
or NewLineHandling
but none have worked so far. I also tried to read the XmlSerializer Code to try and understand what is happening or where to make changes to get to the result I want but that didn't seem to go all well.
CodePudding user response:
You could crate an address class with custom serialization, here is a full working example,
using System;
using System.Diagnostics;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;
using System.Xml.Serialization;
public class Program
{
public static void Main()
{
var houseBefore = new House
{
Address = new FlatAddress
{
Street = "SomeStreet",
HouseNo = "123",
State = "Texas"
}
};
var serializer = new XmlSerializer(typeof(House));
string xml;
using (var writer = new StringWriter())
{
serializer.Serialize(writer, houseBefore);
xml = writer.ToString();
}
Console.WriteLine(xml);
House houseAfter;
using (var reader = new StringReader(xml))
{
houseAfter = serializer.Deserialize(reader) as House;
}
Debug.Assert(houseBefore.Address.Street == houseAfter.Address.Street);
Debug.Assert(houseBefore.Address.HouseNo == houseAfter.Address.HouseNo);
Debug.Assert(houseBefore.Address.State == houseAfter.Address.State);
}
}
public sealed class House
{
public FlatAddress Address { get; set; }
}
public sealed class FlatAddress : IXmlSerializable
{
public string Street { set; get; }
public string HouseNo { set; get; }
public string State { set; get; }
public XmlSchema GetSchema()
{
return default;
}
public void ReadXml(XmlReader reader)
{
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case nameof(Street):
this.Street = reader.ReadElementContentAsString();
break;
case nameof(HouseNo):
this.HouseNo = reader.ReadElementContentAsString();
break;
case nameof(State):
this.State = reader.ReadElementContentAsString();
break;
}
}
}
}
public void WriteXml(XmlWriter writer)
{
writer.WriteElementString(nameof(Street), this.Street);
var houseNoXml = new XElement(nameof(HouseNo), this.HouseNo);
writer.WriteRaw(houseNoXml.ToString());
var stateXml = new XElement(nameof(State), this.State);
writer.WriteRaw(stateXml.ToString());
if (writer.Settings.NewLineHandling == NewLineHandling.Replace)
{
writer.WriteRaw(writer.Settings.NewLineChars);
}
if (writer.Settings.Indent)
{
writer.WriteRaw(writer.Settings.IndentChars);
}
}
}