IXmlSerializable. XmlWriter. How to change root element?

256 Views Asked by At

I need to serialize my Invoice model to Xml in 2 different ways.

First serialization should have "FirsName" as root element.

Second "SecondName".

There is different ways to implement, but i don't know how to implement them.

Either to avoid root element and add it manualy, or somehow dynamically preset it.

Here is my model:

public class InvoiceInfo : IXmlSerializable
{
     public int InvoiceId { get; set; }
}

Depending on condition I want to serialize it like:

<firstRoot>
    <invoiceId value="123" />
</firstRoot>

or

<secondRoot>
    <invoiceId value="123" />
</secondRoot>

Maybe it can solved by adjusting XmlWriter.Settings ?

I've found this approuch, but it seems ugly. Because it's kinda post processing...

var duplicate =  XDocument.Parse(xmlDocument.InnerXml);
duplicate.Root.Name = "newRootName";
var res = duplicate.ToString();
2

There are 2 best solutions below

0
On

You can dynamically add XmlRootAttribute:

bool condition = true;

var xmlRoot = new XmlRootAttribute(condition ? "firstRoot" : "secondRoot");

var ser = new XmlSerializer(typeof(InvoiceInfo), xmlRoot);

var invoice = new InvoiceInfo { InvoiceId = 123 };

ser.Serialize(Console.Out, invoice);

Your model

public class InvoiceInfo : IXmlSerializable
{
    public int InvoiceId { get; set; }

    public XmlSchema GetSchema()
    {
        throw new NotImplementedException();
    }

    public void ReadXml(XmlReader reader)
    {
        throw new NotImplementedException();
    }

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteStartElement("invoiceId");
        writer.WriteAttributeString("value", InvoiceId.ToString());
        writer.WriteEndElement();
    }
}

See Dynamically Generated Assemblies - you must cache the assemblies.

1
On

You can use XmlRootAttribute Class and inheritance:

    public abstract class InvoiceInfo 
    {
        public int InvoiceId { get; set; }
    }

    [XmlRoot("firstRoot")]
    public class FirstInvoiceInfo : InvoiceInfo
    {
    }

    [XmlRoot("secondRoot")]
    public class SecondInvoiceInfo : InvoiceInfo
    {
    }