XmlSerialization of collections

I want to serialize the following Xml structure:

  <XmlRootElement>
     <Company name="Acme Widgets LLC">
        <DbApplication name="ApplicationA" vendor="oracle">
           <ConnSpec environment="DEV" 
                     server="DBOraDev1201" 
                     database="AppA" 
                     userId="MyUser" 
                     password="5613456#6%^%$%$#" />
           <ConnSpec environment="QA" 
                     server="DBOraQA1205" 
                     database="AppA" 
                     userId="MyUser" 
                     password="5613456#6%^%$%$#" />
       </DbApplication>
       <DbApplication name="AnotherApp" "vendor="SQLServer">
           <ConnSpec environment="DEV" 
                     server="DBMsSqlDev1201" 
                     catalog="AnoptherApp" 
                     userId="MyUser" 
                     password="5613456#6%^%$%$#" />
           <ConnSpec environment="QA" 
                     server="DBMsSqlQA1565" 
                     catalog="AnotherApp" 
                     userId="MyUser" 
                     password="5613456#6%^%$%$#" />
       </DbApplication>
     </Company>
     <Company name = "ExpertSoftware Inc" ....
        ...
     </Company>
  </XmlRootElement>

but I have discovered in link text

Quote from above link: ...

  • Q: Why aren't all properties of collection classes serialized?
  • A: The XmlSerializer only serializes the elements in the collection when it detects either the IEnumerable or the ICollection interface. This behavior is by design. The only work around is to re-factor the custom collection into two classes, one of which exposes the properties including one of the pure collection types.

...

after discovering that you can't serialize or deserialize a collection that has other Xml attributes in it... The suggested workaround is to separate the element that has the collection from the the ones that have other attributes... i.e, You have to change the structure so that it looks like this instead:

  <XmlRootElement>
     <Companys>
        <Company name="Acme Widgets LLC">
           <DbApplications>
               <DbApplication name="ApplicationA" vendor="oracle">
                  <ConnSpecs>
                     <ConnSpec environment="DEV" 
                         server="DBOraDev1201" ...  />
                     <ConnSpec environment="QA" 
                         server="DBOraQA1205" 
                         database="AppA" ... />
                  </ConnSpecs>
               </DbApplication>
               <DbApplication name="AnotherApp" "vendor="SQLServer">
                  <ConnSpecs>
                      <ConnSpec environment="DEV" ... />
                      <ConnSpec environment="QA"  ... />
                  </ConnSpecs>
                </DbApplication>
           </DbApplications>
         </Company>
         <Company name = "ExpertSoftware Inc" ....
             ...
         </Company>
     </Companys>
  </XmlRootElement>

Does anyone know why this is so? or if there is some other way to do this?

Answers


If you are using XmlSerializer you need to indicate it how to serialize your collections:

public class XmlRootElement
{
    [XmlElement(ElementName="Company")]
    public Company[] Company { get; set; }

    // Other properties ....
}

public class Company
{
    [XmlAttribute(AttributeName="name")]
    public string Name { get; set; }

    [XmlElement(ElementName = "DbApplication")]
    public DbApplication[] DbApplication { get; set; }

    // Other properties ....
}

public class DbApplication
{
    [XmlElement(ElementName = "ConnSpec")]
    public ConnSpec[] ConnSpec { get; set; }

    // Other properties ....
}

public class ConnSpec
{
    // Other properties ....
}

And then:

using (Stream stream = new FileStream("test.xml", FileMode.Open, FileAccess.Read, FileShare.Read))
{
    XmlSerializer serializer = new XmlSerializer(typeof(XmlRootElement));
    XmlRootElement root = (XmlRootElement)serializer.Deserialize(stream);
}

Hope this helps.


An alternative to adding XMl serialization attributes to all of your classes is to implement the IXmlSerializable interface on the root element container class. The ReadXml and WriteXml methods of this interface will be used by the XmlSerializer, allowing you to have more fine grained control over the serialization/deserialization process.


Need Your Help

g++ produce executable for windows

windows compiler-construction g++

I am using gcc/g++ to compile c/c++ applications - living on OpenSuSe btw.

How to add a custom field into template.php using Zen sub theme

drupal-7 drupal-theming

First time poster here, I'm a designer not skilled at all with php and I have a small issue I don't seem to be able to solve. I'm making a site in drupal 7 using a sub theme on zen.