views:

59

answers:

4

I have the following object:

public class MyClass
{
    public int Id { get; set;}
    public string Name { get; set; }
}

I'm wanting to serialize this to the following xml string:

<MyClass>
    <Id>1</Id>
    <Name>My Name</Name>
</MyClass>

Unfortunately, when I use the XMLSerializer I get a string which looks like:

<?xml version="1.0" encoding="utf-8"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;  
    <Id>1</Id>
    <Name>My Name</Name>
</MyClass>

I'm not wanting MyClass to be the root element the document, rather I'm eventually wanting to add the string with other similar serialized objects which will be within a larger xml document.

i.e. Eventually I'll have a xml string which looks like this:

<Classes>
    <MyClass>
        <Id>1</Id>
        <Name>My Name</Name>
    </MyClass>
    <MyClass>
        <Id>1</Id>
        <Name>My Name</Name>
    </MyClass>
</Classes>"

My first thought was to create a class as follows:

public class Classes
{
    public List<MyClass> MyClasses { get; set; }
}

...but that just addes an additional node called MyClasses to wrap the list of MyClass....

My gut feeling is that I'm approaching this the wrong way and that my lack of experience with creating xml files isn't helping to point me to some part of the .NET framework or some other library that simplifies this.

+1  A: 

Don't use the XmlSerializer, but use DataContracts instead. Create a new type Classes, that inherits List<MyClass> like:

[CollectionDataContract(Name = "Classes")]
public class Classes : List<MyClass>
{
}

[DataContract(Name = "MyClass")]
public class MyClass
{
    [DataMember(Name="Id")]
    public int Id { get;set; }
}

Now use the DataContractSerializer to serialize your Classes instance:

Classes myItems = new Classes();
myItems.Add( ... );

DataContractSerializer serializer = new DataContractSerializer(typeof(Classes));
serializer.WriteObject( /* some stream */, myItems);

in response to comment

Use something like this:

[CollectionDataContract(Name = "MyClasses1")]
public class MyClassesOne : List<MyClass> { }

[CollectionDataContract(Name = "MyClasses2")]
public class MyClassesTwo : List<MyClass> { }

[DataContract(Name = "Classes")]
public class Classes {
    [DataMember] public MyClassesOne MyClasses1 { get; set; }
    [DataMember] public MyClassesTwo MyClasses2 { get; set; }
}

It's way more easy to consume by any client.

Jan Jongboom
+1 for this, but I would make the Classes object derive from List<Object> so that he can use a mixed bag of classes instead of restricting the 'classes' node to just MyClass
Adrian Regan
How do I get it to work when I want classes to contain a list of MyClass and MyClass2? I tried making it implement List<object> but it throws a SerializationException...
mezoid
Don't. Rather use something like: `<Classes><MyClasses1>.. list of myclasses1 .. </MyClasses1><MyClasses2> .. list of myclasses2 .. </MyClasses2></Classes>`.
Jan Jongboom
See comment too.
Jan Jongboom
A: 

It shouldn't be a problem for the element to be the root node. You can import it (it'll be the XmlDocument's DocumentElement) into another XmlDocument later on.

Rob
A: 

You could take a look at XStream for .NET. This tutorial shows you how to achieve what you want.

npinti
+1  A: 

You need to use the XmlWriter object - this gives you full control over how the XML will be rendered. You also need to pass a XmlSerializerNamespaces instance to the serializer to get what you need.

The sample program below achieves exactly what you are looking for (notice how the XmlWriter is initialized with XmlWriterSettings, and how the XmlNamespaces instance is passed to the serializer):

    public class MyClass
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }


    class Program
    {
        static void Main(string[] args)
        {
            var xml = new StringBuilder();

            using (var writer = 
                XmlWriter.Create(xml, 
                        new XmlWriterSettings { Indent = true, 
                          ConformanceLevel = ConformanceLevel.Auto, 
                          OmitXmlDeclaration = true }))
            {
                MyClass myClass = new MyClass { Id = 1, Name = "My Name" };

                var ns = new XmlSerializerNamespaces();
                ns.Add("", "");

                var xs = new XmlSerializer(typeof(MyClass), "");
                xs.Serialize(writer, myClass, ns);
            }

            Console.WriteLine(xml.ToString());

            // pause program execution to review results...
            Console.WriteLine("Press enter to exit");
            Console.ReadLine();
        }


//Result:
<MyClass>
<Id>1</Id>
<Name>My Name</Name>
</MyClass>
code4life
Awesome! Thanks man!
mezoid