Element was not expected While Deserializing an Array with XML Serialization
OK. I'm trying to work on communicating with the Pivotal Tracker API, which only returns data in an XML format. I have the following XML that I'm trying to deserialize into my domain model.
<?xml version="1.0" encoding="UTF-8"?>
<stories type="array" count="2" total="2">
<story>
<id type="integer">2909137</id>
<project_id type="integer">68153</project_id>
<story_type>bug</story_type>
<url>http://www.pivotaltracker.com/story/show/2909137</url>
<current_state>unscheduled</current_state>
<description></desc开发者_StackOverflowription>
<name>Test #2</name>
<requested_by>Anthony Shaw</requested_by>
<created_at type="datetime">2010/03/23 20:05:58 EDT</created_at>
<updated_at type="datetime">2010/03/23 20:05:58 EDT</updated_at>
</story>
<story>
<id type="integer">2909135</id>
<project_id type="integer">68153</project_id>
<story_type>feature</story_type>
<url>http://www.pivotaltracker.com/story/show/2909135</url>
<estimate type="integer">-1</estimate>
<current_state>unscheduled</current_state>
<description></description>
<name>Test #1</name>
<requested_by>Anthony Shaw</requested_by>
<created_at type="datetime">2010/03/23 20:05:53 EDT</created_at>
<updated_at type="datetime">2010/03/23 20:05:53 EDT</updated_at>
</story>
</stories>
My 'story' object is created as follows:
public class story
{
public int id { get; set; }
public int estimate { get; set; }
public int project_id { get; set; }
public string story_type { get; set; }
public string url { get; set; }
public string current_state { get; set; }
public string description { get; set; }
public string name { get; set; }
public string requested_by { get; set; }
public string labels { get; set; }
public string lighthouse_id { get; set; }
public string lighthouse_url { get; set; }
public string owned_by { get; set; }
public string accepted_at { get; set; }
public string created_at { get; set; }
public attachment[] attachments { get; set; }
public note[] notes { get; set; }
}
When I execute my deserialization code, I receive the following exception:
Exception:
There is an error in XML document (2, 2).
Inner Exception:
<stories xmlns=''> was not expected.
I can deserialize the individual stories just fine, I just cannot deserialize this xml into an array of 'story' objects
And my deserialization code (value is a string of the xml)
var byteArray = Encoding.ASCII.GetBytes(value);
var stream = new MemoryStream(byteArray);
var deserializedObject = new XmlSerializer(typeof (story[])).Deserialize(stream)
Does anybody have any ideas?
Let me offer a more concise solution. Set your deserialization up to look like this:
var deserializedObject = new XmlSerializer(typeof(story[]), new XmlRootAttribute("stories")).Deserialize(stream);
By specifying that second parameter in the XmlSerializer, you can avoid having to stub out that class. It lets the serializer know what the root element's name is.
For this to work, the name of the class that represents the array-element type must exactly match the XML name, e.g. class story {}
, <story>
. You can get around this (and I'd recommend it as a best practice anyway) by specifying the XmlType:
[XmlType("story")]
public class Story
{
...
}
I prefer to do this as it frees me from being stuck with the XML type name.
The problem is that you have no property named "stories". The XML Serializer has no idea what to do with the stories
element when it sees it.
One thing you could try is to create a "stories" class:
public class stories : List<story> {}
and use
var byteArray = Encoding.ASCII.GetBytes(value);
stories deserializedObject = null;
using (var stream = new MemoryStream(byteArray))
{
var storiesSerializer = new XmlSerializer(typeof (stories));
deserializedObject = (stories)storiesSerializer .Deserialize(stream);
}
Try something like
public class stories
{
[XmlElement("story")]
public story[] storyarray { get; set; }
}
...
var byteArray = Encoding.ASCII.GetBytes(value);
XmlSerializer serializer = new XmlSerializer(typeof(stories));
stories myStories = null;
using (var stream = new MemoryStream(byteArray))
{
myStories = (stories)serializer.Deserialize(stream);
}
foreach (story stor in myStories.storyarray)
Console.WriteLine(stor.story_type);
Edit: Updated code sample to use using statement based on feedback.
XMSerializer expects an XML Namespace with which to understand your XML from.
xmlns="http://schemas.microsoft.com"
... ought to do. See the XML sample at the bottom of this page.
I would recommend that you generate an XSD from some sample XML you get from the web service. Then, with that XSD, you can generate the classes that have all the proper serialization attributes affixed to them.
- To generate a schema (unless you prefer to write your own), open the sample XML file in Visual Studio, and select the XML -> Create Schema menu option. Save that XSD.
- To generate the classes, run the XSD command from the VS command prompt. If you run it without parameters, it'll show you the command-line parameters you can use.
- Now you can create a type-safe XML serializer.
精彩评论