is it possible to use C# XmlSerialization API to store single class in two different ways ?
For example
class Test
{
int group1_attr1;
int group1_attr2;
int group2_attr1;
}
I would like to have a way how to split class fields into two parts(groups - with specified attributes) and each time I call Serialize to control which part will be stored. For example if saving as group1
<?xml version="1.0" encoding="utf-8"?>
<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org /2001/XMLSchema">
<group1_attr1>0</group1_attr1>
<group1_attr2>0</group1_attr2>
</Test>
if saving as group2
<?xml version="1.0" encoding="utf-8"?>
<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org /2001/XMLSchema">
<group2_attr1>0</group2_attr1>
</Test>
Is there a way how to do it in a "clean" way ? If not in xmlserialization then in binary perhaps ?
Then I would like to know what is the best way how to merge those two files into single instance of Test. (Note that fields from group1 and group2 do not overlap)
Here's code demonstrating how to serialize like you want, however, deserialization will be more tricky because it's not straightforward to deserialize into an existing instance (see How to use XmlSerializer to deserialize into an existing instance?).
public class Test
{
public int group1_attr1;
public int group1_attr2;
public int group2_attr1;
}
class Program
{
static void Main(string[] args)
{
System.Xml.Serialization.XmlAttributes xa =
new System.Xml.Serialization.XmlAttributes();
xa.XmlIgnore = true;
System.Xml.Serialization.XmlAttributeOverrides xo1 =
new System.Xml.Serialization.XmlAttributeOverrides();
xo1.Add(typeof(Test), "group1_attr1", xa);
xo1.Add(typeof(Test), "group1_attr2", xa);
System.Xml.Serialization.XmlAttributeOverrides xo2 =
new System.Xml.Serialization.XmlAttributeOverrides();
xo2.Add(typeof(Test), "group2_attr1", xa);
System.Xml.Serialization.XmlSerializer xs1 =
new System.Xml.Serialization.XmlSerializer(typeof(Test), xo1);
System.Xml.Serialization.XmlSerializer xs2 =
new System.Xml.Serialization.XmlSerializer(typeof(Test), xo2);
Test t1 = new Test();
t1.group1_attr1 = 1;
t1.group1_attr2 = 2;
t1.group2_attr1 = 3;
using (System.IO.StringWriter sw = new System.IO.StringWriter())
{
xs1.Serialize(sw, t1);
Console.WriteLine(sw);
}
using (System.IO.StringWriter sw = new System.IO.StringWriter())
{
xs2.Serialize(sw, t1);
Console.WriteLine(sw);
}
}
}
The deserialization could maybe merge the XML before deserializing:
Test t2 = new Test();
System.Xml.Serialization.XmlSerializer xs3 = new System.Xml.Serialization.XmlSerializer(typeof(Test));
string mergedXml = MergeSerializedXml(group1, group2);
using (System.IO.StringReader sr = new System.IO.StringReader(mergedXml))
{
t2 = (Test)xs3.Deserialize(sr);
}
...
static string MergeSerializedXml(string x1, string x2)
{
System.Xml.XmlDocument xd = new System.Xml.XmlDocument();
xd.LoadXml(x1);
System.Xml.XmlReaderSettings xrs = new System.Xml.XmlReaderSettings();
xrs.IgnoreWhitespace = true;
using (System.Xml.XmlReader xr = System.Xml.XmlReader.Create(new System.IO.StringReader(x2), xrs))
{
while (xr.Read() && !xr.IsStartElement())
;
xr.MoveToContent();
xr.Read();
System.Xml.XmlNode xn = xd.ChildNodes[1];
do
{
xn.AppendChild(xd.ReadNode(xr));
} while (xr.NodeType != System.Xml.XmlNodeType.EndElement);
}
return xd.OuterXml;
}
Composition will sort of allow you to do this, http://en.wikipedia.org/wiki/Composition_over_inheritance. If you serialize CompositeGroup1 then stick it in an instance of CompositeData. Do the same for CompositeGroup2. There's no way to do what you are asking for, as you asked it, with the built in serializers. When you serialize data it will always generate the full serialization for that type.
class CompositeData
{
public CompositeGroup1 Group1 { get; set; }
public CompositeGroup2 Group2 { get; set; }
}
class CompositeGroup1
{
public int Attr1 { get; set; }
public int Attr2 { get; set; }
}
class CompositeGroup2
{
public int Attr1 { get; set; }
}
You could also consider making CompositeData implement abstract classes, one for each grouping. You can use some other JSON serializers that use the type passed in instead of the runtime type to generate the serialized data.
var json1 = serializer.Serialize<AbstractGroup1>(new CompositeData());
var json2 = serializer.Serialize<AbstractGroup2>(new CompositeData());
However, putting them back together again would still be your problem.
You can loook into my project, Xml Serialization Framework, that will use interfaces idiom to solve the same issue as you might have
Example:
To serialize class instance/object
class Person
{
public string Name { get; set; }
}
you would probably declare interfaces to use in metadata driven xml runtime serialization:
interface IPersonRoot
{
string Name { get; set; }
}
[XmlRootSerializer("Body")]
interface IPersonCustomRoot
{
string Name { get; set; }
}
interface IPersonCustomAttribute
{
[XmlAttributeRuntimeSerializer("Id")]
string Name { get; set; }
}
This framework supports even working with partial update of living instances using particular interfaces/XML formats:
to/from XML using IPersonRoot interface:
<Person>
<Name>John Doe</Name>
</Person>
to/from XML using IPersonCustomRoot interface:
<Body>
<Name>John Doe</Name>
</Body>
to/from XML using IPersonCustomAttribute interface:
<Person Id="John Doe" />
Have a nice day,
Cheers ;)
Artur M.
Related
Below piece of code is failing and throwing ArgumentException
static void Main(string[] args)
{
string xml = "<root><SourcePatient><Communication>HP:6055550120</Communication></SourcePatient></root>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
var serializedString = JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.None,true);
var deserialise = serializedString.ToObject<SampleModel>();
}
Models are,
public class SampleModel
{
public SourcePatientModel SourcePatient { get; set; }
}
public class SourcePatientModel
{
public List<string> Communication { get; set; }
}
How to deserialize this? Sometimes Communication node from xml string will have multiple entries
Your current xml is only a single entry
<Communication>HP:6055550120</Communication>
Change your xml input
<Communication><Entry>HP:6055550120</Entry></Communication>
So later when you get multiple entries, they can be processed
<Communication><Entry>HP:6055550120</Entry><Entry>HP:xxxxxxxxx</Entry></Communication>
Your class needs tweaked a bit
if a string [] is acceptable
[XmlArray(ElementName = "Communication")]
[XmlArrayItem(ElementName = "Entry")]
public string[] comm_list // Whatever name you want here
{
get; set;
}
// if you want a list here
// also if your going to do this, realize it creates a new list every time you use it, not the best. (bad practice)
List<string> Communication
{
get => new List<string>(comm_list );
}
otherwise it gets a little complicated
[XmlRoot(ElementName="Communication")]
public class Communication // element name by def
{
[XmlElement(ElementName="Entry")]
public List<string> entry { get; set; }
}
Another possibility, not sure how your multiple entries come in.
If multiple entries look like the following
<Communication>HP:6055550120, HP:7055550120</Communication>
Then you cant have a direct list,
public class SourcePatientModel
{
public string Communication { get; set; }
// which again this creates a list everytime, its better to change your xml to match a tag name for each entry
[XmlIgnore]
public List<string> CommunicationValues { get => Communication.Split(',').ToList();
}
Also this is just typed up code, there may be some typos or compile errors
First I parsed xml to the valid model, then you can convert to json if needed
using (TextReader sr = new StringReader(xml))
{
XmlSerializer serializer = new XmlSerializer(typeof(SampleModel));
var schema = (SampleModel)serializer.Deserialize(sr);
}
[Serializable, XmlRoot("root")]
public class SampleModel
{
public SourcePatientModel SourcePatient { get; set; }
}
public class SourcePatientModel
{
[XmlElement("Communication")]
public List<string> Communication { get; set; }
}
I modified your classes to include some XML serialization attributes. (More on how to figure those out later - the short version is that you don't have to figure it out.)
[XmlRoot(ElementName = "SourcePatient")]
public class SourcePatientModel
{
[XmlElement(ElementName = "Communication")]
public List<string> Communication { get; set; }
}
[XmlRoot(ElementName = "root")]
public class SampleModel
{
[XmlElement(ElementName = "SourcePatient")]
public SourcePatientModel SourcePatientModel { get; set; }
}
...and this code deserializes it:
var serializer = new XmlSerializer(typeof(SampleModel));
using var stringReader = new StringReader(xmlString);
SampleModel deserialized = (SampleModel) serializer.Deserialize(stringReader);
Here's a unit test to make sure a test XML string is deserialized with a list of strings as expected. A unit test is a little easier to run and repeat than a console app. Using them makes writing code a lot easier.
[Test]
public void DeserializationTest()
{
string xmlString = #"
<root>
<SourcePatient>
<Communication>A</Communication>
<Communication>B</Communication>
</SourcePatient>
</root>";
var serializer = new XmlSerializer(typeof(SampleModel));
using var stringReader = new StringReader(xmlString);
SampleModel deserialized = (SampleModel) serializer.Deserialize(stringReader);
Assert.AreEqual(2, deserialized.SourcePatientModel.Communication.Count);
}
Here's a key takeaway: You don't need to memorize XML serialization attributes. I don't bother because I find them confusing. Instead, google "XML to Csharp" and you'll find sites like this one. I pasted your XML into that site and let it generate the classes for me. (Then I renamed them so that they matched your question.)
But be sure that you include enough sample data in your XML so that it can generate the classes for you. I made sure there were two Communication elements so it would create a List<string> in the generated class.
Sites like that might not work for extremely complicated XML, but they work for most scenarios, and it's much easier than figuring out how to write the classes ourselves.
I need to convert the XML string to List, the method should be generic. I wrote a method but its not performing as expected.
Scenario: #1
Model Class:
public class Employee {
public int EmpId { get; set; }
public string Name { get; set; }
}
XML:
<EmployeeList
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Employee>
<EmpId>1</EmpId>
<Name>Emma</Name>
</Employee>
<Employee>
<EmpId>2</EmpId>
<Name>Watson</Name>
</Employee>
</EmployeeList>
Scenario: #2
Model Class:
public class Person {
public int PersonId { get; set; }
public string Name { get; set; }
}
XML:
<PersonList
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Person>
<PersonId>1</EmpId>
<Name>Emma</Name>
</Person>
<Person>
<PersonId>2</EmpId>
<Name>Watson</Name>
</Person>
</PersonList>
I need a generic method to Convert the above said XML's to List<Employee> and List<Person>.
I used the following code
public static T[] ParseXML<T>(this string #this) where T : class {
var reader = XmlReader.Create(#this.Trim().ToStream(),new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Document });
return new XmlSerializer(typeof(T[])).Deserialize(reader) as T[];
}
But I'm getting NULL. Kindly assist me how to handle this.
I refereed lots of code but they are telling to specify the Root element as hard-coded value. But I need a generic method.
The Signature should be
public static T[] ParseXML<T>(this string #this) where T : class { }
Kindly assist me in this regards.
The default root name is ArrayOfThing, not ThingList, so you will need to tell the serializer:
var ser = new XmlSerializer(list.GetType(), new XmlRootAttribute("EmployeeList"));
However, you'll also need to cache and re-use this to prevent assembly memory leaks (only the most basic constructors automatically cache). A static read-only field on a generic type is a good bet, for example:
static class SerializerCache<T> {
public static readonly XmlSerializer Instance = new XmlSerializer(
typeof(List<T>), new XmlRootAttribute(typeof(T).Name + "List"));
}
then use SerializerCache<T>.Instance instead of new XmlSerializer
Obviously swap lists and arrays if you like...
I derived the answer from Marc Gravell - Convert XML string to List<T> without specifiying Element Root in C#, which I was marked as Correct.
public static class SerializerCache<T> {
public static readonly XmlSerializer Instance = new XmlSerializer(
typeof(List<T>), new XmlRootAttribute(typeof(T).Name + "List"));
}
public static class XMLHelper {
public static List<T> ParseXML<T>(this string #this) where T : class {
XmlSerializer serializer = SerializerCache<T>.Instance;
MemoryStream memStream = new MemoryStream(Encoding.UTF8.GetBytes(#this));
if(!string.IsNullorEmpty(#this) && (serializer != null) && (memStream != null)) {
return serializer.Deserialize(memStream) as List<T>;
}
else {
return null;
}
}
}
The Main Method is looks like
public static List<Employee> GetEmployeeList(string xml) {
return xml.ParseXML<Employee>();
}
I have a class which I need to serialize using XMLserializer in C#
[DataContract]
Public class X
{
[Datamember]
Public List<string> CodeList {get;set;}
}
But as the Data type of CodeList is string, I am getting below xml
<CodeList>
<string>asd</string>
<string>cvb</string>
</CodeList>
But I want to show the xml in the format wherein string is shown as code i.e I want to give string an alias name of code.
<CodeList>
<Code>asd</Code>
<Code>cvb</Code>
</CodeList>
You mention using the XMLSerializer but you are using attributes for the DataContractSerializer. If you stick to using the XMLSerializer it is dead simple.
class Program
{
static void Main(string[] args)
{
X x = new X();
x.CodeList = new List<string>() {"test", "test1"};
var xml = new XmlSerializer(typeof (X));
TextWriter writer = new StreamWriter("test.xml");
xml.Serialize(writer,x);
writer.Close();
}
}
public class X
{
[XmlArrayItem("Code")]
public List<string> CodeList { get; set; }
}
You notice that I don't need any attributes other than the [XmlArrayItem]. That is because the XmlSerializer will go ahead and serialize all public properties. If that is a problem, you can use the [System.Xml.Serialization.XmlIgnoreAttribute], which will ignore a property while serializing.
This is the output I got from my code above:
<?xml version="1.0" encoding="utf-8"?>
<X xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CodeList>
<Code>test</Code>
<Code>test1</Code>
</CodeList>
</X>
I have different kinds of objects in c# that I would like to save to a file (XML is preferred) but I can't use serialization since the class are not written by me but are from a DLL.
What is the best solution for this ?
I eventually used JavaScriptSerializer and it does exactly what I was looking for:
List<Person> persons = new List<Person>();
persons.Add(new Person(){Name = "aaa"});
persons.Add(new Person() { Name = "bbb" });
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
var strData = javaScriptSerializer.Serialize(persons);
var persons2 = javaScriptSerializer.Deserialize<List<Person>>(strData);
I've whipped up a quick little extension method that will "serialize" to XML, given a non-serializable object. It's pretty rough and doesn't do a heck of a lot of checking and the XML it generates you can easily tweak to meet your needs:
public static string SerializeObject<T>(this T source, bool serializeNonPublic = false)
{
if (source == null)
{
return null;
}
var bindingFlags = BindingFlags.Instance | BindingFlags.Public;
if (serializeNonPublic)
{
bindingFlags |= BindingFlags.NonPublic;
}
var properties = typeof(T).GetProperties(bindingFlags).Where(property => property.CanRead).ToList();
var sb = new StringBuilder();
using (var writer = XmlWriter.Create(sb))
{
writer.WriteStartElement(typeof(T).Name);
if (properties.Any())
{
foreach (var property in properties)
{
var value = property.GetValue(source, null);
writer.WriteStartElement(property.Name);
writer.WriteAttributeString("Type", property.PropertyType.Name);
writer.WriteAttributeString("Value", value.ToString());
writer.WriteEndElement();
}
}
else if (typeof(T).IsValueType)
{
writer.WriteValue(source.ToString());
}
writer.WriteEndElement();
}
return sb.ToString();
}
I tested it on this class:
private sealed class Test
{
private readonly string name;
private readonly int age;
public Test(string name, int age)
{
this.name = name;
this.age = age;
}
public string Name
{
get
{
return this.name;
}
}
public int Age
{
get
{
return this.age;
}
}
}
as well as the number 3 and object. The resulting XML is as such:
<?xml version="1.0" encoding="utf-16"?>
<Test>
<Name Type="String" Value="John Doe" />
<Age Type="Int32" Value="35" />
</Test>
<?xml version="1.0" encoding="utf-16"?>
<Int32>3</Int32>
<?xml version="1.0" encoding="utf-16"?>
<Object />
respectively.
write your own serializable wrappers around the non-serializable classes of the DLL.
EDIT: AutoMapper was suggested in the comments and I hadn't heard of it yet, but now that I have I'd definitely use that instead of writing the wrappers myself. Unless there's some reflection required to capture some of the internal state of the non-serializable object (if possible), I don't know if AutoMapper has anything to offer there or you'd have to see if you could capture that in your wrapper.
I would write a POCO (Plain Old Class Object) class that mimics the object from the DLL returned. Generally if you are using, I believe, .NET 3.5 or higher you have the ability to use LINQ. I favor Linq to put objects into other classes or perform sorting or other operations on them.
Here is a simple example where you would be dummying in your return object for example. Keep in mind in a DLL of course you could have many differing objects and do this multiple times. I also would wrap my methods up in their own class for re usability instead of doing it in the main. But here is a simple proof of concept
using System;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using System.Xml.Serialization;
using System.Collections.Generic;
using System.Xml.Linq;
namespace ExampleSerializer
{
class Program
{
// example class to serialize
[Serializable]
public class SQLBit
{
[XmlElement("Name")]
public string Name { get; set; }
[XmlText]
public string data { get; set; }
}
// example class to populate to get test data
public class example
{
public string Name { get; set; }
public string data { get; set; }
}
static void Main(string[] args)
{
string s = "";
// make a generic and put some data in it from the test
var ls = new List<example> { new example { Name = "thing", data = "data" }, new example { Name = "thing2", data = "data2" } };
// make a second generic and put data from the first one in using a lambda
// statement creation method. If your object returned from DLL is a of a
// type that implements IEnumerable it should be able to be used.
var otherlist = ls.Select(n => new SQLBit
{
Name = n.Name,
data = n.data
});
// start a new xml serialization with a type.
XmlSerializer xmler = new XmlSerializer(typeof(List<SQLBit>));
// I use a textwriter to start a new instance of a stream writer
TextWriter twrtr = new StreamWriter(#"C:\Test\Filename.xml");
// Serialize the stream to the location with the list
xmler.Serialize(twrtr, otherlist);
// Close
twrtr.Close();
// TODO: You may want to put this in a try catch wrapper and make up your
// own classes. This is a simple example.
}
}
}
I think the term "without-serialization" in the question header is misleading.
If i understood you correctly you want to serialize objects that have no serilisation-attributes.
There are libraries like sharpserializer and protobuf-net that can do the job for you.
My app serializes objects in streams.
Here is a sample of what I need :
<links>
<link href="/users" rel="users" />
<link href="/features" rel="features" />
</links>
In this case, the object is a collection of 'links' object.
-----------First version
At first I used the DataContractSerializer, however you cannot serialize members as attributes (source)
Here is the object :
[DataContract(Name="link")]
public class LinkV1
{
[DataMember(Name="href")]
public string Url { get; set; }
[DataMember(Name="rel")]
public string Relationship { get; set; }
}
And here is the result :
<ArrayOflink xmlns:i="...." xmlns="...">
<link>
<href>/users</href>
<rel>users</rel>
</link>
<link>
<href>/features</href>
<rel>features</rel>
</link>
</ArrayOflink>
----------- Second version
Ok, not quiet what I want, so I tried the classic XmlSerializer, but... oh nooo, you cannot specify the name of the root element & of the collection's elements if the root element is a collection...
Here is the code :
[XmlRoot("link")]
public class LinkV2
{
[XmlAttribute("href")]
public string Url { get; set; }
[XmlAttribute("rel")]
public string Relationship { get; set; }
}
Here is the result :
<ArrayOfLinkV2>
<LinkV2 href="/users" rel="users" />
<LinkV2 href="/features" rel="features" />
<LinkV2 href="/features/user/{keyUser}" rel="featuresByUser" />
</ArrayOfLinkV2>
----------- Third version
using XmlSerializer + a root element :
[XmlRoot("trick")]
public class TotallyUselessClass
{
[XmlArray("links"), XmlArrayItem("link")]
public List<LinkV2> Links { get; set; }
}
And its result :
<trick>
<links>
<link href="/users" rel="users" />
<link href="/features" rel="features" />
<link href="/features/user/{keyUser}" rel="featuresByUser" />
</links>
</trick>
Nice, but I don't want that root node !!
I want my collection to be the root node.
Here are the contraints :
the serialization code is generic, it works with anything serializable
the inverse operation (deserialization) have to work too
I don't want to regex the result (I serialize directly in an output stream)
What are my solutions now :
Coding my own XmlSerializer
Trick XmlSerializer when it works with a collection (I tried, having it find a XmlRootElement and plurialize it to generate its own XmlRootAttribute, but that causes problem when deserializing + the items name still keeps the class name)
Any idea ?
What really bother me in that issue, is that what I want seems to be really really really simple...
Ok, here is my final solution (hope it helps someone), that can serialize a plain array, List<>, HashSet<>, ...
To achieve this, we'll need to tell the serializer what root node to use, and it's kind of tricky...
1) Use 'XmlType' on the serializable object
[XmlType("link")]
public class LinkFinalVersion
{
[XmlAttribute("href")]
public string Url { get; set; }
[XmlAttribute("rel")]
public string Relationship { get; set; }
}
2) Code a 'smart-root-detector-for-collection' method, that will return a XmlRootAttribute
private XmlRootAttribute XmlRootForCollection(Type type)
{
XmlRootAttribute result = null;
Type typeInner = null;
if(type.IsGenericType)
{
var typeGeneric = type.GetGenericArguments()[0];
var typeCollection = typeof (ICollection<>).MakeGenericType(typeGeneric);
if(typeCollection.IsAssignableFrom(type))
typeInner = typeGeneric;
}
else if(typeof (ICollection).IsAssignableFrom(type)
&& type.HasElementType)
{
typeInner = type.GetElementType();
}
// yeepeeh ! if we are working with a collection
if(typeInner != null)
{
var attributes = typeInner.GetCustomAttributes(typeof (XmlTypeAttribute), true);
if((attributes != null)
&& (attributes.Length > 0))
{
var typeName = (attributes[0] as XmlTypeAttribute).TypeName + 's';
result = new XmlRootAttribute(typeName);
}
}
return result;
}
3) Push that XmlRootAttribute into the serializer
// hack : get the XmlRootAttribute if the item is a collection
var root = XmlRootForCollection(type);
// create the serializer
var serializer = new XmlSerializer(type, root);
I told you it was tricky ;)
To improve this, you can :
A) Create a XmlTypeInCollectionAttribute to specify a custom root name (If the basic pluralization does not fit your need)
[XmlType("link")]
[XmlTypeInCollection("links")]
public class LinkFinalVersion
{
}
B) If possible, cache your XmlSerializer (in a static Dictionary for example).
In my testing, instanciating a XmlSerializer without the XmlRootAttributes takes 3ms.
If you specify an XmlRootAttribute, it takes around 80ms (Just to have a custom root node name !)
XmlSerializer should be able to do what you need, but it is highly dependent on the initial structure and setup. I use it in my own code to generate remarkably similar things.
public class Links<Link> : BaseArrayClass<Link> //use whatever base collection extension you actually need here
{
//...stuff...//
}
public class Link
{
[XmlAttribute("href")]
public string Url { get; set; }
[XmlAttribute("rel")]
public string Relationship { get; set; }
}
now, serializing the Links class should generate exactly what you are looking for.
The problem with XmlSerializer is when you give it generics, it responds with generics. List implemets Array somewhere in there and the serialized result will nearly always be ArrayOf<X>. To get around that you can name the property, or the class root. The closes to what you need is probably the Second Version from your examples. Im assuming you attempted direct serialization of an object List Links. That wouldn't work because you didn't specify the root node. Now, a similar approach can be found here. In this one they specify the XmlRootAttribute when declaring the serializer. yours would look like this:
XmlSerializer xs = new XmlSerializer(typeof(List<Link>), new XmlRootAttribute("Links"));
Here you go...
class Program
{
static void Main(string[] args)
{
Links ls = new Links();
ls.Link.Add(new Link() { Name = "Mike", Url = "www.xml.com" });
ls.Link.Add(new Link() { Name = "Jim", Url = "www.xml.com" });
ls.Link.Add(new Link() { Name = "Peter", Url = "www.xml.com" });
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Links));
StringWriter stringWriter = new StringWriter();
xmlSerializer.Serialize(stringWriter, ls);
string serializedXML = stringWriter.ToString();
Console.WriteLine(serializedXML);
Console.ReadLine();
}
}
[XmlRoot("Links")]
public class Links
{
public Links()
{
Link = new List<Link>();
}
[XmlElement]
public List<Link> Link { get; set; }
}
[XmlType("Link")]
public class Link
{
[XmlAttribute("Name")]
public string Name { get; set; }
[XmlAttribute("Href")]
public string Url { get; set; }
}