Suppose I have an XML-serializable class called Song:
[Serializable]
class Song
{
public string Artist;
public string SongTitle;
}
In order to save space (and also semi-obfuscate the XML file), I decide to rename the xml elements:
[XmlRoot("g")]
class Song
{
[XmlElement("a")]
public string Artist;
[XmlElement("s")]
public string SongTitle;
}
This will produce XML output like this:
<Song>
<a>Britney Spears</a>
<s>I Did It Again</s>
</Song>
I want to rename/remap the name of the class/object as well. Say, in the above example, I wish to rename the class Song to g. So that the resultant xml should look like this:
<g>
<a>Britney Spears</a>
<s>I Did It Again</s>
</g>
Is it possible to rename class-names via xml-attributes?
I don't wish to create/traverse the DOM manually, so I was wondering if it could be achieved via a decorator.
Thanks in advance!
UPDATE: Oops! This time I really did it again! Forgot to mention - I'm actually serializing a list of Song objects in the XML.
Here's the serialization code:
public static bool SaveSongs(List<Song> songs)
{
XmlSerializer serializer = new XmlSerializer(typeof(List<Song>));
using (TextWriter textWriter = new StreamWriter("filename"))
{
serializer.Serialize(textWriter, songs);
}
}
And here's the XML output:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfSong>
<Song>
<a>Britney Spears</a>
<s>Oops! I Did It Again</s>
</Song>
<Song>
<a>Rihanna</a>
<s>A Girl Like Me</s>
</Song>
</ArrayOfSong>
Apparently, the XmlRoot() attribute doesn't rename the object in a list context.
Am I missing something?
Use XmlElementAttribute: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlrootattribute.aspx
should work.
Should do the trick
Solution: Use [XmlType(TypeName="g")]
XmlRoot only works with XML root nodes as per the documentation (and what you would expect, given its name includes root)!
I was unable to get any of the other answers to work so kept digging...
Instead I found that the XmlTypeAttribute (i.e.
[XmlType]
) and its TypeName property do a similar job for non-root classes/objects.e.g.
Assuming you apply it to the other classes e.g.:
This will output the following exactly as required in the question:
I have used this in several production projects and found no problems with it.
Checkout the XmlRoot attribute.
Documentation can be found here: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlrootattribute(v=VS.90).aspx
UPDATE: Just tried and it works perfectly on VS 2008. This code:
Outputs:
If this is the root element of the document, you can use [XmlRoot("g")].
Here is my updated response based on your clarification. The degree of control you are asking for is not possible without a wrapping class. This example uses a
SongGroup
class to wrap the list so that you can give alternate names to the items within.This has the side effect of generating one more inner element representing the list itself. On my system, the output looks like this: