How to Use XmlSerializer to Serialize Collections of Objects
Here are the steps I've taken so far to work with an XmlDocument being returned by a 3rd party DLL.
- I saved the XmlDocument as SegmentationSummary.xml.
- I used XSD.exe to create SegmentationSummary.xsd.
- I used XSD.exe to create SegmentationSummary.cs.
Here is a sample of SegmentationSummary.cs. Note that ShmResult is the root node representation.
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "omitted")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "omitted", IsNullable = false)]
public partial class ShmResult
{
private ShmResultDownloadDetail[] downloadDetailField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("DownloadDetail")]
public ShmResultDownloadDetail[] DownloadDetail
{
get
{
return this.downloadDetailField;
}
set
{
this.downloadDetailField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "omitted")]
public partial 开发者_JAVA百科class ShmResultDownloadDetail
{
private string modelCodeField;
/// <remarks/>
public string ModelCode
{
get
{
return this.modelCodeField;
}
set
{
this.modelCodeField = value;
}
}
}
Now, I wanted to use this to read the XmlDocument and begin working with the classes in SegmentationSummary.cs. Here's the code I wrote:
private XmlDocument _document;
SegmentationSummary.ShmResult _Result;
private void LoadXML()
{
XmlReader xmlRdr = new XmlNodeReader(_document);
System.Xml.Serialization.XmlSerializer s = new System.Xml.Serialization.XmlSerializer(typeof(SegmentationSummary.ShmResult));
_Result = (SegmentationSummary.ShmResult)s.Deserialize(xmlRdr);
}
When LoadXML() is executed, I get exceptions of this variety:
Test method SegmentationSummaryHandlerTest.TestMethod1 threw exception: System.InvalidOperationException: Unable to generate a temporary class (result=1). error CS0030: Cannot convert type 'MERC.AIRCAT.SHMCoreInterface.SegmentationSummary.ShmResultDownloadDetail[]' to 'MERC.AIRCAT.SHMCoreInterface.SegmentationSummary.ShmResultDownloadDetail' error CS0029: Cannot implicitly convert type 'MERC.AIRCAT.SHMCoreInterface.SegmentationSummary.ShmResultDownloadDetail' to 'MERC.AIRCAT.SHMCoreInterface.SegmentationSummary.ShmResultDownloadDetail[]'
Now, the FAQ at http://msdn.microsoft.com/en-us/library/ms950721.aspx states the following:
Q: How do I serialize collections of objects?
A: The XmlSerializer throws an exception when the collection contains types that were not declared to the constructor of the XmlSerializer. You can:
Declare the types to the serializer by passing in a Type[] with the types to expect within the collection.
OR
- Implement a strongly-typed collection derived from System.Collections.CollectionBase with an indexer matching the Add() method.
My question is: Which of these is "best" and how do I go about implementing the solution?
I ran into a similar issue.
There is an issue with serializing nested unbound elements. Here is an explanation.
To fix the issue I removed the maxoccurs="unbounded" from the xsd and regenerated the class file. After that the serialization worked.
I've always used option 2 there, so for you, something a little like this might work:
public class ShmResult : List<ShmResultDownloadDetail> { }
I had same issue as you did:
- I made xsd from XML by using the xsd.exe
- I generated class(es) by using xsd.exe and resulting schema from step 1.
- After attempting to use this class as type for XMLSerializer constructor, I got this exception message (pseudo message):
System.InvalidOperationException: Unable to generate a temporary class (result=1). error CS0030: Cannot convert type Type1 [] to Type1.
Also, xsd.exe generated resulting class which had matrix data types (Type[][]), and actually that was my main concern.
Once I made XMLSerializer constructor with array of types , which can be inside collection, I also modified my xsd file by removing the maxoccurs="unbounded" from several elements in my schema. New generation process gave me new class. After attempting to use newly generated class in XMLSerializer, everything was well.
Therefore, I suggest you to declare array of types (types that may be part of collection), and introduce it to XMLSerializer constructor. Also, from your generated schema remove maxoccurs="unbounded" from certain elements.
Microsoft has a bug here. It's been out since 2003. I know the thread is old, but for others banging their head on this. The XSD generation is wrong. In the steps above, using xsd.exe to generate an xsd from the xml just looks wrong. I used a tool called trang (open source java) you can create the xsd with that. In fact, you can use multiple XML files to create it. Then, use xsd.exe to create the .cs file. This worked.
精彩评论