Serialization with XmlSerializer: how to set the XML root node to something different from <ArrayOf

  • Thread starter Thread starter Bob Rock
  • Start date Start date
B

Bob Rock

Hello,

when serializing an array of elements of a class Classname using
XmlSerializer.Serialize() I get an XML like the following:

<?xml version="1.0">
<ArrayOfClassname>
.......
.......
</ArrayOfClassname>

I'd like to be able to set the XML root node to something different from
<ArrayOfClassname> .... for example something like <Classnames>.
As an alternative when deserilizing an XML such as the following:

<?xml version="1.0">
<Classnames>
.......
.......
</Classnames>

I'd like to be able to "load" it into an array of objects of class Classname
(at the moment when making such an attempt I get an obvious exception
stating "<Classnames> was not expected").


Bob Rock
 
Maybe not exactly what you want, but you can get close like this:

public class Foo
{
ArrayList _classNames = new ArrayList();
[XmlArray("ClassNames"), XmlArrayItem("ClassName")]
public string[] ClassNames
{
get { return (string[])_classNames.ToArray(typeof(string)); }
set {_classNames = new ArrayList(value);}
}
}

Construct and serialize a Foo like this:

string[] names = new string[]{"f", "g", "h"};
Foo f = new Foo();
f.ClassNames = names;
Console.WriteLine(SerializeThingToXmlString(f));


Where the helper method is:

static string SerializeThingToXmlString(object thing)
{
StringWriter stringWriter = new StringWriter();
XmlSerializer serializer = new XmlSerializer(thing.GetType());
serializer.Serialize(stringWriter, thing);
return stringWriter.ToString();
}
 
Maybe not exactly what you want, but you can get close like this:
public class Foo
{
ArrayList _classNames = new ArrayList();
[XmlArray("ClassNames"), XmlArrayItem("ClassName")]
public string[] ClassNames
{
get { return (string[])_classNames.ToArray(typeof(string)); }
set {_classNames = new ArrayList(value);}
}
}

Construct and serialize a Foo like this:

string[] names = new string[]{"f", "g", "h"};
Foo f = new Foo();
f.ClassNames = names;
Console.WriteLine(SerializeThingToXmlString(f));


Where the helper method is:

static string SerializeThingToXmlString(object thing)
{
StringWriter stringWriter = new StringWriter();
XmlSerializer serializer = new XmlSerializer(thing.GetType());
serializer.Serialize(stringWriter, thing);
return stringWriter.ToString();
}

Ahhh, so that is the way you can use the XmlArrayAttribute and
XmlArrayItemAttribute on something that is not a field!!!
Is it possible to use it on methods returning arrays???

I've also seen that there is a way of setting the root node element to
whatever one wants using the XmlSerializer(Type, XmlRootAttribute)
constructor. Unfortunately when deserializing I need to change the root node
element to <ArrayOfClassname> as the XmlSerializer expects to avoid the
exception.


Bob Rock
 
Hi, Bob.
One solution I can think right out-of-the box is:

public class Classnames {
[XmlElement("Classname")]
public Classname[] Members;
......
}

By applying XmlElementAttribute to an array, You can eliminate the
ArrayOfClassname/Members element from the serialized result. And by wrapping
the array in a class named Classnames, you can make sure the result Xml has
a Classnames root element. The net effect is that you get an Xml document
that has a Classnames root and a list of Classname.

On the other hand, .NET does allow XmlXXXAttributes to be applied on
function return value. But there isn't any easy way to leverage it. E.g:
WebService engine utilizes this through XmlMapping, which is marked "not
intended to be used directly from your code" in MSDN. I think that you can
still use XmlMapping classes, though.

Hope this helps.
Ming Chen [.NET MVP]
 
Back
Top