views:

1014

answers:

2

Hi

I made an xml document by using XML Serialization.

It looks like this

<?xml version="1.0" encoding="utf-8"?>
<Course xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <courseName>Comp 1510</courseName>
  <backgroundColor>#ffffff</backgroundColor>
  <fontColor>#ffffff</fontColor>
  <sharingKey>ed35d1f8-6be1-4f87-b77f-c70298e5abbb</sharingKey>
  <task type="Assignment">
    <taskName>First Task</taskName>
    <description>description</description>
    <taskDueDate>2010-01-24T12:41:20.0321826-08:00</taskDueDate>
    <weight xsi:nil="true" />
    <beforeDueDateNotification>30</beforeDueDateNotification>
    <outOf>50.4</outOf>
  </task>
</Course>

My Code to make this

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;

namespace ConsoleApplication1
{
    [XmlRoot("Course")]
    public class MyWrapper 
    {
        public MyWrapper()
        {
            TaskList = new List<Tasks>();
        }

        [XmlElement("courseName")]
        public string CourseName { get; set; }

        [XmlElement("backgroundColor")]
        public string BackgroundColor { get; set; }

        [XmlElement("fontColor")]
        public string  FontColor { get; set; }

        [XmlElement("sharingKey")]
        public Guid SharingKey { get; set; }

        [XmlElement("task")]
        public List<Tasks> TaskList { get; set; }

    }

public class Tasks
{
    [XmlAttribute("type")]
    public string Type { get; set; }

    [XmlElement("taskName")]
    public string TaskName { get; set; }

    [XmlElement("description")]
    public string Description { get; set; }

    [XmlElement("taskDueDate")]
    public DateTime TaskDueDate { get; set; }

    [XmlElement("weight")]
    public decimal? Weight { get; set; }

    [XmlElement("beforeDueDateNotification")]
    public int BeforeDueDateNotification { get; set; }

    [XmlElement("outOf")]
    public decimal? OutOf { get; set; }

}

}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {

            MyWrapper wrap = new MyWrapper();
            wrap.CourseName = "Comp 1510";
            wrap.FontColor = "#ffffff";
            wrap.BackgroundColor = "#ffffff";
            wrap.SharingKey = Guid.NewGuid();

            Tasks task = new Tasks()
            {
                TaskName = "First Task",
                Type = "Assignment",
                TaskDueDate = DateTime.Now,
                Description = "description",
                BeforeDueDateNotification = 30,
                OutOf = 50.4M
            };

            wrap.TaskList.Add(task);
            SerializeToXML(wrap);

           var grab = DeserializeFromXML();

           foreach (var item in grab)
           {

           }
        }

        static public void SerializeToXML(MyWrapper list)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(MyWrapper));
            TextWriter textWriter = new StreamWriter(@"C:\New folder\test.xml");
            serializer.Serialize(textWriter, list);
            textWriter.Close();
        }

        static List<MyWrapper> DeserializeFromXML()
        {
            XmlSerializer deserializer = new XmlSerializer(typeof(List<MyWrapper>));
            TextReader textReader = new StreamReader(@"C:\New folder\test.xml");
            List<MyWrapper> tasks;
            tasks = (List<MyWrapper>)deserializer.Deserialize(textReader);
            textReader.Close();

            return tasks;
        }
    }
}

Now when I try to de serialize it I get this error

System.InvalidOperationException was unhandled
  Message="There is an error in XML document (2, 2)."
  Source="System.Xml"
  StackTrace:
       at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
       at System.Xml.Serialization.XmlSerializer.Deserialize(TextReader textReader)
       at ConsoleApplication1.Program.DeserializeFromXML() in C:\Users\chobo2\Desktop\ConsoleApplication1\ConsoleApplication1\Program.cs:line 55
       at ConsoleApplication1.Program.Main(String[] args) in C:\Users\chobo2\Desktop\ConsoleApplication1\ConsoleApplication1\Program.cs:line 34
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: System.InvalidOperationException
       Message="<Course xmlns=''> was not expected."
       Source="ap72r7cf"
       StackTrace:
            at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderList1.Read5_ArrayOfMyWrapper()
       InnerException: 

I am not sure why this is happening.

Some Side Questions - Answer please after main problem is answered

I did not want to make a new forum post for these 2 questions unless I have to.

  1. Why is it important to give it an object type? Like why not make all the fields as strings?

        [XmlElement("sharingKey")]
        public Guid SharingKey { get; set; }
    

Is it just for when you de serialize that you will get in this case a Guid so that you won't later one have to convert it from a string to a Guid?

If this is correct how about if you get an xml file from someone else and you want to de serialize it how will you know what objects will come out of it? Like for instance how would you know that my "OutOf" is actually a type of nullable decimal? In fact how does C# know that? I don't see anything that would tip it off that this is the type.

  1. When I get it to actually de serialize, I am wondering how do I make my foreach loop. Since I want to go through each of the list of "MyWrapper" objects. But in MyWrapper there is a collection of Task objects. So do I have to make a for loop inside my foreach loop to get at it? Or is there a better way?

Thanks

+1  A: 

Well I guess the problem is: you're serializing a single MyWrapper, but trying to deserialize a List<MyWrapper>

That's not going to work - you serialize a single object into your file, you'll get back a single object MyWrapper when deserializing from that file.

Change your deserialization to:

    static MyWrapper DeserializeFromXML()
    {
        XmlSerializer deserializer = new XmlSerializer(typeof(MyWrapper));
        TextReader textReader = new StreamReader(@"C:\New folder\test.xml");
        MyWrapper tasks = (MyWrapper)deserializer.Deserialize(textReader);
        textReader.Close();
        return tasks;
    }

and things should work again.

marc_s
Yep that seems to done the trick. Do you know anything about my other 2 questions?
chobo2
+1  A: 

You're trying to serialize a single instance of MyWrapper, but then deserialize it as a list of them. If you stick to one way or the other (either way) it works fine. For example:

static public void SerializeToXML(MyWrapper wrapper)
{
    XmlSerializer serializer = new XmlSerializer(typeof(List<MyWrapper>));
    using (TextWriter textWriter = File.CreateText("test.xml"))
    {
        // Create single-element list
        serializer.Serialize(textWriter, new List<MyWrapper>{wrapper});
    }
}

static List<MyWrapper> DeserializeFromXML()
{
    XmlSerializer deserializer = new XmlSerializer(typeof(List<MyWrapper>));
    using (TextReader textReader = File.OpenText("test.xml"))
    {
        return (List<MyWrapper>)deserializer.Deserialize(textReader);
    }
}

or (for a single element):

static public void SerializeToXML(MyWrapper wrapper)
{
    XmlSerializer serializer = new XmlSerializer(typeof(MyWrapper));
    using (TextWriter textWriter = File.CreateText("test.xml"))
    {
        serializer.Serialize(textWriter, wrapper);
    }
}

static MyWrapper DeserializeFromXML()
{
    XmlSerializer deserializer = new XmlSerializer(typeof(MyWrapper));
    using (TextReader textReader = File.OpenText("test.xml"))
    {
        return (MyWrapper)deserializer.Deserialize(textReader);
    }
}

You've just got to be consistent, that's all.

Jon Skeet
Yep. I just copied in pasted from the tutorial I was working from and guess forgot they did not have a wrapper class like that I am using.
chobo2