This is similar to many questions I've looked at on here, but none of them have helped or fit my situation exactly. I'm trying to deserialize XML output from SQL Server into C# objects.
The classes I have are comprised of some properties and a list of other objects. The problem is that when it deserializes, it only grabs the first item of each list.
Here's my code:
The XML:
<Product>
<Id>2</Id>
<Name>Foo</Name>
<Versions>
<Version>
<Id>2</Id>
<Product>Foo</Product>
<VersionNumber>2.0</VersionNumber>
<Resources>
<Resource>
<Id>5</Id>
<Name>FunTimes</Name>
<Uri>/fun</Uri>
<Properties>
<Property>
<Id>25</Id>
<Name>Time</Name>
<PropertyTypeId>5</PropertyTypeId>
<EnumerationId>7</EnumerationId>
<Enumeration>
<Id>7</Id>
<Name>Time</Name>
<Members>
<Member>
<Name>Hours</Name>
</Member>
<Member>
<Name>Seconds</Name>
</Member>
</Members>
</Enumeration>
</Property>
<Property>
<Id>58</Id>
<Name>Place</Name>
<PropertyTypeId>4</PropertyTypeId>
</Property>
</Properties>
</Resource>
<Resource>
<Id>4</Id>
<Name>BadTimes</Name>
<Uri>/bad</Uri>
<Properties>
<Property>
<Id>25</Id>
<Name>Cause</Name>
<PropertyTypeId>5</PropertyTypeId>
<EnumerationId>7</EnumerationId>
<Enumeration>
<Id>7</Id>
<Name>Cause</Name>
<Members>
<Member>
<Name>Local</Name>
</Member>
<Member>
<Name>International</Name>
</Member>
</Members>
</Enumeration>
</Property>
</Properties>
</Resource>
</Resources>
</Version>
</Versions>
</Product>
The code I'm using to deserialize:
XmlSerializer deserializer = new XmlSerializer(typeof(Product));
TextReader stringReader = new StringReader(content.ToString());
object obj = deserializer.Deserialize(stringReader);
Product XmlData = (Product) obj;
stringReader.Close();
where the XML is being stored in a StringBuilder called "content".
And here are the classes:
[Serializable]
public class Product
{
// Fields...
// Properties
[XmlElement]
public int Id { get; set; }
[XmlElement]
public string Name { get; set; }
[XmlElement]
public string Comments { get; set; }
[XmlArray("Versions")]
[XmlArrayItem("Version")]
public List<Version> Versions { get; set; }
// Constructors and methods...
}
[Serializable]
public class Version
{
// Fields...
// Properties
[XmlElement]
public int Id { get; set; }
[XmlElement]
public string Product { get; set; }
[XmlElement]
public string VersionNumber { get; set; }
[XmlElement]
public string Comments { get; set; }
[XmlArray("Resources")]
[XmlArrayItem("Resource")]
public List<Resource> Resources { get; set; }
// Constructors and methods...
}
[Serializable]
public class Resource
{
// Fields...
// Properties
[XmlElement]
public int Id { get; set; }
[XmlElement]
public string Name { get; set; }
[XmlElement]
public string Uri { get; set; }
[XmlElement]
public string Comments { get; set; }
[XmlArray("Properties")]
[XmlArrayItem("Property")]
public List<Property> Properties { get; set; }
// Constructors and methods...
}
[Serializable]
public class Property
{
// Fields...
// Properties
[XmlElement]
public int Id { get; set; }
[XmlElement]
public string Name { get; set; }
[XmlElement]
public PropertyType PropertyTypeId { get; set; }
[XmlElement]
public int? MaximumStringLength { get; set; }
[XmlElement]
public double? MinimumValue { get; set; }
[XmlElement]
public double? MaximumValue { get; set; }
[XmlElement]
public int? EnumerationId { get; set; }
[XmlElement]
public PropertyEnumeration Enumeration { get; set; }
[XmlElement]
public int? ResourceId { get; set; }
[XmlElement]
public string Comments { get; set; }
[XmlArray("Properties")]
[XmlArrayItem("Property")]
public List<Property> CompositeProperties { get; set; }
// Constructors and methods...
}
And here's the result that it gives me if I re-serialize it as XML. (I know for a fact that it isn't the re-serialization's fault.)
<?xml version="1.0" encoding="utf-16"?>
<Product xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Id>2</Id>
<Name>Foo</Name>
<Versions>
<Version>
<Id>2</Id>
<Product>Foo</Product>
<VersionNumber>2.0</VersionNumber>
<Resources>
<Resource>
<Id>5</Id>
<Name>FunTimes</Name>
<Uri>/fun</Uri>
<Properties>
<Property>
<Id>25</Id>
<Name>Time</Name>
<PropertyTypeId>5</PropertyTypeId>
<MaximumStringLength xsi:nil="true" />
<MinimumValue xsi:nil="true" />
<MaximumValue xsi:nil="true" />
<EnumerationId>7</EnumerationId>
<Enumeration>
<Id>7</Id>
<Members>
<Member>Hours</Member>
</Members>
</Enumeration>
<ResourceId xsi:nil="true" />
</Property>
</Properties>
</Resource>
</Resources>
</Version>
</Versions>
</Product>
There's also an Enumeration class and some other helper classes, but they're not important. Basically I need it to give me the rest of the items in the XML. I've tried having the list properties use the XmlElement tag, but that produces the same result. How can I make it read all of the items in the XML?
Edit: Oleg mentioned in a comment that it worked for him. Does anyone know if there's a way that my system in particular would be messing it up?
Edit: Found the solution. I unfortunately hadn't even given you all enough information to solve it. In the XML, it says
<Members>
<Member>
<Name>Local</Name>
</Member>
<Member>
<Name>International</Name>
</Member>
</Members>
under Enumeration. In my Enumeration class, I had a property that was a list of strings called Members. It was expecting a list of Members with a Name property inside, so it freaked out. By changing it to
<Members>
<Member>Local</Member>
<Member>International</Member>
</Members>
it fixed the issue.
Try this. I used a file so I replaced the text reader. You don't need two levels of items like Properties and Property. One level can be eliminated if you change the XML