XML Serialization of List<T> - XML Root
Asked Answered
C

4

13

First question on Stackoverflow (.Net 2.0):

So I am trying to return an XML of a List with the following:

public XmlDocument GetEntityXml()
    {        
        StringWriter stringWriter = new StringWriter();
        XmlDocument xmlDoc = new XmlDocument();            

        XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter);

        XmlSerializer serializer = new XmlSerializer(typeof(List<T>));

        List<T> parameters = GetAll();

        serializer.Serialize(xmlWriter, parameters);

        string xmlResult = stringWriter.ToString();

        xmlDoc.LoadXml(xmlResult);

        return xmlDoc;
    }

Now this will be used for multiple Entities I have already defined.

Say I would like to get an XML of List<Cat>

The XML would be something like:

<ArrayOfCat>
  <Cat>
    <Name>Tom</Name>
    <Age>2</Age>
  </Cat>
  <Cat>
    <Name>Bob</Name>
    <Age>3</Age>
  </Cat>
</ArrayOfCat>

Is there a way for me to get the same Root all the time when getting these Entities?

Example:

<Entity>
  <Cat>
    <Name>Tom</Name>
    <Age>2</Age>
  </Cat>
  <Cat>
    <Name>Bob</Name>
    <Age>3</Age>
  </Cat>
</Entity>

Also note that I do not intend to Deserialize the XML back to List<Cat>

Casta answered 6/8, 2009 at 8:45 Comment(1)
What do you mean by "get the same Root all the time" ? Please give more details...Savona
R
31

There is a much easy way:

public XmlDocument GetEntityXml<T>()
{
    XmlDocument xmlDoc = new XmlDocument();
    XPathNavigator nav = xmlDoc.CreateNavigator();
    using (XmlWriter writer = nav.AppendChild())
    {
        XmlSerializer ser = new XmlSerializer(typeof(List<T>), new XmlRootAttribute("TheRootElementName"));
        ser.Serialize(writer, parameters);
    }
    return xmlDoc;
}
Rollin answered 26/8, 2009 at 12:55 Comment(1)
With this approach, the XmlSerializer must be statically cached and reused to avoid a severe memory leak, see Memory Leak using StreamReader and XmlSerializer for details.Tousle
S
8

If I understand correctly, you want the root of the document to always be the same, whatever the type of element in the collection ? In that case you can use XmlAttributeOverrides :

       XmlAttributeOverrides overrides = new XmlAttributeOverrides();
       XmlAttributes attr = new XmlAttributes();
       attr.XmlRoot = new XmlRootAttribute("TheRootElementName");
       overrides.Add(typeof(List<T>), attr);
       XmlSerializer serializer = new XmlSerializer(typeof(List<T>), overrides);
       List<T> parameters = GetAll();
       serializer.Serialize(xmlWriter, parameters);
Savona answered 6/8, 2009 at 9:17 Comment(0)
A
6

A better way to the same thing:

public XmlDocument GetEntityXml<T>()
{
    XmlAttributeOverrides overrides = new XmlAttributeOverrides();
    XmlAttributes attr = new XmlAttributes();
    attr.XmlRoot = new XmlRootAttribute("TheRootElementName");
    overrides.Add(typeof(List<T>), attr);

    XmlDocument xmlDoc = new XmlDocument();
    XPathNavigator nav = xmlDoc.CreateNavigator();
    using (XmlWriter writer = nav.AppendChild())
    {
        XmlSerializer ser = new XmlSerializer(typeof(List<T>), overrides);
        List<T> parameters = GetAll<T>();
        ser.Serialize(writer, parameters);
    }
    return xmlDoc;
}
Alysa answered 9/8, 2009 at 18:14 Comment(2)
The main thing is that it serializes directly into the XmlDocument. Your code required parsing the results in order to get them back into the document. Your code also used XmlTextWriter, which is largely obsolete.Alysa
This was really helpful, but since I am using a Dictionary which cannot be serialized, this post helped me alot: theburningmonk.com/2010/05/…Spiritualist
T
2

so simple....

public static XElement ToXML<T>(this IList<T> lstToConvert, Func<T, bool> filter, string rootName)
{
    var lstConvert = (filter == null) ? lstToConvert : lstToConvert.Where(filter);
    return new XElement(rootName,
       (from node in lstConvert
       select new XElement(typeof(T).ToString(),
       from subnode in node.GetType().GetProperties()
       select new XElement(subnode.Name, subnode.GetValue(node, null)))));

}
Tobey answered 27/9, 2010 at 9:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.