Tim
Tim

Reputation: 1769

XmlSerialisation without root in C#

I have this object

var myObj = new Root
{
    Items = new List<Items>
    {
        new Items { MyValue1 = "test", MyValue2 = 22 },
        new Items { MyValue1 = "test2", MyValue2 = 44 },
    }
};

with

public class Root
{
    public List<Items> Items { get; set; }
}

public class Items
{
    public string MyValue1 { get; set; }
    public int MyValue2 { get; set; }
}

I can serialize it like this :

<Root>
    <Items>
        <Items>
            <MyValue1>test</MyValue1>
            <MyValue2>22</MyValue2>
        </Items>
        <Items>
            <MyValue1>test2</MyValue1>
            <MyValue2>44</MyValue2>
        </Items>
    </Items>
</Root>

But I would like to serialize like :

<Items>
    <MyValue1>test</MyValue1>
    <MyValue2>22</MyValue2>
</Items>
<Items>
    <MyValue1>test2</MyValue1>
    <MyValue2>44</MyValue2>
</Items>

But I can't find a way to do this

This is the reproduction code :

class Program
{
    static void Main(string[] args)
    {
        var myObj = new Root
        {
            Items = new List<Items>
            {
                new Items { MyValue1 = "test", MyValue2 = 22 },
                new Items { MyValue1 = "test2", MyValue2 = 44 },
            }
        };

        var serializer = new XmlSerializer(typeof(Root));
        var ms = new MemoryStream();
        var settings = new XmlWriterSettings { Encoding = new UTF8Encoding(false), OmitXmlDeclaration = true };
        using var xmlWriter = XmlWriter.Create(ms, settings);
        var ns = new XmlSerializerNamespaces();
        ns.Add(string.Empty, string.Empty);
        serializer.Serialize(xmlWriter, myObj, ns);

        var xmlDebug = Encoding.UTF8.GetString(ms.ToArray());

        var result = @"<?xml version=""1.0"" encoding=""utf-8""?><Items><MyValue1>test</MyValue1><MyValue2>22</MyValue2></Items><Items><MyValue1>test2</MyValue1><MyValue2>44</MyValue2></Items>";
        Assert.AreEqual(result, xmlDebug);

    }
}

public class Root
{
    public List<Items> Items { get; set; }
}

public class Items
{
    public string MyValue1 { get; set; }
    public int MyValue2 { get; set; }
}

Upvotes: 3

Views: 525

Answers (2)

TVOHM
TVOHM

Reputation: 2742

Let me preface with I agree with the other comments that this sounds like a bad idea! But also if you are stuck with this as you say, I think you could try something like:

string xml = myObj.Items.Aggregate(seed: new StringBuilder(),
    func: (builder, item) =>
    {
        using var writer = new StringWriter();
        new XmlSerializer(typeof(Items))
            .Serialize(writer, item);
        return builder.AppendLine(writer.ToString());
    }).ToString();

As you want some unusually structured XML, you are working against the intentions of the XmlSerializer. But we can still use it to build up valid serialized XML fragments. The solution aggreagates these valid fragments into a single string with a StringBuilder.

For simplicity I've used a StringWriter, but you can slot in your XmlWriter etc. for pretty print as you require.

Upvotes: 0

Murat Acarsoy
Murat Acarsoy

Reputation: 304

You can use xml attributes in your data models.

public class Root
{
    [XmlElement("Items")]
    public List<Items> Items { get; set; }
}

public class Items
{
    public string MyValue1 { get; set; }
    public int MyValue2 { get; set; }
}

Default xml attribute for "List" is XmlArrayItem, if you use XmlElement for it, this will be your result

<Root>
    <Items>
        <MyValue1>test</MyValue1>
        <MyValue2>22</MyValue2>
    </Items>
    <Items>
        <MyValue1>test2</MyValue1>
        <MyValue2>44</MyValue2>
    </Items>
</Root>

And xml format must have one root node always. If you want to change root node name you can use XmlRoot attribute for Root class.

[XmlRoot("AnotherName")]
public class Root
{
    [XmlElement("Items")]
    public List<Items> Items { get; set; }
}

Upvotes: 1

Related Questions