Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I rename class-names via Xml attributes?

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?

like image 589
invarbrass Avatar asked Sep 06 '10 17:09

invarbrass


2 Answers

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.

[XmlType(TypeName="g")] class Song {     public string Artist;     public string SongTitle; } 

Assuming you apply it to the other classes e.g.:

[XmlType(TypeName="a")] class Artist {     ..... }  [XmlType(TypeName="s")] class SongTitle {     ..... } 

This will output the following exactly as required in the question:

<g>   <a>Britney Spears</a>   <s>I Did It Again</s> </g> 

I have used this in several production projects and found no problems with it.

like image 159
Gone Coding Avatar answered Sep 16 '22 20:09

Gone Coding


Checkout the XmlRoot attribute.

Documentation can be found here: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlrootattribute(v=VS.90).aspx

[XmlRoot(Namespace = "www.contoso.com",       ElementName = "MyGroupName",       DataType = "string",       IsNullable=true)] public class Group 

UPDATE: Just tried and it works perfectly on VS 2008. This code:

[XmlRoot(ElementName = "sgr")] public class SongGroup {     public SongGroup()     {        this.Songs = new List<Song>();     }    [XmlElement(ElementName = "sgs")]     public List<Song> Songs { get; set; } }  [XmlRoot(ElementName = "g")] public class Song {     [XmlElement("a")]     public string Artist { get; set; }      [XmlElement("s")]     public string SongTitle { get; set; } }  

Outputs:

<?xml version="1.0" encoding="utf-8"?> <sgr xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www .w3.org/2001/XMLSchema">   <sgs>     <a>A1</a>     <s>S1</s>   </sgs>   <sgs>     <a>A2</a>     <s>S2</s>   </sgs> </sgr> 
like image 40
Ariel Popovsky Avatar answered Sep 19 '22 20:09

Ariel Popovsky