0

I want to serialize CMainClass:

[XmlType("Param")]
public class CParam
{
    [XmlElement]
    public string Name;
    [XmlElement]
    public object Value;

    public CParam() { }
    public CParam(string name, object value)
    {
        Name = name;
        Value = value;
    }
}

public class CMainClass
{
    public List<CParam> Parameters = new List<CParam>();
    public CMainClass() { }
    public string GetXML()
    {
        XmlDocument doc = new XmlDocument();
        Type[] extraTypes = new Type[1];
        extraTypes[0] = typeof(CParam);
        XmlSerializer serializer = new XmlSerializer(typeof(CMainClass), extraTypes); 
        MemoryStream stream = new MemoryStream();
        try
        {
            serializer.Serialize(stream, this);
            stream.Position = 0;
            doc.Load(stream);
            return doc.InnerXml;
        }
        catch { throw; }
        finally
        {
            stream.Close();
            stream.Dispose();
        }
    }
}

The type of attribute Value can be various, that why object-type is used.

here is test code

        CMainClass mc = new CMainClass();
        mc.Parameters.Add(new CParam("number", 123));
        mc.Parameters.Add(new CParam("text", "lorem ipsum"));
        mc.Parameters.Add(new CParam("price", 23.50));

        string s = mc.GetXML();
        Console.WriteLine(s);
        Console.ReadLine();

All I want is to get output in following form

<?xml version="1.0"?>
<CMainClass>
    <Parameters>
        <Param Name="number" Value="123" />
        <Param Name="text" Value="lorem ipsum" />
        <Param Name="price" Value="23.5" />
    </Parameters>
</CMainClass>

instead of

<?xml version="1.0"?>
<CMainClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Parameters>
        <Param>
            <Name>number</Name>
            <Value xsi:type="xsd:int">123</Value>
        </Param>
        <Param>
            <Name>text</Name>
            <Value xsi:type="xsd:string">lorem ipsum</Value>
        </Param>
        <Param>
            <Name>price</Name>
            <Value xsi:type="xsd:double">23.5</Value>
        </Param>
    </Parameters>
</CMainClass>

Is it possible? Changing property of Value from [XmlElement] to [XmlAttribute] leads to error.

Charles Mager
  • 25,735
  • 2
  • 35
  • 45
Pavel
  • 11
  • 3
  • Are you aware of the memoryleak using that constructor? http://blog.forse.no/xmlserializer-causes-memory-leaks/ – Myrtle Aug 24 '16 at 10:36

2 Answers2

0

If you want to use attributes, then you'll have to specify their types explicitly. The reason for the error you get when trying this is that the serializer doesn't know what type object actually is when deserializing as, unlike elements, it can't use type attributes to indicate this. You will have to change it to string instead and handle the conversion yourself.

public class Param
{     
    [XmlAttribute]
    public string Name { get; set; }
    [XmlAttribute]
    public string Value { get; set; }
}

Also note that your GetXML method can be simplified to just this:

var serializer = new XmlSerializer(typeof(CMainClass));

using (var writer = new StringWriter())
{
    serializer.Serialize(writer, this);
    return writer.ToString();
}  

See this fiddle for a working demo.

Charles Mager
  • 25,735
  • 2
  • 35
  • 45
0

To serialize a class you should add [Serializable()] attribute.

  • This both doesn't answer the question and is factually incorrect - `Serializable` has nothing to do with `XmlSerializer`. – Charles Mager Aug 24 '16 at 14:50