2

I have a class that I need to do some custom XML output from, thus I implement the IXmlSerializable interface. However, some of the fields I want to output with the default serialization except I want to change the xml tag names. When I call serializer.Serialize, I get default tag names in the XML. Can I change these somehow?

Here is my code:

public class myClass: IXmlSerializable
{
    //Some fields here that I do the custom serializing on
    ...

    // These fields I want the default serialization on except for tag names
    public string[] BatchId { get; set; }
    ...

    ... ReadXml and GetSchema methods are here ...

    public void WriteXml(XmlWriter writer)
    {                        
        XmlSerializer serializer = new XmlSerializer(typeof(string[]));
        serializer.Serialize(writer, BatchId);
        ... same for the other fields ...

        // This method does my custom xml stuff
        writeCustomXml(writer);   
    }

    // My custom xml method is here and works fine
    ...
}

Here is my Xml output:

  <MyClass>
    <ArrayOfString>
      <string>2643-15-17</string>
      <string>2642-15-17</string>
      ...
    </ArrayOfString>
    ... My custom Xml that is correct ..
  </MyClass>

What I want to end up with is:

  <MyClass>
    <BatchId>
      <id>2643-15-17</id>
      <id>2642-15-17</id>
      ...
    </BatchId>
    ... My custom Xml that is correct ..
  </MyClass>
KrisTrip
  • 4,943
  • 12
  • 55
  • 74
  • How often are you serializing / deserializing ? 100s of times during the app lifecycle or only on startup / shutdown. If the former I have an implementation that is significantly more flexible. – Sam Saffron Dec 30 '09 at 20:30
  • Really only serializing once. This application is a simple tool that pulls data from a proprietary database format and saves to xml. So I am pulling data into an object model and then immediately serializing. Most of the data was simple so I didn't need to implement IXmlSerializable...but this particular piece of data was a bit of a pain. – KrisTrip Dec 30 '09 at 20:34
  • Well have a look here, the code is MIT http://code.google.com/p/videobrowser/source/browse/MediaBrowser/Library/Persistance/XmlSettings.cs there is a unit test as well, you may have to extend it a bit, but all the architecture is there. plus for your scenario it will perform MUCH better than XmlSerializer – Sam Saffron Dec 30 '09 at 20:41

3 Answers3

7

In many cases, you can use the XmlSerializer constructor-overload that accepts a XmlAttributeOverrides to specify this extra name information (for example, passing a new XmlRootAttribute) - however, this doesn't work for arrays AFAIK. I expect for the string[] example it would be simpler to just write it manually. In most cases, IXmlSerializable is a lot of extra work - I avoid it as far as possible for reasons like this. Sorry.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • XmlSerializer is an old piece of unmaintained, inefficient technology that should have been deprecated by MS ages ago, or at the bare minimum reimplemented. I have only had trouble with it. Better off use protocol buffers :p – Sam Saffron Dec 30 '09 at 20:29
  • How tempting is it to see if I can crank the output of pb-net to xml ;-p – Marc Gravell Dec 30 '09 at 20:41
  • you should totally do that, and make it pluggable so people can implement their own persistence format, then you could even use sqlite as a data store ... – Sam Saffron Dec 30 '09 at 20:48
3

You can tag your fields with attributes to control the serialized XML. For example, adding the following attributes:

[XmlArray("BatchId")]
[XmlArrayItem("id")]
public string[] BatchId { get; set; }

will probably get you there.

womp
  • 115,835
  • 26
  • 236
  • 269
0

If anyone is still looking for this you can definitely use the XmlArrayItem however this needs to be a property in a class.

For readability you should use the plural and singular of the same word.

    /// <summary>
    /// Gets or sets the groups to which the computer is a member.
    /// </summary>
    [XmlArrayItem("Group")]
    public SerializableStringCollection Groups
    {
        get { return _Groups; }
        set { _Groups = value; }
    }
    private SerializableStringCollection _Groups = new SerializableStringCollection();



<Groups>
   <Group>Test</Group>
   <Group>Test2</Group>
</Groups>

David

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
David Homer
  • 396
  • 2
  • 8